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

@@ -7,7 +7,7 @@
This action makes it easy to quickly write a script in your workflow that This action makes it easy to quickly write a script in your workflow that
uses the GitHub API and the workflow run context. uses the GitHub API and the workflow run context.
To use this action, provide an input named `script` that contains the body of an asynchronous function call. To use this action, provide an input named `script` that contains the body of an asynchronous function call.
The following arguments will be provided: The following arguments will be provided:
- `github` A pre-authenticated - `github` A pre-authenticated
@@ -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]'
})` })`
) )