diff --git a/dist/index.js b/dist/index.js index fb93d046af..d906825fda 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1390,6 +1390,7 @@ class GitHubHelper { options.baseUrl = 'https://api.github.com'; } options.throttle = octokit_client_1.throttleOptions; + options.retry = octokit_client_1.retryOptions; this.octokit = new octokit_client_1.Octokit(options); } parseRepository(repository) { @@ -1819,14 +1820,15 @@ var __importStar = (this && this.__importStar) || (function () { }; })(); Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.throttleOptions = exports.Octokit = void 0; +exports.retryOptions = exports.throttleOptions = exports.Octokit = void 0; const core = __importStar(__nccwpck_require__(7484)); -const core_1 = __nccwpck_require__(767); +const core_1 = __nccwpck_require__(708); const plugin_paginate_rest_1 = __nccwpck_require__(3779); const plugin_rest_endpoint_methods_1 = __nccwpck_require__(9210); +const plugin_retry_1 = __nccwpck_require__(9735); const plugin_throttling_1 = __nccwpck_require__(6856); const proxy_1 = __nccwpck_require__(3459); -exports.Octokit = core_1.Octokit.plugin(plugin_paginate_rest_1.paginateRest, plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_throttling_1.throttling, autoProxyAgent); +exports.Octokit = core_1.Octokit.plugin(plugin_paginate_rest_1.paginateRest, plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_retry_1.retry, plugin_throttling_1.throttling, autoProxyAgent); exports.throttleOptions = { onRateLimit: (retryAfter, options, _, retryCount) => { core.debug(`Hit rate limit for request ${options.method} ${options.url}`); @@ -1841,6 +1843,10 @@ exports.throttleOptions = { core.warning(`Requests may be retried after ${retryAfter} seconds.`); } }; +exports.retryOptions = { + // 429 is handled by the throttling plugin, so we exclude it from retry + doNotRetry: [400, 401, 403, 404, 410, 422, 429, 451] +}; // Octokit plugin to support the standard environment variables http_proxy, https_proxy and no_proxy function autoProxyAgent(octokit) { octokit.hook.before('request', options => { @@ -32216,7 +32222,7 @@ module.exports = fetch; /***/ }), -/***/ 767: +/***/ 708: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nccwpck_require__) => { "use strict"; @@ -32736,46 +32742,8 @@ var endpoint = withDefaults(null, DEFAULTS); // EXTERNAL MODULE: ./node_modules/fast-content-type-parse/index.js var fast_content_type_parse = __nccwpck_require__(8739); -;// CONCATENATED MODULE: ./node_modules/@octokit/request-error/dist-src/index.js -class RequestError extends Error { - name; - /** - * http status code - */ - status; - /** - * Request options that lead to the error. - */ - request; - /** - * Response object if a response was received - */ - response; - constructor(message, statusCode, options) { - super(message); - this.name = "HttpError"; - this.status = Number.parseInt(statusCode); - if (Number.isNaN(this.status)) { - this.status = 0; - } - if ("response" in options) { - this.response = options.response; - } - const requestCopy = Object.assign({}, options.request); - if (options.request.headers.authorization) { - requestCopy.headers = Object.assign({}, options.request.headers, { - authorization: options.request.headers.authorization.replace( - /(?= 400) { octokitResponse.data = await getResponseData(fetchResponse); - throw new RequestError(toErrorMessage(octokitResponse.data), status, { + throw new dist_src/* RequestError */.G(toErrorMessage(octokitResponse.data), status, { response: octokitResponse, request: requestOptions }); @@ -36195,6 +36163,98 @@ legacyRestEndpointMethods.VERSION = VERSION; //# sourceMappingURL=index.js.map +/***/ }), + +/***/ 9735: +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nccwpck_require__) => { + +"use strict"; +__nccwpck_require__.r(__webpack_exports__); +/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { +/* harmony export */ VERSION: () => (/* binding */ VERSION), +/* harmony export */ retry: () => (/* binding */ retry) +/* harmony export */ }); +/* harmony import */ var bottleneck_light_js__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(3251); +/* harmony import */ var _octokit_request_error__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(1015); +// pkg/dist-src/version.js +var VERSION = "0.0.0-development"; + +// pkg/dist-src/error-request.js +async function errorRequest(state, octokit, error, options) { + if (!error.request || !error.request.request) { + throw error; + } + if (error.status >= 400 && !state.doNotRetry.includes(error.status)) { + const retries = options.request.retries != null ? options.request.retries : state.retries; + const retryAfter = Math.pow((options.request.retryCount || 0) + 1, 2); + throw octokit.retry.retryRequest(error, retries, retryAfter); + } + throw error; +} + +// pkg/dist-src/wrap-request.js + + +async function wrapRequest(state, octokit, request, options) { + const limiter = new bottleneck_light_js__WEBPACK_IMPORTED_MODULE_0__(); + limiter.on("failed", function(error, info) { + const maxRetries = ~~error.request.request.retries; + const after = ~~error.request.request.retryAfter; + options.request.retryCount = info.retryCount + 1; + if (maxRetries > info.retryCount) { + return after * state.retryAfterBaseValue; + } + }); + return limiter.schedule( + requestWithGraphqlErrorHandling.bind(null, state, octokit, request), + options + ); +} +async function requestWithGraphqlErrorHandling(state, octokit, request, options) { + const response = await request(request, options); + if (response.data && response.data.errors && response.data.errors.length > 0 && /Something went wrong while executing your query/.test( + response.data.errors[0].message + )) { + const error = new _octokit_request_error__WEBPACK_IMPORTED_MODULE_1__/* .RequestError */ .G(response.data.errors[0].message, 500, { + request: options, + response + }); + return errorRequest(state, octokit, error, options); + } + return response; +} + +// pkg/dist-src/index.js +function retry(octokit, octokitOptions) { + const state = Object.assign( + { + enabled: true, + retryAfterBaseValue: 1e3, + doNotRetry: [400, 401, 403, 404, 410, 422, 451], + retries: 3 + }, + octokitOptions.retry + ); + if (state.enabled) { + octokit.hook.error("request", errorRequest.bind(null, state, octokit)); + octokit.hook.wrap("request", wrapRequest.bind(null, state, octokit)); + } + return { + retry: { + retryRequest: (error, retries, retryAfter) => { + error.request.request = Object.assign({}, error.request.request, { + retries, + retryAfter + }); + return error; + } + } + }; +} +retry.VERSION = VERSION; + + + /***/ }), /***/ 6856: @@ -36434,6 +36494,55 @@ throttling.triggersNotification = triggersNotification; +/***/ }), + +/***/ 1015: +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nccwpck_require__) => { + +"use strict"; +/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { +/* harmony export */ G: () => (/* binding */ RequestError) +/* harmony export */ }); +class RequestError extends Error { + name; + /** + * http status code + */ + status; + /** + * Request options that lead to the error. + */ + request; + /** + * Response object if a response was received + */ + response; + constructor(message, statusCode, options) { + super(message); + this.name = "HttpError"; + this.status = Number.parseInt(statusCode); + if (Number.isNaN(this.status)) { + this.status = 0; + } + if ("response" in options) { + this.response = options.response; + } + const requestCopy = Object.assign({}, options.request); + if (options.request.headers.authorization) { + requestCopy.headers = Object.assign({}, options.request.headers, { + authorization: options.request.headers.authorization.replace( + /(?=6" } }, + "node_modules/@octokit/plugin-retry": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.2.1.tgz", + "integrity": "sha512-wUc3gv0D6vNHpGxSaR3FlqJpTXGWgqmk607N9L3LvPL4QjaxDgX/1nY2mGpT37Khn+nlIXdljczkRnNdTTV3/A==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^25.1.0" + } + }, "node_modules/@octokit/plugin-throttling": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.6.1.tgz", @@ -2478,6 +2513,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2983,6 +3019,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001640", "electron-to-chromium": "^1.4.820", @@ -3854,6 +3891,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -4100,6 +4138,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -5689,6 +5728,7 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -7233,6 +7273,7 @@ "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -8106,6 +8147,7 @@ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -8423,6 +8465,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 34cdedc973..32572fb849 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@octokit/core": "^6.1.6", "@octokit/plugin-paginate-rest": "^11.6.0", "@octokit/plugin-rest-endpoint-methods": "^13.5.0", + "@octokit/plugin-retry": "^7.2.1", "@octokit/plugin-throttling": "^9.6.1", "node-fetch-native": "^1.6.7", "p-limit": "^6.2.0", diff --git a/src/github-helper.ts b/src/github-helper.ts index 1779f7c165..85439dddf0 100644 --- a/src/github-helper.ts +++ b/src/github-helper.ts @@ -1,7 +1,12 @@ import * as core from '@actions/core' import {Inputs} from './create-pull-request' import {Commit, GitCommandManager} from './git-command-manager' -import {Octokit, OctokitOptions, throttleOptions} from './octokit-client' +import { + Octokit, + OctokitOptions, + retryOptions, + throttleOptions +} from './octokit-client' import pLimit from 'p-limit' import * as utils from './utils' @@ -52,6 +57,7 @@ export class GitHubHelper { options.baseUrl = 'https://api.github.com' } options.throttle = throttleOptions + options.retry = retryOptions this.octokit = new Octokit(options) } diff --git a/src/octokit-client.ts b/src/octokit-client.ts index 8c2c02addf..11b0e3a6fa 100644 --- a/src/octokit-client.ts +++ b/src/octokit-client.ts @@ -2,6 +2,7 @@ import * as core from '@actions/core' import {Octokit as OctokitCore} from '@octokit/core' import {paginateRest} from '@octokit/plugin-paginate-rest' import {restEndpointMethods} from '@octokit/plugin-rest-endpoint-methods' +import {retry} from '@octokit/plugin-retry' import {throttling} from '@octokit/plugin-throttling' import {fetch} from 'node-fetch-native/proxy' export {RestEndpointMethodTypes} from '@octokit/plugin-rest-endpoint-methods' @@ -11,6 +12,7 @@ export {OctokitOptions} from '@octokit/core/dist-types/types' export const Octokit = OctokitCore.plugin( paginateRest, restEndpointMethods, + retry, throttling, autoProxyAgent ) @@ -32,6 +34,11 @@ export const throttleOptions = { } } +export const retryOptions = { + // 429 is handled by the throttling plugin, so we exclude it from retry + doNotRetry: [400, 401, 403, 404, 410, 422, 429, 451] +} + // Octokit plugin to support the standard environment variables http_proxy, https_proxy and no_proxy function autoProxyAgent(octokit: OctokitCore) { octokit.hook.before('request', options => {