Check artifact size and warn if too large

This commit is contained in:
Greta Parks
2023-05-22 17:00:13 +00:00
parent b580d214b4
commit 2fb2bbeb02
6 changed files with 94 additions and 19 deletions

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 78.94%"><title>Coverage: 78.94%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#e05d44"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">78.94%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">78.94%</text></g></svg> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 79.72%"><title>Coverage: 79.72%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#e05d44"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">79.72%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">79.72%</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

34
dist/index.js generated vendored
View File

@@ -9840,7 +9840,7 @@ async function processRuntimeResponse(res, requestOptions) {
return response return response
} }
async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName }) { async function getSignedArtifactMetadata({ runtimeToken, workflowRunId, artifactName }) {
const { runTimeUrl: RUNTIME_URL } = getContext() const { runTimeUrl: RUNTIME_URL } = getContext()
const artifactExchangeUrl = `${RUNTIME_URL}_apis/pipelines/workflows/${workflowRunId}/artifacts?api-version=6.0-preview` const artifactExchangeUrl = `${RUNTIME_URL}_apis/pipelines/workflows/${workflowRunId}/artifacts?api-version=6.0-preview`
@@ -9874,7 +9874,8 @@ async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName
throw error throw error
} }
const artifactRawUrl = data?.value?.find(artifact => artifact.name === artifactName)?.url const artifact = data?.value?.find(artifact => artifact.name === artifactName)
const artifactRawUrl = artifact?.url
if (!artifactRawUrl) { if (!artifactRawUrl) {
throw new Error( throw new Error(
'No uploaded artifact was found! Please check if there are any errors at build step, or uploaded artifact name is correct.' 'No uploaded artifact was found! Please check if there are any errors at build step, or uploaded artifact name is correct.'
@@ -9882,7 +9883,16 @@ async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName
} }
const signedArtifactUrl = `${artifactRawUrl}&%24expand=SignedContent` const signedArtifactUrl = `${artifactRawUrl}&%24expand=SignedContent`
return signedArtifactUrl
const artifactSize = artifact?.size
if (!artifactSize) {
core.warning('Artifact size was not found. Can not check if artifact size exceeds the allowed size.')
}
return {
url: signedArtifactUrl,
size: artifactSize
}
} }
async function createPagesDeployment({ githubToken, artifactUrl, buildVersion, idToken, isPreview = false }) { async function createPagesDeployment({ githubToken, artifactUrl, buildVersion, idToken, isPreview = false }) {
@@ -9949,7 +9959,7 @@ async function cancelPagesDeployment({ githubToken, deploymentId }) {
} }
module.exports = { module.exports = {
getSignedArtifactUrl, getSignedArtifactMetadata,
createPagesDeployment, createPagesDeployment,
getPagesDeploymentStatus, getPagesDeploymentStatus,
cancelPagesDeployment cancelPagesDeployment
@@ -10003,7 +10013,7 @@ const core = __nccwpck_require__(2186)
// All variables we need from the runtime are loaded here // All variables we need from the runtime are loaded here
const getContext = __nccwpck_require__(8454) const getContext = __nccwpck_require__(8454)
const { const {
getSignedArtifactUrl, getSignedArtifactMetadata,
createPagesDeployment, createPagesDeployment,
getPagesDeploymentStatus, getPagesDeploymentStatus,
cancelPagesDeployment cancelPagesDeployment
@@ -10024,6 +10034,8 @@ const finalErrorStatus = {
} }
const MAX_TIMEOUT = 600000 const MAX_TIMEOUT = 600000
const ONE_GIGABYTE = 1073741824
const SIZE_LIMIT_DESCRIPTION = '1 GB'
class Deployment { class Deployment {
constructor() { constructor() {
@@ -10062,15 +10074,21 @@ class Deployment {
core.debug(`Action ID: ${this.actionsId}`) core.debug(`Action ID: ${this.actionsId}`)
core.debug(`Actions Workflow Run ID: ${this.workflowRun}`) core.debug(`Actions Workflow Run ID: ${this.workflowRun}`)
const artifactUrl = await getSignedArtifactUrl({ const artifactData = await getSignedArtifactMetadata({
runtimeToken: this.runTimeToken, runtimeToken: this.runTimeToken,
workflowRunId: this.workflowRun, workflowRunId: this.workflowRun,
artifactName: this.artifactName artifactName: this.artifactName
}) })
if (artifactData?.size > ONE_GIGABYTE) {
core.warning(
`Uploaded artifact size of ${artifactData?.size} bytes exceeds the allowed size of ${SIZE_LIMIT_DESCRIPTION}. Deployment might fail.`
)
}
const deployment = await createPagesDeployment({ const deployment = await createPagesDeployment({
githubToken: this.githubToken, githubToken: this.githubToken,
artifactUrl, artifactUrl: artifactData.url,
buildVersion: this.buildVersion, buildVersion: this.buildVersion,
idToken, idToken,
isPreview: this.isPreview isPreview: this.isPreview
@@ -10243,7 +10261,7 @@ class Deployment {
} }
} }
module.exports = { Deployment, MAX_TIMEOUT } module.exports = { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION }
/***/ }), /***/ }),

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
const core = require('@actions/core') const core = require('@actions/core')
const nock = require('nock') const nock = require('nock')
const { Deployment, MAX_TIMEOUT } = require('../../internal/deployment') const { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION } = require('../../internal/deployment')
const fakeJwt = const fakeJwt =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w' 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w'
@@ -248,6 +248,45 @@ describe('Deployment', () => {
createDeploymentScope.done() createDeploymentScope.done()
}) })
it('warns if the artifact size is bigger than maximum', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactSize = ONE_GIGABYTE + 1
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
.reply(200, {
value: [
{ url: 'https://fake-artifact.com', name: 'github-pages', size: `${artifactSize}` },
{ url: 'https://another-artifact.com', name: 'another-artifact' }
]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://fake-artifact.com&%24expand=SignedContent',
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
.reply(200, {
status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`,
page_url: 'https://actions.github.io/is-awesome'
})
const deployment = new Deployment()
await deployment.create(fakeJwt)
expect(core.warning).toBeCalledWith(
`Uploaded artifact size of ${artifactSize} bytes exceeds the allowed size of ${SIZE_LIMIT_DESCRIPTION}. Deployment might fail.`
)
expect(core.setFailed).not.toHaveBeenCalled()
expect(core.info).toHaveBeenLastCalledWith(
expect.stringMatching(new RegExp(`^Created deployment for ${process.env.GITHUB_SHA}`))
)
artifactExchangeScope.done()
createDeploymentScope.done()
})
it('warns when the timeout is greater than the maximum allowed', async () => { it('warns when the timeout is greater than the maximum allowed', async () => {
process.env.GITHUB_SHA = 'valid-build-version' process.env.GITHUB_SHA = 'valid-build-version'

View File

@@ -54,7 +54,7 @@ async function processRuntimeResponse(res, requestOptions) {
return response return response
} }
async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName }) { async function getSignedArtifactMetadata({ runtimeToken, workflowRunId, artifactName }) {
const { runTimeUrl: RUNTIME_URL } = getContext() const { runTimeUrl: RUNTIME_URL } = getContext()
const artifactExchangeUrl = `${RUNTIME_URL}_apis/pipelines/workflows/${workflowRunId}/artifacts?api-version=6.0-preview` const artifactExchangeUrl = `${RUNTIME_URL}_apis/pipelines/workflows/${workflowRunId}/artifacts?api-version=6.0-preview`
@@ -88,7 +88,8 @@ async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName
throw error throw error
} }
const artifactRawUrl = data?.value?.find(artifact => artifact.name === artifactName)?.url const artifact = data?.value?.find(artifact => artifact.name === artifactName)
const artifactRawUrl = artifact?.url
if (!artifactRawUrl) { if (!artifactRawUrl) {
throw new Error( throw new Error(
'No uploaded artifact was found! Please check if there are any errors at build step, or uploaded artifact name is correct.' 'No uploaded artifact was found! Please check if there are any errors at build step, or uploaded artifact name is correct.'
@@ -96,7 +97,16 @@ async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName
} }
const signedArtifactUrl = `${artifactRawUrl}&%24expand=SignedContent` const signedArtifactUrl = `${artifactRawUrl}&%24expand=SignedContent`
return signedArtifactUrl
const artifactSize = artifact?.size
if (!artifactSize) {
core.warning('Artifact size was not found. Can not check if artifact size exceeds the allowed size.')
}
return {
url: signedArtifactUrl,
size: artifactSize
}
} }
async function createPagesDeployment({ githubToken, artifactUrl, buildVersion, idToken, isPreview = false }) { async function createPagesDeployment({ githubToken, artifactUrl, buildVersion, idToken, isPreview = false }) {
@@ -163,7 +173,7 @@ async function cancelPagesDeployment({ githubToken, deploymentId }) {
} }
module.exports = { module.exports = {
getSignedArtifactUrl, getSignedArtifactMetadata,
createPagesDeployment, createPagesDeployment,
getPagesDeploymentStatus, getPagesDeploymentStatus,
cancelPagesDeployment cancelPagesDeployment

View File

@@ -3,7 +3,7 @@ const core = require('@actions/core')
// All variables we need from the runtime are loaded here // All variables we need from the runtime are loaded here
const getContext = require('./context') const getContext = require('./context')
const { const {
getSignedArtifactUrl, getSignedArtifactMetadata,
createPagesDeployment, createPagesDeployment,
getPagesDeploymentStatus, getPagesDeploymentStatus,
cancelPagesDeployment cancelPagesDeployment
@@ -24,6 +24,8 @@ const finalErrorStatus = {
} }
const MAX_TIMEOUT = 600000 const MAX_TIMEOUT = 600000
const ONE_GIGABYTE = 1073741824
const SIZE_LIMIT_DESCRIPTION = '1 GB'
class Deployment { class Deployment {
constructor() { constructor() {
@@ -62,15 +64,21 @@ class Deployment {
core.debug(`Action ID: ${this.actionsId}`) core.debug(`Action ID: ${this.actionsId}`)
core.debug(`Actions Workflow Run ID: ${this.workflowRun}`) core.debug(`Actions Workflow Run ID: ${this.workflowRun}`)
const artifactUrl = await getSignedArtifactUrl({ const artifactData = await getSignedArtifactMetadata({
runtimeToken: this.runTimeToken, runtimeToken: this.runTimeToken,
workflowRunId: this.workflowRun, workflowRunId: this.workflowRun,
artifactName: this.artifactName artifactName: this.artifactName
}) })
if (artifactData?.size > ONE_GIGABYTE) {
core.warning(
`Uploaded artifact size of ${artifactData?.size} bytes exceeds the allowed size of ${SIZE_LIMIT_DESCRIPTION}. Deployment might fail.`
)
}
const deployment = await createPagesDeployment({ const deployment = await createPagesDeployment({
githubToken: this.githubToken, githubToken: this.githubToken,
artifactUrl, artifactUrl: artifactData.url,
buildVersion: this.buildVersion, buildVersion: this.buildVersion,
idToken, idToken,
isPreview: this.isPreview isPreview: this.isPreview
@@ -243,4 +251,4 @@ class Deployment {
} }
} }
module.exports = { Deployment, MAX_TIMEOUT } module.exports = { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION }