mirror of
https://github.com/actions/deploy-pages.git
synced 2025-12-08 16:16:16 +00:00
enforce a max timeout
This commit is contained in:
@@ -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: 73.52%"><title>Coverage: 73.52%</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">73.52%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">73.52%</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: 76.32%"><title>Coverage: 76.32%</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">76.32%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">76.32%</text></g></svg>
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
28
dist/index.js
generated
vendored
28
dist/index.js
generated
vendored
@@ -10041,6 +10041,8 @@ class Deployment {
|
|||||||
this.githubServerUrl = context.githubServerUrl
|
this.githubServerUrl = context.githubServerUrl
|
||||||
this.artifactName = context.artifactName
|
this.artifactName = context.artifactName
|
||||||
this.isPreview = context.isPreview === true
|
this.isPreview = context.isPreview === true
|
||||||
|
this.timeout = maxTimeout
|
||||||
|
this.startTime = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
||||||
@@ -10052,6 +10054,9 @@ class Deployment {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let timeoutInput = Number(core.getInput('timeout'))
|
||||||
|
this.timeout = timeoutInput <= 0 ? maxTimeout : Math.min(timeoutInput, maxTimeout)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
core.debug(`Actor: ${this.buildActor}`)
|
core.debug(`Actor: ${this.buildActor}`)
|
||||||
core.debug(`Action ID: ${this.actionsId}`)
|
core.debug(`Action ID: ${this.actionsId}`)
|
||||||
@@ -10077,6 +10082,7 @@ class Deployment {
|
|||||||
id: deployment.id || deployment.status_url?.split('/')?.pop() || this.buildVersion,
|
id: deployment.id || deployment.status_url?.split('/')?.pop() || this.buildVersion,
|
||||||
pending: true
|
pending: true
|
||||||
}
|
}
|
||||||
|
this.startTime = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
core.info(`Created deployment for ${this.buildVersion}, ID: ${this.deploymentInfo?.id}`)
|
core.info(`Created deployment for ${this.buildVersion}, ID: ${this.deploymentInfo?.id}`)
|
||||||
@@ -10125,11 +10131,9 @@ class Deployment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deploymentId = this.deploymentInfo.id || this.buildVersion
|
const deploymentId = this.deploymentInfo.id || this.buildVersion
|
||||||
const timeout = Number(core.getInput('timeout'))
|
|
||||||
const reportingInterval = Number(core.getInput('reporting_interval'))
|
const reportingInterval = Number(core.getInput('reporting_interval'))
|
||||||
const maxErrorCount = Number(core.getInput('error_count'))
|
const maxErrorCount = Number(core.getInput('error_count'))
|
||||||
|
|
||||||
let startTime = Date.now()
|
|
||||||
let errorCount = 0
|
let errorCount = 0
|
||||||
|
|
||||||
// Time in milliseconds between two deployment status report when status errored, default 0.
|
// Time in milliseconds between two deployment status report when status errored, default 0.
|
||||||
@@ -10139,6 +10143,16 @@ class Deployment {
|
|||||||
|
|
||||||
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
||||||
while (true) {
|
while (true) {
|
||||||
|
// Handle timeout
|
||||||
|
if (Date.now() - this.startTime >= this.timeout) {
|
||||||
|
core.error('Timeout reached, aborting!')
|
||||||
|
core.setFailed('Timeout reached, aborting!')
|
||||||
|
|
||||||
|
// Explicitly cancel the deployment
|
||||||
|
await this.cancel()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Handle reporting interval
|
// Handle reporting interval
|
||||||
await new Promise(resolve => setTimeout(resolve, reportingInterval + errorReportingInterval))
|
await new Promise(resolve => setTimeout(resolve, reportingInterval + errorReportingInterval))
|
||||||
|
|
||||||
@@ -10195,16 +10209,6 @@ class Deployment {
|
|||||||
await this.cancel()
|
await this.cancel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle timeout
|
|
||||||
if (Date.now() - startTime >= timeout) {
|
|
||||||
core.error('Timeout reached, aborting!')
|
|
||||||
core.setFailed('Timeout reached, aborting!')
|
|
||||||
|
|
||||||
// Explicitly cancel the deployment
|
|
||||||
await this.cancel()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -384,6 +384,201 @@ describe('Deployment', () => {
|
|||||||
artifactExchangeScope.done()
|
artifactExchangeScope.done()
|
||||||
createDeploymentScope.done()
|
createDeploymentScope.done()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('enforces max timeout', async () => {
|
||||||
|
process.env.GITHUB_SHA = 'valid-build-version'
|
||||||
|
|
||||||
|
const artifactExchangeScope = nock(`http://my-url`)
|
||||||
|
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
|
||||||
|
.reply(200, {
|
||||||
|
value: [
|
||||||
|
{ url: 'https://another-artifact.com', name: 'another-artifact' },
|
||||||
|
{ url: 'https://fake-artifact.com', name: 'github-pages' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
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 cancelDeploymentScope = nock('https://api.github.com')
|
||||||
|
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`)
|
||||||
|
.reply(200, {})
|
||||||
|
|
||||||
|
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
|
||||||
|
|
||||||
|
// Set timeout to great than max
|
||||||
|
jest.spyOn(core, 'getInput').mockImplementation(param => {
|
||||||
|
switch (param) {
|
||||||
|
case 'artifact_name':
|
||||||
|
return 'github-pages'
|
||||||
|
case 'token':
|
||||||
|
return process.env.GITHUB_TOKEN
|
||||||
|
case 'timeout':
|
||||||
|
return maxTimeout + 1
|
||||||
|
default:
|
||||||
|
return process.env[`INPUT_${param.toUpperCase()}`] || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
const mockStartTime = now - maxTimeout
|
||||||
|
jest
|
||||||
|
.spyOn(Date, 'now')
|
||||||
|
.mockImplementationOnce(() => mockStartTime)
|
||||||
|
.mockImplementationOnce(() => now)
|
||||||
|
|
||||||
|
// Create the deployment
|
||||||
|
const deployment = new Deployment()
|
||||||
|
await deployment.create(fakeJwt)
|
||||||
|
await deployment.check()
|
||||||
|
|
||||||
|
expect(deployment.timeout).toEqual(maxTimeout)
|
||||||
|
expect(core.error).toBeCalledWith('Timeout reached, aborting!')
|
||||||
|
expect(core.setFailed).toBeCalledWith('Timeout reached, aborting!')
|
||||||
|
|
||||||
|
artifactExchangeScope.done()
|
||||||
|
createDeploymentScope.done()
|
||||||
|
cancelDeploymentScope.done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets timeout to user timeout if user timeout is less than max timeout', async () => {
|
||||||
|
process.env.GITHUB_SHA = 'valid-build-version'
|
||||||
|
|
||||||
|
const artifactExchangeScope = nock(`http://my-url`)
|
||||||
|
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
|
||||||
|
.reply(200, {
|
||||||
|
value: [
|
||||||
|
{ url: 'https://another-artifact.com', name: 'another-artifact' },
|
||||||
|
{ url: 'https://fake-artifact.com', name: 'github-pages' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
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 cancelDeploymentScope = nock('https://api.github.com')
|
||||||
|
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`)
|
||||||
|
.reply(200, {})
|
||||||
|
|
||||||
|
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
|
||||||
|
|
||||||
|
// Set timeout to great than max
|
||||||
|
jest.spyOn(core, 'getInput').mockImplementation(param => {
|
||||||
|
switch (param) {
|
||||||
|
case 'artifact_name':
|
||||||
|
return 'github-pages'
|
||||||
|
case 'token':
|
||||||
|
return process.env.GITHUB_TOKEN
|
||||||
|
case 'timeout':
|
||||||
|
return 42
|
||||||
|
default:
|
||||||
|
return process.env[`INPUT_${param.toUpperCase()}`] || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
const mockStartTime = now - 42
|
||||||
|
jest
|
||||||
|
.spyOn(Date, 'now')
|
||||||
|
.mockImplementationOnce(() => mockStartTime)
|
||||||
|
.mockImplementationOnce(() => now)
|
||||||
|
|
||||||
|
// Create the deployment
|
||||||
|
const deployment = new Deployment()
|
||||||
|
await deployment.create(fakeJwt)
|
||||||
|
await deployment.check()
|
||||||
|
|
||||||
|
expect(deployment.timeout).toEqual(42)
|
||||||
|
expect(core.error).toBeCalledWith('Timeout reached, aborting!')
|
||||||
|
expect(core.setFailed).toBeCalledWith('Timeout reached, aborting!')
|
||||||
|
|
||||||
|
artifactExchangeScope.done()
|
||||||
|
createDeploymentScope.done()
|
||||||
|
cancelDeploymentScope.done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets output to success when timeout is set but not reached', async () => {
|
||||||
|
process.env.GITHUB_SHA = 'valid-build-version'
|
||||||
|
|
||||||
|
const artifactExchangeScope = nock(`http://my-url`)
|
||||||
|
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
|
||||||
|
.reply(200, {
|
||||||
|
value: [
|
||||||
|
{ url: 'https://another-artifact.com', name: 'another-artifact' },
|
||||||
|
{ url: 'https://fake-artifact.com', name: 'github-pages' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
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 deploymentStatusScope = nock('https://api.github.com')
|
||||||
|
.get(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`)
|
||||||
|
.reply(200, {
|
||||||
|
status: 'succeed'
|
||||||
|
})
|
||||||
|
|
||||||
|
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
|
||||||
|
|
||||||
|
// Set timeout to great than max
|
||||||
|
jest.spyOn(core, 'getInput').mockImplementation(param => {
|
||||||
|
switch (param) {
|
||||||
|
case 'artifact_name':
|
||||||
|
return 'github-pages'
|
||||||
|
case 'token':
|
||||||
|
return process.env.GITHUB_TOKEN
|
||||||
|
case 'timeout':
|
||||||
|
return 42
|
||||||
|
default:
|
||||||
|
return process.env[`INPUT_${param.toUpperCase()}`] || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
const mockStartTime = now
|
||||||
|
jest
|
||||||
|
.spyOn(Date, 'now')
|
||||||
|
.mockImplementationOnce(() => mockStartTime)
|
||||||
|
.mockImplementationOnce(() => now)
|
||||||
|
|
||||||
|
// Create the deployment
|
||||||
|
const deployment = new Deployment()
|
||||||
|
await deployment.create(fakeJwt)
|
||||||
|
await deployment.check()
|
||||||
|
|
||||||
|
expect(deployment.timeout).toEqual(42)
|
||||||
|
expect(core.error).not.toBeCalled()
|
||||||
|
expect(core.setOutput).toBeCalledWith('status', 'succeed')
|
||||||
|
expect(core.info).toHaveBeenLastCalledWith('Reported success!')
|
||||||
|
|
||||||
|
artifactExchangeScope.done()
|
||||||
|
createDeploymentScope.done()
|
||||||
|
deploymentStatusScope.done()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#cancel', () => {
|
describe('#cancel', () => {
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ class Deployment {
|
|||||||
this.githubServerUrl = context.githubServerUrl
|
this.githubServerUrl = context.githubServerUrl
|
||||||
this.artifactName = context.artifactName
|
this.artifactName = context.artifactName
|
||||||
this.isPreview = context.isPreview === true
|
this.isPreview = context.isPreview === true
|
||||||
|
this.timeout = maxTimeout
|
||||||
|
this.startTime = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
||||||
@@ -52,6 +54,9 @@ class Deployment {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let timeoutInput = Number(core.getInput('timeout'))
|
||||||
|
this.timeout = timeoutInput <= 0 ? maxTimeout : Math.min(timeoutInput, maxTimeout)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
core.debug(`Actor: ${this.buildActor}`)
|
core.debug(`Actor: ${this.buildActor}`)
|
||||||
core.debug(`Action ID: ${this.actionsId}`)
|
core.debug(`Action ID: ${this.actionsId}`)
|
||||||
@@ -77,6 +82,7 @@ class Deployment {
|
|||||||
id: deployment.id || deployment.status_url?.split('/')?.pop() || this.buildVersion,
|
id: deployment.id || deployment.status_url?.split('/')?.pop() || this.buildVersion,
|
||||||
pending: true
|
pending: true
|
||||||
}
|
}
|
||||||
|
this.startTime = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
core.info(`Created deployment for ${this.buildVersion}, ID: ${this.deploymentInfo?.id}`)
|
core.info(`Created deployment for ${this.buildVersion}, ID: ${this.deploymentInfo?.id}`)
|
||||||
@@ -125,11 +131,9 @@ class Deployment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deploymentId = this.deploymentInfo.id || this.buildVersion
|
const deploymentId = this.deploymentInfo.id || this.buildVersion
|
||||||
const timeout = Number(core.getInput('timeout'))
|
|
||||||
const reportingInterval = Number(core.getInput('reporting_interval'))
|
const reportingInterval = Number(core.getInput('reporting_interval'))
|
||||||
const maxErrorCount = Number(core.getInput('error_count'))
|
const maxErrorCount = Number(core.getInput('error_count'))
|
||||||
|
|
||||||
let startTime = Date.now()
|
|
||||||
let errorCount = 0
|
let errorCount = 0
|
||||||
|
|
||||||
// Time in milliseconds between two deployment status report when status errored, default 0.
|
// Time in milliseconds between two deployment status report when status errored, default 0.
|
||||||
@@ -139,6 +143,16 @@ class Deployment {
|
|||||||
|
|
||||||
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
||||||
while (true) {
|
while (true) {
|
||||||
|
// Handle timeout
|
||||||
|
if (Date.now() - this.startTime >= this.timeout) {
|
||||||
|
core.error('Timeout reached, aborting!')
|
||||||
|
core.setFailed('Timeout reached, aborting!')
|
||||||
|
|
||||||
|
// Explicitly cancel the deployment
|
||||||
|
await this.cancel()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Handle reporting interval
|
// Handle reporting interval
|
||||||
await new Promise(resolve => setTimeout(resolve, reportingInterval + errorReportingInterval))
|
await new Promise(resolve => setTimeout(resolve, reportingInterval + errorReportingInterval))
|
||||||
|
|
||||||
@@ -195,16 +209,6 @@ class Deployment {
|
|||||||
await this.cancel()
|
await this.cancel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle timeout
|
|
||||||
if (Date.now() - startTime >= timeout) {
|
|
||||||
core.error('Timeout reached, aborting!')
|
|
||||||
core.setFailed('Timeout reached, aborting!')
|
|
||||||
|
|
||||||
// Explicitly cancel the deployment
|
|
||||||
await this.cancel()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user