Wrap Twirp responses like Octokit responses for consistency

This commit is contained in:
James M. Greene
2023-12-22 11:40:57 -06:00
parent c704b8a6e2
commit 72ab98158a
4 changed files with 88 additions and 20 deletions

9
package-lock.json generated
View File

@@ -11,7 +11,9 @@
"dependencies": {
"@actions/artifact": "^2.0.0",
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0"
"@actions/github": "^6.0.0",
"@octokit/request-error": "^5.0.1",
"http-status-messages": "^1.1.0"
},
"devDependencies": {
"@vercel/ncc": "^0.38.1",
@@ -4670,6 +4672,11 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
"node_modules/http-status-messages": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/http-status-messages/-/http-status-messages-1.1.0.tgz",
"integrity": "sha512-zq9mKkNX6w6qYtNE0aAiH+urvEenUUIyoq8eAWQh2prhA5o03NETCOm/D2GIVt/qCFItt+23Sm1E7HyelPvi6w=="
},
"node_modules/human-signals": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",

View File

@@ -6,7 +6,9 @@
"dependencies": {
"@actions/artifact": "^2.0.0",
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0"
"@actions/github": "^6.0.0",
"@octokit/request-error": "^5.0.1",
"http-status-messages": "^1.1.0"
},
"devDependencies": {
"@vercel/ncc": "^0.38.1",

View File

@@ -1,16 +1,80 @@
const core = require('@actions/core')
const github = require('@actions/github')
const { DefaultArtifactClient } = require('@actions/artifact')
const { RequestError } = require('@octokit/request-error')
const HttpStatusMessages = require('http-status-messages')
function wrapTwirpResponseLikeOctokit(twirpResponse, requestOptions) {
// Specific response shape aligned with Octokit
const response = {
url: requestOptions.url,
status: 200,
headers: {
...requestOptions.headers
},
data: twirpResponse
}
return response
}
// Mimic the errors thrown by Octokit for consistency.
function wrapTwirpErrorLikeOctokit(twirpError, requestOptions) {
const rawErrorMsg = twirpError?.message || twirpError?.toString() || ''
const statusCodeMatch = rawErrorMsg.match(/Failed request: \((?<statusCode>\d+)\)/)
const statusCode = statusCodeMatch?.groups?.statusCode ?? 500
// Try to provide the best error message
const errorMsg =
rawErrorMsg ||
// Fallback to the HTTP status message based on the status code
HttpStatusMessages[statusCode] ||
// Or if the status code is unexpected...
`Unknown error (${statusCode})`
// RequestError is an Octokit-specific class
return new RequestError(errorMsg, statusCode, {
response: {
url: requestOptions.url,
status: statusCode,
headers: {
...requestOptions.headers
},
data: rawErrorMsg ? { message: rawErrorMsg } : ''
},
request: requestOptions
})
}
function getArtifactsServiceOrigin() {
const resultsUrl = process.env.ACTIONS_RESULTS_URL
return resultsUrl ? new URL(resultsUrl).origin : ''
}
async function getArtifactMetadata({ artifactName }) {
const artifactClient = new DefaultArtifactClient()
// Primarily for debugging purposes, accuracy is not critical
const requestOptions = {
method: 'POST',
url: `${getArtifactsServiceOrigin()}/twirp/github.actions.results.api.v1.ArtifactService/ListArtifacts`,
headers: {
'content-type': 'application/json'
}
}
try {
core.info(`Fetching artifact metadata for ${artifactName} in this workflow run`)
const response = await artifactClient.listArtifacts()
let response
try {
const twirpResponse = await artifactClient.listArtifacts()
response = wrapTwirpResponseLikeOctokit(twirpResponse, requestOptions)
} catch (twirpError) {
const octokitError = wrapTwirpErrorLikeOctokit(twirpError, requestOptions)
throw octokitError
}
const filteredArtifacts = response.artifacts.filter(artifact => artifact.name === artifactName)
const filteredArtifacts = response.data.artifacts.filter(artifact => artifact.name === artifactName)
const artifactCount = filteredArtifacts.length
core.debug(`List artifact count: ${artifactCount}`)

View File

@@ -62,12 +62,8 @@ class Deployment {
core.debug(`Action ID: ${this.actionsId}`)
core.debug(`Actions Workflow Run ID: ${this.workflowRun}`)
let artifactData
try {
artifactData = await getArtifactMetadata({ artifactName: this.artifactName })
} catch (error) {
throw new Error(`Failed to create deployment: ${error.message}`)
}
const artifactData = await getArtifactMetadata({ artifactName: this.artifactName })
if (artifactData?.size > ONE_GIGABYTE) {
core.warning(
@@ -75,7 +71,6 @@ class Deployment {
)
}
try {
const deployment = await createPagesDeployment({
githubToken: this.githubToken,
artifactId: artifactData.id,
@@ -103,14 +98,14 @@ class Deployment {
// build customized error message based on server response
if (error.response) {
let errorMessage = `Failed to create deployment (status: ${error.status}) with build version ${this.buildVersion}. `
let errorMessage = `Failed to create deployment (status: ${error.status}) with build version ${this.buildVersion}.`
if (error.status === 400) {
errorMessage += `Responded with: ${error.message}`
errorMessage += ` Responded with: ${error.message}`
} else if (error.status === 403) {
errorMessage += 'Ensure GITHUB_TOKEN has permission "pages: write".'
errorMessage += ' Ensure GITHUB_TOKEN has permission "pages: write".'
} else if (error.status === 404) {
const pagesSettingsUrl = `${this.githubServerUrl}/${this.repositoryNwo}/settings/pages`
errorMessage += `Ensure GitHub Pages has been enabled: ${pagesSettingsUrl}`
errorMessage += ` Ensure GitHub Pages has been enabled: ${pagesSettingsUrl}`
// If using GHES, add a special note about compatibility
if (new URL(this.githubServerUrl).hostname.toLowerCase() !== 'github.com') {
errorMessage +=
@@ -118,7 +113,7 @@ class Deployment {
}
} else if (error.status >= 500) {
errorMessage +=
'Server error, is githubstatus.com reporting a Pages outage? Please re-run the deployment at a later time.'
' Server error, is githubstatus.com reporting a Pages outage? Please re-run the deployment at a later time.'
}
throw new Error(errorMessage)
} else {