mirror of
https://github.com/actions/deploy-pages.git
synced 2026-09-27 05:06:54 +00:00
Compare commits
6 Commits
v3.0.2-nod
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
758cc81e60 | ||
|
|
368f825286 | ||
|
|
7e97763d1f | ||
|
|
0143e11abb | ||
|
|
5e98f10ce2 | ||
|
|
8b0625abb5 |
@@ -51,7 +51,7 @@ jobs:
|
||||
| `token` | `true` | `${{ github.token }}` | The GitHub token used to create an authenticated client - Provided for you by default! |
|
||||
| `timeout` | `false` | `"600000"` | Time in milliseconds after which to timeout and cancel the deployment (default: 10 minutes) |
|
||||
| `error_count` | `false` | `"10"` | Maximum number of status report errors before cancelling a deployment (default: 10) |
|
||||
| `reporting_interval` | `false` | `"5000"` | Time in milliseconds between two deployment status reports (default: 5 seconds) |
|
||||
| `reporting_interval` | `false` | `"5000"` | Initial time in milliseconds between deployment status reports. Successful non-terminal polls use exponential backoff up to 30 seconds, or the configured interval when higher, with ±20% jitter. Error backoff is added separately (default: 5 seconds). |
|
||||
| `artifact_name` | `false` | `"github-pages"` | The name of the artifact to deploy |
|
||||
| `preview` | `false` | `"false"` | Is this attempting to deploy a pull request as a GitHub Pages preview site? (NOTE: This feature is only in alpha currently and is not available to the public!) |
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ inputs:
|
||||
required: false
|
||||
default: '10'
|
||||
reporting_interval:
|
||||
description: 'Time in milliseconds between two deployment status report (default: 5 seconds)'
|
||||
description: 'Initial time between deployment status reports; successful polls use capped backoff and jitter, with error backoff added separately (default: 5 seconds)'
|
||||
required: false
|
||||
default: '5000'
|
||||
artifact_name:
|
||||
|
||||
33
dist/index.js
generated
vendored
33
dist/index.js
generated
vendored
@@ -149920,9 +149920,18 @@ const finalErrorStatus = {
|
||||
}
|
||||
|
||||
const MAX_TIMEOUT = 600000
|
||||
const DEFAULT_REPORTING_INTERVAL = 5000
|
||||
const MAX_REPORTING_INTERVAL = 30000
|
||||
const REPORTING_BACKOFF_MULTIPLIER = 1.5
|
||||
const REPORTING_JITTER_FACTOR = 0.2
|
||||
const ONE_GIGABYTE = 1073741824
|
||||
const SIZE_LIMIT_DESCRIPTION = '1 GB'
|
||||
|
||||
function getJitteredInterval(interval) {
|
||||
const jitter = interval * REPORTING_JITTER_FACTOR
|
||||
return Math.round(interval - jitter + Math.random() * jitter * 2)
|
||||
}
|
||||
|
||||
class Deployment {
|
||||
constructor() {
|
||||
const context = getContext()
|
||||
@@ -150034,9 +150043,19 @@ class Deployment {
|
||||
}
|
||||
|
||||
const deploymentId = this.deploymentInfo.id || this.buildVersion
|
||||
const reportingInterval = Number(core.getInput('reporting_interval'))
|
||||
const reportingIntervalInput = Number(core.getInput('reporting_interval'))
|
||||
const initialReportingInterval =
|
||||
Number.isFinite(reportingIntervalInput) && reportingIntervalInput > 0
|
||||
? reportingIntervalInput
|
||||
: DEFAULT_REPORTING_INTERVAL
|
||||
const maxReportingInterval = Math.max(MAX_REPORTING_INTERVAL, initialReportingInterval)
|
||||
const maxErrorCount = Number(core.getInput('error_count'))
|
||||
|
||||
if (initialReportingInterval !== reportingIntervalInput) {
|
||||
core.warning(`Invalid reporting_interval value; using the default of ${DEFAULT_REPORTING_INTERVAL} milliseconds.`)
|
||||
}
|
||||
|
||||
let reportingInterval = initialReportingInterval
|
||||
let errorCount = 0
|
||||
|
||||
// Time in milliseconds between two deployment status report when status errored, default 0.
|
||||
@@ -150047,7 +150066,7 @@ class Deployment {
|
||||
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
||||
while (true) {
|
||||
// Handle reporting interval
|
||||
await new Promise(resolve => setTimeout(resolve, reportingInterval + errorReportingInterval))
|
||||
await new Promise(resolve => setTimeout(resolve, getJitteredInterval(reportingInterval + errorReportingInterval)))
|
||||
|
||||
// Check status
|
||||
try {
|
||||
@@ -150075,6 +150094,7 @@ class Deployment {
|
||||
|
||||
// reset the error reporting interval once get the proper status back.
|
||||
errorReportingInterval = 0
|
||||
reportingInterval = Math.min(Math.round(reportingInterval * REPORTING_BACKOFF_MULTIPLIER), maxReportingInterval)
|
||||
} catch (error) {
|
||||
core.error(error.stack)
|
||||
|
||||
@@ -150138,7 +150158,14 @@ class Deployment {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION }
|
||||
module.exports = {
|
||||
Deployment,
|
||||
MAX_TIMEOUT,
|
||||
DEFAULT_REPORTING_INTERVAL,
|
||||
MAX_REPORTING_INTERVAL,
|
||||
ONE_GIGABYTE,
|
||||
SIZE_LIMIT_DESCRIPTION
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
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
98
package-lock.json
generated
98
package-lock.json
generated
@@ -1138,6 +1138,7 @@
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^5.1.2",
|
||||
"string-width-cjs": "npm:string-width@^4.2.0",
|
||||
@@ -1151,9 +1152,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz",
|
||||
"integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -1162,9 +1164,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/ansi-styles": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
|
||||
"integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -1175,12 +1178,14 @@
|
||||
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/string-width": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eastasianwidth": "^0.2.0",
|
||||
"emoji-regex": "^9.2.2",
|
||||
@@ -1194,11 +1199,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
|
||||
"integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
"ansi-regex": "^6.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -1211,6 +1217,7 @@
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.1.0",
|
||||
"string-width": "^5.0.1",
|
||||
@@ -1870,6 +1877,7 @@
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
@@ -2509,22 +2517,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/archiver-utils/node_modules/glob": {
|
||||
"version": "10.3.12",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
|
||||
"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
|
||||
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
|
||||
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^2.3.6",
|
||||
"minimatch": "^9.0.1",
|
||||
"minipass": "^7.0.4",
|
||||
"path-scurry": "^1.10.2"
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.4",
|
||||
"minipass": "^7.1.2",
|
||||
"package-json-from-dist": "^1.0.0",
|
||||
"path-scurry": "^1.11.1"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
@@ -3590,7 +3598,8 @@
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.613",
|
||||
@@ -5509,15 +5518,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
|
||||
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
||||
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
},
|
||||
@@ -6491,9 +6498,10 @@
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
|
||||
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
|
||||
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
@@ -6795,6 +6803,12 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/package-json-from-dist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
|
||||
"license": "BlueOak-1.0.0"
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
@@ -6866,27 +6880,26 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
|
||||
"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
||||
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^10.2.0",
|
||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry/node_modules/lru-cache": {
|
||||
"version": "10.2.2",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
|
||||
"integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
|
||||
"engines": {
|
||||
"node": "14 || >=16.14"
|
||||
}
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "6.2.1",
|
||||
@@ -7502,6 +7515,7 @@
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
@@ -7555,6 +7569,7 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
@@ -8089,6 +8104,7 @@
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
|
||||
@@ -4,7 +4,14 @@ const nock = require('nock')
|
||||
// For mocking network calls with native Fetch (octokit)
|
||||
const { MockAgent, setGlobalDispatcher } = require('undici')
|
||||
|
||||
const { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION } = require('../../internal/deployment')
|
||||
const {
|
||||
Deployment,
|
||||
MAX_TIMEOUT,
|
||||
DEFAULT_REPORTING_INTERVAL,
|
||||
MAX_REPORTING_INTERVAL,
|
||||
ONE_GIGABYTE,
|
||||
SIZE_LIMIT_DESCRIPTION
|
||||
} = require('../../internal/deployment')
|
||||
|
||||
const fakeJwt =
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w'
|
||||
@@ -35,7 +42,7 @@ describe('Deployment', () => {
|
||||
case 'token':
|
||||
return process.env.GITHUB_TOKEN
|
||||
case 'reporting_interval':
|
||||
return 50 // Lower reporting interval to speed up test
|
||||
return process.env.INPUT_REPORTING_INTERVAL || 50 // Lower reporting interval to speed up test
|
||||
default:
|
||||
return process.env[`INPUT_${param.toUpperCase()}`] || ''
|
||||
}
|
||||
@@ -121,6 +128,58 @@ describe('Deployment', () => {
|
||||
twirpScope.done()
|
||||
})
|
||||
|
||||
it('can successfully create a deployment with a 64-character build version', async () => {
|
||||
process.env.GITHUB_SHA = 'a'.repeat(64)
|
||||
|
||||
const twirpScope = nock(process.env.ACTIONS_RESULTS_URL)
|
||||
.post(LIST_ARTIFACTS_TWIRP_PATH)
|
||||
.reply(
|
||||
200,
|
||||
{
|
||||
artifacts: [{ databaseId: 11, name: 'github-pages', size: 221 }]
|
||||
},
|
||||
{ headers: { 'content-type': 'application/json' } }
|
||||
)
|
||||
|
||||
mockPool
|
||||
.intercept({
|
||||
path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`,
|
||||
method: 'POST',
|
||||
body: bodyString => {
|
||||
const body = JSON.parse(bodyString)
|
||||
const keys = Object.keys(body).sort()
|
||||
return (
|
||||
keys.length === 3 &&
|
||||
keys[0] === 'artifact_id' &&
|
||||
keys[1] === 'oidc_token' &&
|
||||
keys[2] === 'pages_build_version' &&
|
||||
body.artifact_id === 11 &&
|
||||
body.pages_build_version === process.env.GITHUB_SHA &&
|
||||
body.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'
|
||||
},
|
||||
{ headers: { 'content-type': 'application/json' } }
|
||||
)
|
||||
|
||||
const deployment = new Deployment()
|
||||
await deployment.create(fakeJwt)
|
||||
|
||||
expect(process.env.GITHUB_SHA).toHaveLength(64)
|
||||
expect(core.setFailed).not.toHaveBeenCalled()
|
||||
expect(core.info).toHaveBeenLastCalledWith(
|
||||
expect.stringMatching(new RegExp(`^Created deployment for ${process.env.GITHUB_SHA}`))
|
||||
)
|
||||
|
||||
twirpScope.done()
|
||||
})
|
||||
|
||||
it('can successfully create a preview deployment', async () => {
|
||||
process.env.GITHUB_SHA = 'valid-build-version'
|
||||
|
||||
@@ -556,6 +615,42 @@ describe('Deployment', () => {
|
||||
})
|
||||
|
||||
describe('#check', () => {
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks()
|
||||
delete process.env.INPUT_ERROR_COUNT
|
||||
delete process.env.INPUT_REPORTING_INTERVAL
|
||||
})
|
||||
|
||||
const mockDeploymentStatus = (status, times = 1) => {
|
||||
mockPool
|
||||
.intercept({
|
||||
path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`,
|
||||
method: 'GET'
|
||||
})
|
||||
.reply(200, { status }, { headers: { 'content-type': 'application/json' } })
|
||||
.times(times)
|
||||
}
|
||||
|
||||
const createPendingDeployment = () => {
|
||||
const deployment = new Deployment()
|
||||
deployment.deploymentInfo = {
|
||||
id: process.env.GITHUB_SHA,
|
||||
pending: true
|
||||
}
|
||||
deployment.startTime = Date.now()
|
||||
return deployment
|
||||
}
|
||||
|
||||
const runWithoutWaiting = async deployment => {
|
||||
const timeoutSpy = jest.spyOn(global, 'setTimeout').mockImplementation(resolve => {
|
||||
resolve()
|
||||
return 0
|
||||
})
|
||||
|
||||
await deployment.check()
|
||||
return timeoutSpy
|
||||
}
|
||||
|
||||
it('sets output to success when deployment is successful', async () => {
|
||||
process.env.GITHUB_SHA = 'valid-build-version'
|
||||
|
||||
@@ -912,7 +1007,7 @@ describe('Deployment', () => {
|
||||
case 'error_count':
|
||||
return 10
|
||||
case 'reporting_interval':
|
||||
return 0 // The default of 5000 is too long for the test
|
||||
return 1 // The default of 5000 is too long for the test
|
||||
case 'timeout':
|
||||
return 42
|
||||
default:
|
||||
@@ -938,6 +1033,108 @@ describe('Deployment', () => {
|
||||
expect(core.info).toHaveBeenLastCalledWith('Reported success!')
|
||||
twirpScope.done()
|
||||
})
|
||||
|
||||
it('backs off successful non-terminal status checks', async () => {
|
||||
process.env.GITHUB_SHA = 'valid-build-version'
|
||||
process.env.INPUT_ERROR_COUNT = '10'
|
||||
mockDeploymentStatus('deployment_in_progress', 2)
|
||||
mockDeploymentStatus('succeed')
|
||||
const randomSpy = jest.spyOn(Math, 'random').mockReturnValue(0.5)
|
||||
|
||||
const timeoutSpy = await runWithoutWaiting(createPendingDeployment())
|
||||
|
||||
expect(timeoutSpy).toHaveBeenNthCalledWith(1, expect.any(Function), 50)
|
||||
expect(timeoutSpy).toHaveBeenNthCalledWith(2, expect.any(Function), 75)
|
||||
expect(timeoutSpy).toHaveBeenNthCalledWith(3, expect.any(Function), 113)
|
||||
|
||||
timeoutSpy.mockRestore()
|
||||
randomSpy.mockRestore()
|
||||
delete process.env.INPUT_ERROR_COUNT
|
||||
})
|
||||
|
||||
it('caps the successful status check backoff', async () => {
|
||||
process.env.GITHUB_SHA = 'valid-build-version'
|
||||
process.env.INPUT_ERROR_COUNT = '10'
|
||||
process.env.INPUT_REPORTING_INTERVAL = '20000'
|
||||
mockDeploymentStatus('deployment_in_progress')
|
||||
mockDeploymentStatus('succeed')
|
||||
const randomSpy = jest.spyOn(Math, 'random').mockReturnValue(0.5)
|
||||
|
||||
const timeoutSpy = await runWithoutWaiting(createPendingDeployment())
|
||||
|
||||
expect(timeoutSpy.mock.calls.map(([, interval]) => interval)).toEqual([20000, MAX_REPORTING_INTERVAL])
|
||||
|
||||
timeoutSpy.mockRestore()
|
||||
randomSpy.mockRestore()
|
||||
})
|
||||
|
||||
it('does not reduce a configured interval above the backoff cap', async () => {
|
||||
process.env.GITHUB_SHA = 'valid-build-version'
|
||||
process.env.INPUT_ERROR_COUNT = '10'
|
||||
process.env.INPUT_REPORTING_INTERVAL = '45000'
|
||||
mockDeploymentStatus('deployment_in_progress')
|
||||
mockDeploymentStatus('succeed')
|
||||
jest.spyOn(Math, 'random').mockReturnValue(0.5)
|
||||
|
||||
const timeoutSpy = await runWithoutWaiting(createPendingDeployment())
|
||||
|
||||
expect(timeoutSpy.mock.calls.map(([, interval]) => interval)).toEqual([45000, 45000])
|
||||
})
|
||||
|
||||
it.each(['not-a-number', '0', '-1'])(
|
||||
'uses the default reporting interval for invalid input %s',
|
||||
async reportingInterval => {
|
||||
process.env.GITHUB_SHA = 'valid-build-version'
|
||||
process.env.INPUT_ERROR_COUNT = '10'
|
||||
process.env.INPUT_REPORTING_INTERVAL = reportingInterval
|
||||
mockDeploymentStatus('succeed')
|
||||
jest.spyOn(Math, 'random').mockReturnValue(0.5)
|
||||
|
||||
const timeoutSpy = await runWithoutWaiting(createPendingDeployment())
|
||||
|
||||
expect(timeoutSpy).toHaveBeenCalledWith(expect.any(Function), DEFAULT_REPORTING_INTERVAL)
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
`Invalid reporting_interval value; using the default of ${DEFAULT_REPORTING_INTERVAL} milliseconds.`
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
it('jitters status check intervals by up to twenty percent', async () => {
|
||||
process.env.GITHUB_SHA = 'valid-build-version'
|
||||
process.env.INPUT_ERROR_COUNT = '10'
|
||||
mockDeploymentStatus('deployment_in_progress')
|
||||
mockDeploymentStatus('succeed')
|
||||
const randomSpy = jest.spyOn(Math, 'random').mockReturnValueOnce(0).mockReturnValueOnce(1)
|
||||
|
||||
const timeoutSpy = await runWithoutWaiting(createPendingDeployment())
|
||||
|
||||
expect(timeoutSpy).toHaveBeenNthCalledWith(1, expect.any(Function), 40)
|
||||
expect(timeoutSpy).toHaveBeenNthCalledWith(2, expect.any(Function), 90)
|
||||
|
||||
timeoutSpy.mockRestore()
|
||||
randomSpy.mockRestore()
|
||||
})
|
||||
|
||||
it('keeps success backoff separate from error backoff', async () => {
|
||||
process.env.GITHUB_SHA = 'valid-build-version'
|
||||
process.env.INPUT_ERROR_COUNT = '10'
|
||||
mockPool
|
||||
.intercept({
|
||||
path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`,
|
||||
method: 'GET'
|
||||
})
|
||||
.reply(500, {}, { headers: { 'content-type': 'application/json' } })
|
||||
mockDeploymentStatus('deployment_in_progress')
|
||||
mockDeploymentStatus('succeed')
|
||||
const randomSpy = jest.spyOn(Math, 'random').mockReturnValue(0.5)
|
||||
|
||||
const timeoutSpy = await runWithoutWaiting(createPendingDeployment())
|
||||
|
||||
expect(timeoutSpy.mock.calls.map(([, interval]) => interval)).toEqual([50, 51, 75])
|
||||
|
||||
timeoutSpy.mockRestore()
|
||||
randomSpy.mockRestore()
|
||||
})
|
||||
})
|
||||
|
||||
describe('#cancel', () => {
|
||||
|
||||
@@ -24,9 +24,18 @@ const finalErrorStatus = {
|
||||
}
|
||||
|
||||
const MAX_TIMEOUT = 600000
|
||||
const DEFAULT_REPORTING_INTERVAL = 5000
|
||||
const MAX_REPORTING_INTERVAL = 30000
|
||||
const REPORTING_BACKOFF_MULTIPLIER = 1.5
|
||||
const REPORTING_JITTER_FACTOR = 0.2
|
||||
const ONE_GIGABYTE = 1073741824
|
||||
const SIZE_LIMIT_DESCRIPTION = '1 GB'
|
||||
|
||||
function getJitteredInterval(interval) {
|
||||
const jitter = interval * REPORTING_JITTER_FACTOR
|
||||
return Math.round(interval - jitter + Math.random() * jitter * 2)
|
||||
}
|
||||
|
||||
class Deployment {
|
||||
constructor() {
|
||||
const context = getContext()
|
||||
@@ -138,9 +147,19 @@ class Deployment {
|
||||
}
|
||||
|
||||
const deploymentId = this.deploymentInfo.id || this.buildVersion
|
||||
const reportingInterval = Number(core.getInput('reporting_interval'))
|
||||
const reportingIntervalInput = Number(core.getInput('reporting_interval'))
|
||||
const initialReportingInterval =
|
||||
Number.isFinite(reportingIntervalInput) && reportingIntervalInput > 0
|
||||
? reportingIntervalInput
|
||||
: DEFAULT_REPORTING_INTERVAL
|
||||
const maxReportingInterval = Math.max(MAX_REPORTING_INTERVAL, initialReportingInterval)
|
||||
const maxErrorCount = Number(core.getInput('error_count'))
|
||||
|
||||
if (initialReportingInterval !== reportingIntervalInput) {
|
||||
core.warning(`Invalid reporting_interval value; using the default of ${DEFAULT_REPORTING_INTERVAL} milliseconds.`)
|
||||
}
|
||||
|
||||
let reportingInterval = initialReportingInterval
|
||||
let errorCount = 0
|
||||
|
||||
// Time in milliseconds between two deployment status report when status errored, default 0.
|
||||
@@ -151,7 +170,7 @@ class Deployment {
|
||||
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
||||
while (true) {
|
||||
// Handle reporting interval
|
||||
await new Promise(resolve => setTimeout(resolve, reportingInterval + errorReportingInterval))
|
||||
await new Promise(resolve => setTimeout(resolve, getJitteredInterval(reportingInterval + errorReportingInterval)))
|
||||
|
||||
// Check status
|
||||
try {
|
||||
@@ -179,6 +198,7 @@ class Deployment {
|
||||
|
||||
// reset the error reporting interval once get the proper status back.
|
||||
errorReportingInterval = 0
|
||||
reportingInterval = Math.min(Math.round(reportingInterval * REPORTING_BACKOFF_MULTIPLIER), maxReportingInterval)
|
||||
} catch (error) {
|
||||
core.error(error.stack)
|
||||
|
||||
@@ -242,4 +262,11 @@ class Deployment {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION }
|
||||
module.exports = {
|
||||
Deployment,
|
||||
MAX_TIMEOUT,
|
||||
DEFAULT_REPORTING_INTERVAL,
|
||||
MAX_REPORTING_INTERVAL,
|
||||
ONE_GIGABYTE,
|
||||
SIZE_LIMIT_DESCRIPTION
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user