From 660d9075171b81920d1814a783d75c69dee697c2 Mon Sep 17 00:00:00 2001 From: Luke Tomlinson Date: Fri, 23 Sep 2022 11:45:39 -0400 Subject: [PATCH] refactor and add tests for retry options --- __test__/get-retry-options.test.ts | 70 +++++++ dist/index.js | 300 +++++++++++++++-------------- src/main.ts | 55 ++---- src/retry-options.ts | 53 +++++ 4 files changed, 293 insertions(+), 185 deletions(-) create mode 100644 __test__/get-retry-options.test.ts create mode 100644 src/retry-options.ts diff --git a/__test__/get-retry-options.test.ts b/__test__/get-retry-options.test.ts new file mode 100644 index 0000000..95b08d7 --- /dev/null +++ b/__test__/get-retry-options.test.ts @@ -0,0 +1,70 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import {getRetryOptions} from '../src/retry-options' + +describe('getRequestOptions', () => { + test('retries disabled if retries == 0', async () => { + const [retryOptions, requestOptions] = getRetryOptions(0, 8, [ + 400, + 500, + 502 + ]) + + expect(retryOptions.enabled).toBe(false) + expect(retryOptions.doNotRetry).toBeFalsy() + + expect(requestOptions.retries).toBeFalsy() + }) + + test('properties set if retries > 0', async () => { + const [retryOptions, requestOptions] = getRetryOptions(1, 8, [ + 400, + 500, + 502 + ]) + + expect(retryOptions.enabled).toBe(true) + expect(retryOptions.doNotRetry).toEqual([400, 500, 502]) + + expect(requestOptions.retries).toEqual(1) + expect(requestOptions.retryAfter).toEqual(8) + }) + + test('properties set if retries > 0', async () => { + const [retryOptions, requestOptions] = getRetryOptions(1, 8, [ + 400, + 500, + 502 + ]) + + expect(retryOptions.enabled).toBe(true) + expect(retryOptions.doNotRetry).toEqual([400, 500, 502]) + + expect(requestOptions.retries).toEqual(1) + expect(requestOptions.retryAfter).toEqual(8) + }) + + test('retryAfter can be set to zero', async () => { + const [retryOptions, requestOptions] = getRetryOptions(1, 0, [ + 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.doNotRetry).toBeUndefined() + + expect(requestOptions.retries).toEqual(1) + expect(requestOptions.retryAfter).toEqual(0) + }) +}) diff --git a/dist/index.js b/dist/index.js index acd5d66..f652b68 100644 --- a/dist/index.js +++ b/dist/index.js @@ -40,7 +40,7 @@ module.exports = /******/ // the startup function /******/ function startup() { /******/ // Load entry module and return exports -/******/ return __webpack_require__(272); +/******/ return __webpack_require__(858); /******/ }; /******/ // initialize runtime /******/ runtime(__webpack_require__); @@ -7084,150 +7084,6 @@ exports.implementation = class URLImpl { }; -/***/ }), - -/***/ 272: -/***/ (function(__unusedmodule, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); - -// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js -var core = __webpack_require__(186); - -// EXTERNAL MODULE: ./node_modules/@actions/exec/lib/exec.js -var exec = __webpack_require__(514); - -// EXTERNAL MODULE: ./node_modules/@actions/github/lib/github.js -var lib_github = __webpack_require__(438); - -// EXTERNAL MODULE: ./node_modules/@actions/glob/lib/glob.js -var glob = __webpack_require__(90); - -// EXTERNAL MODULE: ./node_modules/@actions/io/lib/io.js -var io = __webpack_require__(436); - -// EXTERNAL MODULE: ./node_modules/@octokit/plugin-retry/dist-node/index.js -var dist_node = __webpack_require__(745); - -// CONCATENATED MODULE: ./src/async-function.ts -const AsyncFunction = Object.getPrototypeOf(async () => null).constructor; -function callAsyncFunction(args, source) { - const fn = new AsyncFunction(...Object.keys(args), source); - return fn(...Object.values(args)); -} - -// EXTERNAL MODULE: external "path" -var external_path_ = __webpack_require__(622); - -// CONCATENATED MODULE: ./src/wrap-require.ts - -const wrapRequire = new Proxy(require, { - apply: (target, thisArg, [moduleID]) => { - if (moduleID.startsWith('.')) { - moduleID = Object(external_path_.resolve)(moduleID); - return target.apply(thisArg, [moduleID]); - } - const modulePath = target.resolve.apply(thisArg, [ - moduleID, - { - // Webpack does not have an escape hatch for getting the actual - // module, other than `eval`. - paths: [process.cwd()] - } - ]); - return target.apply(thisArg, [modulePath]); - }, - get: (target, prop, receiver) => { - Reflect.get(target, prop, receiver); - } -}); - -// CONCATENATED MODULE: ./src/main.ts - - - - - - - - -process.on('unhandledRejection', handleError); -main().catch(handleError); -async function main() { - const token = Object(core.getInput)('github-token', { required: true }); - const debug = Object(core.getInput)('debug'); - const userAgent = Object(core.getInput)('user-agent'); - const previews = Object(core.getInput)('previews'); - const retries = parseInt(Object(core.getInput)('retries')); - const retryAfter = parseInt(Object(core.getInput)('retry-after')); - const doNotRetry = parseNumberArray(Object(core.getInput)('do-not-retry')); - const opts = {}; - if (debug === 'true') - opts.log = console; - if (userAgent != null) - opts.userAgent = userAgent; - if (previews != null) - opts.previews = previews.split(','); - if (retries > 0) { - if (doNotRetry.length > 0) { - opts.retry = { doNotRetry }; - } - opts.request = { - retries, - retryAfter - }; - Object(core.info)(`GitHub client configured with: (retries: ${retries}, retryAfter: ${retryAfter}, doNotRetry: ${doNotRetry.length == 0 - ? 'octokit default: [400, 401, 403, 404, 422]' - : doNotRetry})`); - } - else { - opts.retry = { - enabled: false - }; - } - const github = Object(lib_github.getOctokit)(token, opts, dist_node.retry); - const script = Object(core.getInput)('script', { required: true }); - // Using property/value shorthand on `require` (e.g. `{require}`) causes compilation errors. - const result = await callAsyncFunction({ - require: wrapRequire, - __original_require__: require, - github, - context: lib_github.context, - core: core, - exec: exec, - glob: glob, - io: io - }, script); - let encoding = Object(core.getInput)('result-encoding'); - encoding = encoding ? encoding : 'json'; - let output; - switch (encoding) { - case 'json': - output = JSON.stringify(result); - break; - case 'string': - output = String(result); - break; - default: - throw new Error('"result-encoding" must be either "string" or "json"'); - } - Object(core.setOutput)('result', output); -} -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function handleError(err) { - console.error(err); - Object(core.setFailed)(`Unhandled error: ${err}`); -} -function parseNumberArray(listString) { - if (!listString) { - return []; - } - const split = listString.trim().split(','); - return split.map(x => parseInt(x)); -} - - /***/ }), /***/ 274: @@ -13449,6 +13305,160 @@ function expand(str, isTop) { +/***/ }), + +/***/ 858: +/***/ (function(__unusedmodule, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); + +// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js +var core = __webpack_require__(186); + +// EXTERNAL MODULE: ./node_modules/@actions/exec/lib/exec.js +var exec = __webpack_require__(514); + +// EXTERNAL MODULE: ./node_modules/@actions/github/lib/github.js +var lib_github = __webpack_require__(438); + +// EXTERNAL MODULE: ./node_modules/@actions/glob/lib/glob.js +var glob = __webpack_require__(90); + +// EXTERNAL MODULE: ./node_modules/@actions/io/lib/io.js +var io = __webpack_require__(436); + +// EXTERNAL MODULE: ./node_modules/@octokit/plugin-retry/dist-node/index.js +var dist_node = __webpack_require__(745); + +// CONCATENATED MODULE: ./src/async-function.ts +const AsyncFunction = Object.getPrototypeOf(async () => null).constructor; +function callAsyncFunction(args, source) { + const fn = new AsyncFunction(...Object.keys(args), source); + return fn(...Object.values(args)); +} + +// CONCATENATED MODULE: ./src/retry-options.ts + +function getRetryOptions(retries, retryAfter, doNotRetry) { + var _a; + if (retries <= 0) { + return [{ enabled: false }, {}]; + } + const retryOptions = { + enabled: true + }; + if (doNotRetry.length > 0) { + retryOptions.doNotRetry = doNotRetry; + } + const requestOptions = { + 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]'})`); + return [retryOptions, requestOptions]; +} +function parseNumberArray(listString) { + if (!listString) { + return []; + } + const split = listString.trim().split(','); + return split.map(x => parseInt(x)); +} + +// EXTERNAL MODULE: external "path" +var external_path_ = __webpack_require__(622); + +// CONCATENATED MODULE: ./src/wrap-require.ts + +const wrapRequire = new Proxy(require, { + apply: (target, thisArg, [moduleID]) => { + if (moduleID.startsWith('.')) { + moduleID = Object(external_path_.resolve)(moduleID); + return target.apply(thisArg, [moduleID]); + } + const modulePath = target.resolve.apply(thisArg, [ + moduleID, + { + // Webpack does not have an escape hatch for getting the actual + // module, other than `eval`. + paths: [process.cwd()] + } + ]); + return target.apply(thisArg, [modulePath]); + }, + get: (target, prop, receiver) => { + Reflect.get(target, prop, receiver); + } +}); + +// CONCATENATED MODULE: ./src/main.ts + + + + + + + + + +process.on('unhandledRejection', handleError); +main().catch(handleError); +async function main() { + const token = Object(core.getInput)('github-token', { required: true }); + const debug = Object(core.getInput)('debug'); + const userAgent = Object(core.getInput)('user-agent'); + const previews = Object(core.getInput)('previews'); + const retries = parseInt(Object(core.getInput)('retries')); + const retryAfter = parseInt(Object(core.getInput)('retry-after')); + const doNotRetry = parseNumberArray(Object(core.getInput)('do-not-retry')); + const [retryOpts, requestOpts] = getRetryOptions(retries, retryAfter, doNotRetry); + const opts = {}; + if (debug === 'true') + opts.log = console; + if (userAgent != null) + opts.userAgent = userAgent; + if (previews != null) + opts.previews = previews.split(','); + if (retryOpts) + opts.retry = retryOpts; + if (requestOpts) + opts.request = requestOpts; + const github = Object(lib_github.getOctokit)(token, opts, dist_node.retry); + const script = Object(core.getInput)('script', { required: true }); + // Using property/value shorthand on `require` (e.g. `{require}`) causes compilation errors. + const result = await callAsyncFunction({ + require: wrapRequire, + __original_require__: require, + github, + context: lib_github.context, + core: core, + exec: exec, + glob: glob, + io: io + }, script); + let encoding = Object(core.getInput)('result-encoding'); + encoding = encoding ? encoding : 'json'; + let output; + switch (encoding) { + case 'json': + output = JSON.stringify(result); + break; + case 'string': + output = String(result); + break; + default: + throw new Error('"result-encoding" must be either "string" or "json"'); + } + Object(core.setOutput)('result', output); +} +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function handleError(err) { + console.error(err); + Object(core.setFailed)(`Unhandled error: ${err}`); +} + + /***/ }), /***/ 871: diff --git a/src/main.ts b/src/main.ts index f80994f..5027c66 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,12 @@ import * as glob from '@actions/glob' import * as io from '@actions/io' import {retry} from '@octokit/plugin-retry' import {callAsyncFunction} from './async-function' +import { + getRetryOptions, + parseNumberArray, + RequestOptions, + RetryOptions +} from './retry-options' import {wrapRequire} from './wrap-require' process.on('unhandledRejection', handleError) @@ -14,14 +20,8 @@ type Options = { log?: Console userAgent?: string previews?: string[] - retry?: { - doNotRetry?: number[] - enabled?: boolean - } - request?: { - retries: number - retryAfter: number - } + retry?: RetryOptions + request?: RequestOptions } async function main(): Promise { @@ -32,34 +32,18 @@ async function main(): Promise { const retries = parseInt(core.getInput('retries')) const retryAfter = parseInt(core.getInput('retry-after')) const doNotRetry = parseNumberArray(core.getInput('do-not-retry')) + const [retryOpts, requestOpts] = getRetryOptions( + retries, + retryAfter, + doNotRetry + ) const opts: Options = {} if (debug === 'true') opts.log = console if (userAgent != null) opts.userAgent = userAgent if (previews != null) opts.previews = previews.split(',') - - if (retries > 0) { - if (doNotRetry.length > 0) { - opts.retry = {doNotRetry} - } - - opts.request = { - retries, - retryAfter - } - - core.info( - `GitHub client configured with: (retries: ${retries}, retryAfter: ${retryAfter}, doNotRetry: ${ - doNotRetry.length == 0 - ? 'octokit default: [400, 401, 403, 404, 422]' - : doNotRetry - })` - ) - } else { - opts.retry = { - enabled: false - } - } + if (retryOpts) opts.retry = retryOpts + if (requestOpts) opts.request = requestOpts const github = getOctokit(token, opts, retry) @@ -104,12 +88,3 @@ function handleError(err: any): void { console.error(err) core.setFailed(`Unhandled error: ${err}`) } - -function parseNumberArray(listString: string): number[] { - if (!listString) { - return [] - } - - const split = listString.trim().split(',') - return split.map(x => parseInt(x)) -} diff --git a/src/retry-options.ts b/src/retry-options.ts new file mode 100644 index 0000000..2c32dde --- /dev/null +++ b/src/retry-options.ts @@ -0,0 +1,53 @@ +import * as core from '@actions/core' + +export type RetryOptions = { + doNotRetry?: number[] + enabled?: boolean +} + +export type RequestOptions = { + retries?: number + retryAfter?: number +} + +export function getRetryOptions( + retries: number, + retryAfter: number, + doNotRetry: number[] +): [RetryOptions, RequestOptions] { + if (retries <= 0) { + return [{enabled: false}, {}] + } + + const retryOptions: RetryOptions = { + enabled: true + } + + if (doNotRetry.length > 0) { + retryOptions.doNotRetry = doNotRetry + } + + const requestOptions: RequestOptions = { + retries, + retryAfter: retryAfter + } + + core.info( + `GitHub client configured with: (retries: ${ + requestOptions.retries + }, retryAfter: ${requestOptions.retryAfter}, doNotRetry: ${ + retryOptions?.doNotRetry ?? 'octokit default: [400, 401, 403, 404, 422]' + })` + ) + + return [retryOptions, requestOptions] +} + +export function parseNumberArray(listString: string): number[] { + if (!listString) { + return [] + } + + const split = listString.trim().split(',') + return split.map(x => parseInt(x)) +}