Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
29374e1e56 Bump picomatch from 2.3.1 to 2.3.2
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-15 21:47:57 +00:00
7 changed files with 57 additions and 323 deletions

View File

@@ -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"` | 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). |
| `reporting_interval` | `false` | `"5000"` | Time in milliseconds between two deployment status reports (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!) |

View File

@@ -18,7 +18,7 @@ inputs:
required: false
default: '10'
reporting_interval:
description: 'Initial time between deployment status reports; successful polls use capped backoff and jitter, with error backoff added separately (default: 5 seconds)'
description: 'Time in milliseconds between two deployment status report (default: 5 seconds)'
required: false
default: '5000'
artifact_name:

33
dist/index.js generated vendored
View File

@@ -149920,18 +149920,9 @@ 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()
@@ -150043,19 +150034,9 @@ class Deployment {
}
const deploymentId = this.deploymentInfo.id || this.buildVersion
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 reportingInterval = Number(core.getInput('reporting_interval'))
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.
@@ -150066,7 +150047,7 @@ class Deployment {
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
while (true) {
// Handle reporting interval
await new Promise(resolve => setTimeout(resolve, getJitteredInterval(reportingInterval + errorReportingInterval)))
await new Promise(resolve => setTimeout(resolve, reportingInterval + errorReportingInterval))
// Check status
try {
@@ -150094,7 +150075,6 @@ 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)
@@ -150158,14 +150138,7 @@ class Deployment {
}
}
module.exports = {
Deployment,
MAX_TIMEOUT,
DEFAULT_REPORTING_INTERVAL,
MAX_REPORTING_INTERVAL,
ONE_GIGABYTE,
SIZE_LIMIT_DESCRIPTION
}
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

105
package-lock.json generated
View File

@@ -1138,7 +1138,6 @@
"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",
@@ -1152,10 +1151,9 @@
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz",
"integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==",
"license": "MIT",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"engines": {
"node": ">=12"
},
@@ -1164,10 +1162,9 @@
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-styles": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
"integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
"license": "MIT",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"engines": {
"node": ">=12"
},
@@ -1178,14 +1175,12 @@
"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==",
"license": "MIT"
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"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",
@@ -1199,12 +1194,11 @@
}
},
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
"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",
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dependencies": {
"ansi-regex": "^6.2.2"
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
@@ -1217,7 +1211,6 @@
"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",
@@ -1877,7 +1870,6 @@
"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"
@@ -2517,22 +2509,22 @@
}
},
"node_modules/archiver-utils/node_modules/glob": {
"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",
"version": "10.3.12",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
"jackspeak": "^2.3.6",
"minimatch": "^9.0.1",
"minipass": "^7.0.4",
"path-scurry": "^1.10.2"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
@@ -3598,8 +3590,7 @@
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"license": "MIT"
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/electron-to-chromium": {
"version": "1.4.613",
@@ -5518,13 +5509,15 @@
}
},
"node_modules/jackspeak": {
"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",
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
@@ -6498,10 +6491,9 @@
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"node_modules/minipass": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
"license": "BlueOak-1.0.0",
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
"engines": {
"node": ">=16 || 14 >=14.17"
}
@@ -6803,12 +6795,6 @@
"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",
@@ -6880,26 +6866,27 @@
"dev": true
},
"node_modules/path-scurry": {
"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",
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.18"
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
"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"
}
},
"node_modules/path-to-regexp": {
"version": "6.2.1",
@@ -6922,10 +6909,11 @@
"dev": true
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
},
@@ -7515,7 +7503,6 @@
"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",
@@ -7569,7 +7556,6 @@
"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"
},
@@ -8104,7 +8090,6 @@
"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",

View File

@@ -4,14 +4,7 @@ const nock = require('nock')
// For mocking network calls with native Fetch (octokit)
const { MockAgent, setGlobalDispatcher } = require('undici')
const {
Deployment,
MAX_TIMEOUT,
DEFAULT_REPORTING_INTERVAL,
MAX_REPORTING_INTERVAL,
ONE_GIGABYTE,
SIZE_LIMIT_DESCRIPTION
} = require('../../internal/deployment')
const { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION } = require('../../internal/deployment')
const fakeJwt =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w'
@@ -42,7 +35,7 @@ describe('Deployment', () => {
case 'token':
return process.env.GITHUB_TOKEN
case 'reporting_interval':
return process.env.INPUT_REPORTING_INTERVAL || 50 // Lower reporting interval to speed up test
return 50 // Lower reporting interval to speed up test
default:
return process.env[`INPUT_${param.toUpperCase()}`] || ''
}
@@ -128,58 +121,6 @@ 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'
@@ -615,42 +556,6 @@ 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'
@@ -1007,7 +912,7 @@ describe('Deployment', () => {
case 'error_count':
return 10
case 'reporting_interval':
return 1 // The default of 5000 is too long for the test
return 0 // The default of 5000 is too long for the test
case 'timeout':
return 42
default:
@@ -1033,108 +938,6 @@ 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', () => {

View File

@@ -24,18 +24,9 @@ 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()
@@ -147,19 +138,9 @@ class Deployment {
}
const deploymentId = this.deploymentInfo.id || this.buildVersion
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 reportingInterval = Number(core.getInput('reporting_interval'))
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.
@@ -170,7 +151,7 @@ class Deployment {
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
while (true) {
// Handle reporting interval
await new Promise(resolve => setTimeout(resolve, getJitteredInterval(reportingInterval + errorReportingInterval)))
await new Promise(resolve => setTimeout(resolve, reportingInterval + errorReportingInterval))
// Check status
try {
@@ -198,7 +179,6 @@ 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)
@@ -262,11 +242,4 @@ class Deployment {
}
}
module.exports = {
Deployment,
MAX_TIMEOUT,
DEFAULT_REPORTING_INTERVAL,
MAX_REPORTING_INTERVAL,
ONE_GIGABYTE,
SIZE_LIMIT_DESCRIPTION
}
module.exports = { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION }