mirror of
https://github.com/actions/deploy-pages.git
synced 2026-02-11 12:51:24 +00:00
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="110" height="20" role="img" aria-label="Coverage: 72.9%"><title>Coverage: 72.9%</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="110" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="47" height="20" fill="#e05d44"/><rect width="110" 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="855" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">72.9%</text><text x="855" y="140" transform="scale(.1)" fill="#fff" textLength="370">72.9%</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: 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>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
20
dist/index.js
generated
vendored
20
dist/index.js
generated
vendored
@@ -10023,6 +10023,8 @@ const finalErrorStatus = {
|
||||
deployment_lost: 'Deployment failed to report final status.'
|
||||
}
|
||||
|
||||
const MAX_TIMEOUT = 600000
|
||||
|
||||
class Deployment {
|
||||
constructor() {
|
||||
const context = getContext()
|
||||
@@ -10039,11 +10041,22 @@ class Deployment {
|
||||
this.githubServerUrl = context.githubServerUrl
|
||||
this.artifactName = context.artifactName
|
||||
this.isPreview = context.isPreview === true
|
||||
this.timeout = MAX_TIMEOUT
|
||||
this.startTime = null
|
||||
}
|
||||
|
||||
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
||||
// by creating a deployment with that artifact
|
||||
async create(idToken) {
|
||||
if (Number(core.getInput('timeout')) > MAX_TIMEOUT) {
|
||||
core.warning(
|
||||
`Warning: timeout value is greater than the allowed maximum - timeout set to the maximum of ${MAX_TIMEOUT} milliseconds.`
|
||||
)
|
||||
}
|
||||
|
||||
const timeoutInput = Number(core.getInput('timeout'))
|
||||
this.timeout = !timeoutInput || timeoutInput <= 0 ? MAX_TIMEOUT : Math.min(timeoutInput, MAX_TIMEOUT)
|
||||
|
||||
try {
|
||||
core.debug(`Actor: ${this.buildActor}`)
|
||||
core.debug(`Action ID: ${this.actionsId}`)
|
||||
@@ -10069,6 +10082,7 @@ class Deployment {
|
||||
id: deployment.id || deployment.status_url?.split('/')?.pop() || this.buildVersion,
|
||||
pending: true
|
||||
}
|
||||
this.startTime = Date.now()
|
||||
}
|
||||
|
||||
core.info(`Created deployment for ${this.buildVersion}, ID: ${this.deploymentInfo?.id}`)
|
||||
@@ -10122,11 +10136,9 @@ class Deployment {
|
||||
}
|
||||
|
||||
const deploymentId = this.deploymentInfo.id || this.buildVersion
|
||||
const timeout = Number(core.getInput('timeout'))
|
||||
const reportingInterval = Number(core.getInput('reporting_interval'))
|
||||
const maxErrorCount = Number(core.getInput('error_count'))
|
||||
|
||||
let startTime = Date.now()
|
||||
let errorCount = 0
|
||||
|
||||
// Time in milliseconds between two deployment status report when status errored, default 0.
|
||||
@@ -10194,7 +10206,7 @@ class Deployment {
|
||||
}
|
||||
|
||||
// Handle timeout
|
||||
if (Date.now() - startTime >= timeout) {
|
||||
if (Date.now() - this.startTime >= this.timeout) {
|
||||
core.error('Timeout reached, aborting!')
|
||||
core.setFailed('Timeout reached, aborting!')
|
||||
|
||||
@@ -10231,7 +10243,7 @@ class Deployment {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Deployment }
|
||||
module.exports = { Deployment, MAX_TIMEOUT }
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
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
@@ -1,7 +1,7 @@
|
||||
const core = require('@actions/core')
|
||||
const nock = require('nock')
|
||||
|
||||
const { Deployment } = require('../../internal/deployment')
|
||||
const { Deployment, MAX_TIMEOUT } = require('../../internal/deployment')
|
||||
|
||||
const fakeJwt =
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w'
|
||||
@@ -247,6 +247,55 @@ describe('Deployment', () => {
|
||||
artifactExchangeScope.done()
|
||||
createDeploymentScope.done()
|
||||
})
|
||||
|
||||
it('warns when the timeout is greater than the maximum allowed', 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'
|
||||
})
|
||||
|
||||
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
|
||||
|
||||
jest.spyOn(core, 'getInput').mockImplementation(param => {
|
||||
switch (param) {
|
||||
case 'artifact_name':
|
||||
return 'github-pages'
|
||||
case 'token':
|
||||
return process.env.GITHUB_TOKEN
|
||||
case 'timeout':
|
||||
return MAX_TIMEOUT + 1
|
||||
default:
|
||||
return process.env[`INPUT_${param.toUpperCase()}`] || ''
|
||||
}
|
||||
})
|
||||
|
||||
const deployment = new Deployment()
|
||||
await deployment.create(fakeJwt)
|
||||
|
||||
expect(core.warning).toBeCalledWith(
|
||||
`Warning: timeout value is greater than the allowed maximum - timeout set to the maximum of ${MAX_TIMEOUT} milliseconds.`
|
||||
)
|
||||
|
||||
artifactExchangeScope.done()
|
||||
createDeploymentScope.done()
|
||||
})
|
||||
})
|
||||
|
||||
describe('#check', () => {
|
||||
@@ -280,14 +329,6 @@ describe('Deployment', () => {
|
||||
})
|
||||
|
||||
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
|
||||
core.GetInput = jest.fn(input => {
|
||||
switch (input) {
|
||||
case 'timeout':
|
||||
return 10 * 1000
|
||||
case 'reporting_interval':
|
||||
return 0
|
||||
}
|
||||
})
|
||||
|
||||
// Create the deployment
|
||||
const deployment = new Deployment()
|
||||
@@ -333,14 +374,6 @@ describe('Deployment', () => {
|
||||
})
|
||||
|
||||
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
|
||||
core.GetInput = jest.fn(input => {
|
||||
switch (input) {
|
||||
case 'timeout':
|
||||
return 10 * 1000
|
||||
case 'reporting_interval':
|
||||
return 0
|
||||
}
|
||||
})
|
||||
|
||||
const deployment = new Deployment()
|
||||
await deployment.create(fakeJwt)
|
||||
@@ -351,6 +384,207 @@ describe('Deployment', () => {
|
||||
artifactExchangeScope.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 'error_count':
|
||||
return 10
|
||||
case 'timeout':
|
||||
return MAX_TIMEOUT + 1
|
||||
default:
|
||||
return process.env[`INPUT_${param.toUpperCase()}`] || ''
|
||||
}
|
||||
})
|
||||
|
||||
const now = Date.now()
|
||||
const mockStartTime = now - MAX_TIMEOUT
|
||||
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(MAX_TIMEOUT)
|
||||
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 'error_count':
|
||||
return 10
|
||||
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 'error_count':
|
||||
return 10
|
||||
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', () => {
|
||||
|
||||
@@ -23,6 +23,8 @@ const finalErrorStatus = {
|
||||
deployment_lost: 'Deployment failed to report final status.'
|
||||
}
|
||||
|
||||
const MAX_TIMEOUT = 600000
|
||||
|
||||
class Deployment {
|
||||
constructor() {
|
||||
const context = getContext()
|
||||
@@ -39,11 +41,22 @@ class Deployment {
|
||||
this.githubServerUrl = context.githubServerUrl
|
||||
this.artifactName = context.artifactName
|
||||
this.isPreview = context.isPreview === true
|
||||
this.timeout = MAX_TIMEOUT
|
||||
this.startTime = null
|
||||
}
|
||||
|
||||
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
||||
// by creating a deployment with that artifact
|
||||
async create(idToken) {
|
||||
if (Number(core.getInput('timeout')) > MAX_TIMEOUT) {
|
||||
core.warning(
|
||||
`Warning: timeout value is greater than the allowed maximum - timeout set to the maximum of ${MAX_TIMEOUT} milliseconds.`
|
||||
)
|
||||
}
|
||||
|
||||
const timeoutInput = Number(core.getInput('timeout'))
|
||||
this.timeout = !timeoutInput || timeoutInput <= 0 ? MAX_TIMEOUT : Math.min(timeoutInput, MAX_TIMEOUT)
|
||||
|
||||
try {
|
||||
core.debug(`Actor: ${this.buildActor}`)
|
||||
core.debug(`Action ID: ${this.actionsId}`)
|
||||
@@ -69,6 +82,7 @@ class Deployment {
|
||||
id: deployment.id || deployment.status_url?.split('/')?.pop() || this.buildVersion,
|
||||
pending: true
|
||||
}
|
||||
this.startTime = Date.now()
|
||||
}
|
||||
|
||||
core.info(`Created deployment for ${this.buildVersion}, ID: ${this.deploymentInfo?.id}`)
|
||||
@@ -122,11 +136,9 @@ class Deployment {
|
||||
}
|
||||
|
||||
const deploymentId = this.deploymentInfo.id || this.buildVersion
|
||||
const timeout = Number(core.getInput('timeout'))
|
||||
const reportingInterval = Number(core.getInput('reporting_interval'))
|
||||
const maxErrorCount = Number(core.getInput('error_count'))
|
||||
|
||||
let startTime = Date.now()
|
||||
let errorCount = 0
|
||||
|
||||
// Time in milliseconds between two deployment status report when status errored, default 0.
|
||||
@@ -194,7 +206,7 @@ class Deployment {
|
||||
}
|
||||
|
||||
// Handle timeout
|
||||
if (Date.now() - startTime >= timeout) {
|
||||
if (Date.now() - this.startTime >= this.timeout) {
|
||||
core.error('Timeout reached, aborting!')
|
||||
core.setFailed('Timeout reached, aborting!')
|
||||
|
||||
@@ -231,4 +243,4 @@ class Deployment {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Deployment }
|
||||
module.exports = { Deployment, MAX_TIMEOUT }
|
||||
|
||||
Reference in New Issue
Block a user