PR feedback

This commit is contained in:
Luke Tomlinson
2022-09-23 16:16:31 -04:00
parent 3cca041b86
commit 3faaff918c
6 changed files with 68 additions and 61 deletions

View File

@@ -83,6 +83,47 @@ output of a github-script step. For some workflows, string encoding is preferred
script: return "I will be string (not JSON) encoded!" script: return "I will be string (not JSON) encoded!"
``` ```
## Retries
By default, requests made with the `github` instance will not be retried. You can configure this with the `retries` option:
```yaml
- uses: actions/github-script@v6
id: my-script
with:
result-encoding: string
retries: 3
script: |
github.rest.issues.get({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
})
```
In this example, request failures from `github.rest.issues.get()` will be retried up to 3 times.
You can also configure which status codes should be exempt from retries via the `retry-exempt-status-codes` option:
```yaml
- uses: actions/github-script@v6
id: my-script
with:
result-encoding: string
retries: 3
retry-exempt-status-codes: 400,401
script: |
github.rest.issues.get({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
})
```
By default, the following status codes will not be retried: `400, 401, 403, 404, 422` [(source)](https://github.com/octokit/plugin-retry.js/blob/9a2443746c350b3beedec35cf26e197ea318a261/src/index.ts#L14).
These retries are implemented using the [octokit/plugin-retry.js](https://github.com/octokit/plugin-retry.js) plugin. The retries use [exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) to space out retries. ([source](https://github.com/octokit/plugin-retry.js/blob/9a2443746c350b3beedec35cf26e197ea318a261/src/error-request.ts#L13))
## Examples ## Examples
Note that `github-token` is optional in this action, and the input is there Note that `github-token` is optional in this action, and the input is there
@@ -354,8 +395,11 @@ jobs:
To import an ESM file, you'll need to reference your script by an absolute path and ensure you have a `package.json` file with `"type": "module"` specified. To import an ESM file, you'll need to reference your script by an absolute path and ensure you have a `package.json` file with `"type": "module"` specified.
For a script in your repository `src/print-stuff.js`: For a script in your repository `src/print-stuff.js`:
```js ```js
export default function printStuff() { console.log('stuff') } export default function printStuff() {
console.log('stuff')
}
``` ```
```yaml ```yaml

View File

@@ -4,11 +4,7 @@ import {getRetryOptions} from '../src/retry-options'
describe('getRequestOptions', () => { describe('getRequestOptions', () => {
test('retries disabled if retries == 0', async () => { test('retries disabled if retries == 0', async () => {
const [retryOptions, requestOptions] = getRetryOptions(0, 8, [ const [retryOptions, requestOptions] = getRetryOptions(0, [400, 500, 502])
400,
500,
502
])
expect(retryOptions.enabled).toBe(false) expect(retryOptions.enabled).toBe(false)
expect(retryOptions.doNotRetry).toBeFalsy() expect(retryOptions.doNotRetry).toBeFalsy()
@@ -17,54 +13,29 @@ describe('getRequestOptions', () => {
}) })
test('properties set if retries > 0', async () => { test('properties set if retries > 0', async () => {
const [retryOptions, requestOptions] = getRetryOptions(1, 8, [ const [retryOptions, requestOptions] = getRetryOptions(1, [400, 500, 502])
400,
500,
502
])
expect(retryOptions.enabled).toBe(true) expect(retryOptions.enabled).toBe(true)
expect(retryOptions.doNotRetry).toEqual([400, 500, 502]) expect(retryOptions.doNotRetry).toEqual([400, 500, 502])
expect(requestOptions.retries).toEqual(1) expect(requestOptions.retries).toEqual(1)
expect(requestOptions.retryAfter).toEqual(8)
}) })
test('properties set if retries > 0', async () => { test('properties set if retries > 0', async () => {
const [retryOptions, requestOptions] = getRetryOptions(1, 8, [ const [retryOptions, requestOptions] = getRetryOptions(1, [400, 500, 502])
400,
500,
502
])
expect(retryOptions.enabled).toBe(true) expect(retryOptions.enabled).toBe(true)
expect(retryOptions.doNotRetry).toEqual([400, 500, 502]) expect(retryOptions.doNotRetry).toEqual([400, 500, 502])
expect(requestOptions.retries).toEqual(1) expect(requestOptions.retries).toEqual(1)
expect(requestOptions.retryAfter).toEqual(8)
}) })
test('retryAfter can be set to zero', async () => { test('retryOptions.doNotRetry not set if exemptStatusCodes isEmpty', async () => {
const [retryOptions, requestOptions] = getRetryOptions(1, 0, [ const [retryOptions, requestOptions] = getRetryOptions(1, [])
400,
500,
502
])
expect(retryOptions.enabled).toBe(true)
expect(retryOptions.doNotRetry).toEqual([400, 500, 502])
expect(requestOptions.retries).toEqual(1)
expect(requestOptions.retryAfter).toEqual(0)
})
test('retryOptions.doNotRetry not set if doNotRetry isEmpty', async () => {
const [retryOptions, requestOptions] = getRetryOptions(1, 0, [])
expect(retryOptions.enabled).toBe(true) expect(retryOptions.enabled).toBe(true)
expect(retryOptions.doNotRetry).toBeUndefined() expect(retryOptions.doNotRetry).toBeUndefined()
expect(requestOptions.retries).toEqual(1) expect(requestOptions.retries).toEqual(1)
expect(requestOptions.retryAfter).toEqual(0)
}) })
}) })

View File

@@ -29,9 +29,9 @@ inputs:
retry-after: retry-after:
description: "The number of seconds between retries. No effect unless `retries` is set." description: "The number of seconds between retries. No effect unless `retries` is set."
default: "0" default: "0"
do-not-retry: retry-exempt-status-codes:
description: "A comma separated list of status codes that will NOT be retried. Example: '400,500'. No effect unless `retries` is set." description: "A comma separated list of status codes that will NOT be retried. Example: '400,500'. No effect unless `retries` is set."
default: "" default: "400, 401, 403, 404, 422" # from https://github.com/octokit/plugin-retry.js/blob/9a2443746c350b3beedec35cf26e197ea318a261/src/index.ts#L14
outputs: outputs:
result: result:
description: The return value of the script, stringified with `JSON.stringify` description: The return value of the script, stringified with `JSON.stringify`

16
dist/index.js vendored
View File

@@ -13340,7 +13340,7 @@ function callAsyncFunction(args, source) {
// CONCATENATED MODULE: ./src/retry-options.ts // CONCATENATED MODULE: ./src/retry-options.ts
function getRetryOptions(retries, retryAfter, doNotRetry) { function getRetryOptions(retries, exemptStatusCodes) {
var _a; var _a;
if (retries <= 0) { if (retries <= 0) {
return [{ enabled: false }, {}]; return [{ enabled: false }, {}];
@@ -13348,14 +13348,13 @@ function getRetryOptions(retries, retryAfter, doNotRetry) {
const retryOptions = { const retryOptions = {
enabled: true enabled: true
}; };
if (doNotRetry.length > 0) { if (exemptStatusCodes.length > 0) {
retryOptions.doNotRetry = doNotRetry; retryOptions.doNotRetry = exemptStatusCodes;
} }
const requestOptions = { const requestOptions = {
retries, retries
retryAfter: retryAfter
}; };
Object(core.info)(`GitHub client configured with: (retries: ${requestOptions.retries}, retryAfter: ${requestOptions.retryAfter}, doNotRetry: ${(_a = retryOptions === null || retryOptions === void 0 ? void 0 : retryOptions.doNotRetry) !== null && _a !== void 0 ? _a : 'octokit default: [400, 401, 403, 404, 422]'})`); Object(core.info)(`GitHub client configured with: (retries: ${requestOptions.retries}, retry-exempt-status-code: ${(_a = retryOptions === null || retryOptions === void 0 ? void 0 : retryOptions.doNotRetry) !== null && _a !== void 0 ? _a : 'octokit default: [400, 401, 403, 404, 422]'})`);
return [retryOptions, requestOptions]; return [retryOptions, requestOptions];
} }
function parseNumberArray(listString) { function parseNumberArray(listString) {
@@ -13410,9 +13409,8 @@ async function main() {
const userAgent = Object(core.getInput)('user-agent'); const userAgent = Object(core.getInput)('user-agent');
const previews = Object(core.getInput)('previews'); const previews = Object(core.getInput)('previews');
const retries = parseInt(Object(core.getInput)('retries')); const retries = parseInt(Object(core.getInput)('retries'));
const retryAfter = parseInt(Object(core.getInput)('retry-after')); const exemptStatusCodes = parseNumberArray(Object(core.getInput)('retry-exempt-status-codes'));
const doNotRetry = parseNumberArray(Object(core.getInput)('do-not-retry')); const [retryOpts, requestOpts] = getRetryOptions(retries, exemptStatusCodes);
const [retryOpts, requestOpts] = getRetryOptions(retries, retryAfter, doNotRetry);
const opts = {}; const opts = {};
if (debug === 'true') if (debug === 'true')
opts.log = console; opts.log = console;

View File

@@ -30,13 +30,10 @@ async function main(): Promise<void> {
const userAgent = core.getInput('user-agent') const userAgent = core.getInput('user-agent')
const previews = core.getInput('previews') const previews = core.getInput('previews')
const retries = parseInt(core.getInput('retries')) const retries = parseInt(core.getInput('retries'))
const retryAfter = parseInt(core.getInput('retry-after')) const exemptStatusCodes = parseNumberArray(
const doNotRetry = parseNumberArray(core.getInput('do-not-retry')) core.getInput('retry-exempt-status-codes')
const [retryOpts, requestOpts] = getRetryOptions(
retries,
retryAfter,
doNotRetry
) )
const [retryOpts, requestOpts] = getRetryOptions(retries, exemptStatusCodes)
const opts: Options = {} const opts: Options = {}
if (debug === 'true') opts.log = console if (debug === 'true') opts.log = console

View File

@@ -7,13 +7,11 @@ export type RetryOptions = {
export type RequestOptions = { export type RequestOptions = {
retries?: number retries?: number
retryAfter?: number
} }
export function getRetryOptions( export function getRetryOptions(
retries: number, retries: number,
retryAfter: number, exemptStatusCodes: number[]
doNotRetry: number[]
): [RetryOptions, RequestOptions] { ): [RetryOptions, RequestOptions] {
if (retries <= 0) { if (retries <= 0) {
return [{enabled: false}, {}] return [{enabled: false}, {}]
@@ -23,19 +21,18 @@ export function getRetryOptions(
enabled: true enabled: true
} }
if (doNotRetry.length > 0) { if (exemptStatusCodes.length > 0) {
retryOptions.doNotRetry = doNotRetry retryOptions.doNotRetry = exemptStatusCodes
} }
const requestOptions: RequestOptions = { const requestOptions: RequestOptions = {
retries, retries
retryAfter: retryAfter
} }
core.info( core.info(
`GitHub client configured with: (retries: ${ `GitHub client configured with: (retries: ${
requestOptions.retries requestOptions.retries
}, retryAfter: ${requestOptions.retryAfter}, doNotRetry: ${ }, retry-exempt-status-code: ${
retryOptions?.doNotRetry ?? 'octokit default: [400, 401, 403, 404, 422]' retryOptions?.doNotRetry ?? 'octokit default: [400, 401, 403, 404, 422]'
})` })`
) )