Skip to content

Commit

Permalink
Merge pull request #124 from actions/actions-http-client
Browse files Browse the repository at this point in the history
Use the `@actions/http-client` and `@actions/github` modules for proxy support
  • Loading branch information
JamesMGreene authored Mar 9, 2023
2 parents 3adc03e + ce35ecd commit 497da40
Show file tree
Hide file tree
Showing 9 changed files with 8,267 additions and 7,914 deletions.
14,082 changes: 6,857 additions & 7,225 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

587 changes: 436 additions & 151 deletions dist/licenses.txt

Large diffs are not rendered by default.

634 changes: 430 additions & 204 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
"main": "./dist/index.js",
"dependencies": {
"@actions/core": "^1.10.0",
"axios": "^1.3.3",
"axios-retry": "^3.2.4"
"@actions/github": "^5.1.1",
"@actions/http-client": "^2.0.1",
"@octokit/request-error": "^3.0.3",
"http-status-messages": "^1.1.0"
},
"devDependencies": {
"@vercel/ncc": "^0.31.1",
Expand Down
170 changes: 170 additions & 0 deletions src/api-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
const core = require('@actions/core')
const github = require('@actions/github')
const hc = require('@actions/http-client')
const { RequestError } = require('@octokit/request-error')
const HttpStatusMessages = require('http-status-messages')

// All variables we need from the runtime are loaded here
const getContext = require('./context')

async function processRuntimeResponse(res, requestOptions) {
// Parse the response body as JSON
let obj = null
try {
const contents = await res.readBody()
if (contents && contents.length > 0) {
obj = JSON.parse(contents)
}
} catch (error) {
// Invalid resource (contents not json); leaving resulting obj as null
}

// Specific response shape aligned with Octokit
const response = {
url: res.message?.url || requestOptions.url,
status: res.message?.statusCode || 0,
headers: {
...res.message?.headers
},
data: obj
}

// Forcibly throw errors for negative HTTP status codes!
// @actions/http-client doesn't do this by default.
// Mimic the errors thrown by Octokit for consistency.
if (response.status >= 400) {
// Try to get an error message from the response body
const errorMsg =
(typeof response.data === 'string' && response.data) ||
response.data?.error ||
response.data?.message ||
// Try the Node HTTP IncomingMessage's statusMessage property
res.message?.statusMessage ||
// Fallback to the HTTP status message based on the status code
HttpStatusMessages[response.status] ||
// Or if the status code is unexpected...
`Unknown error (${response.status})`

throw new RequestError(errorMsg, response.status, {
response,
request: requestOptions
})
}

return response
}

async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName }) {
const { runTimeUrl: RUNTIME_URL } = getContext()
const artifactExchangeUrl = `${RUNTIME_URL}_apis/pipelines/workflows/${workflowRunId}/artifacts?api-version=6.0-preview`

const httpClient = new hc.HttpClient()
let data = null

try {
const requestHeaders = {
accept: 'application/json',
authorization: `Bearer ${runtimeToken}`
}
const requestOptions = {
method: 'GET',
url: artifactExchangeUrl,
headers: {
...requestHeaders
},
body: null
}

core.info(`Artifact exchange URL: ${artifactExchangeUrl}`)
const res = await httpClient.get(artifactExchangeUrl, requestHeaders)

// May throw a RequestError (HttpError)
const response = await processRuntimeResponse(res, requestOptions)

data = response.data
core.debug(JSON.stringify(data))
} catch (error) {
core.error('Getting signed artifact URL failed', error)
throw error
}

const artifactRawUrl = data?.value?.find(artifact => artifact.name === artifactName)?.url
if (!artifactRawUrl) {
throw new Error(
'No uploaded artifact was found! Please check if there are any errors at build step, or uploaded artifact name is correct.'
)
}

const signedArtifactUrl = `${artifactRawUrl}&%24expand=SignedContent`
return signedArtifactUrl
}

async function createPagesDeployment({ githubToken, artifactUrl, buildVersion, idToken, isPreview = false }) {
const octokit = github.getOctokit(githubToken)

const payload = {
artifact_url: artifactUrl,
pages_build_version: buildVersion,
oidc_token: idToken
}
if (isPreview === true) {
payload.preview = true
}
core.info(`Creating Pages deployment with payload:\n${JSON.stringify(payload, null, '\t')}`)

try {
const response = await octokit.request('POST /repos/{owner}/{repo}/pages/deployment', {
owner: github.context.repo.owner,
repo: github.context.repo.repo,
...payload
})

return response.data
} catch (error) {
core.error('Creating Pages deployment failed', error)
throw error
}
}

async function getPagesDeploymentStatus({ githubToken, deploymentId }) {
const octokit = github.getOctokit(githubToken)

core.info('Getting Pages deployment status...')
try {
const response = await octokit.request('GET /repos/{owner}/{repo}/pages/deployment/status/{deploymentId}', {
owner: github.context.repo.owner,
repo: github.context.repo.repo,
deploymentId
})

return response.data
} catch (error) {
core.error('Getting Pages deployment status failed', error)
throw error
}
}

async function cancelPagesDeployment({ githubToken, deploymentId }) {
const octokit = github.getOctokit(githubToken)

core.info('Canceling Pages deployment...')
try {
const response = await octokit.request('PUT /repos/{owner}/{repo}/pages/deployment/cancel/{deploymentId}', {
owner: github.context.repo.owner,
repo: github.context.repo.repo,
deploymentId
})

return response.data
} catch (error) {
core.error('Canceling Pages deployment failed', error)
throw error
}
}

module.exports = {
getSignedArtifactUrl,
createPagesDeployment,
getPagesDeploymentStatus,
cancelPagesDeployment
}
Loading

0 comments on commit 497da40

Please sign in to comment.