From 1618e91da69b9fe614fb9837ac673ea4600eb529 Mon Sep 17 00:00:00 2001 From: dessant Date: Mon, 12 Jun 2023 20:42:07 +0300 Subject: [PATCH] fix: retry and throttle GitHub API requests Closes #35. --- package-lock.json | 132 +++++++++++++++++++++++++++++++++++++++++++--- package.json | 2 + src/index.js | 3 +- src/utils.js | 36 +++++++++++++ 4 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 src/utils.js diff --git a/package-lock.json b/package-lock.json index 0825484..527a015 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,8 @@ "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", + "@octokit/plugin-retry": "^4.1.6", + "@octokit/plugin-throttling": "^5.2.3", "joi": "^17.9.2" }, "devDependencies": { @@ -465,6 +467,62 @@ "@octokit/core": ">=3" } }, + "node_modules/@octokit/plugin-retry": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-4.1.6.tgz", + "integrity": "sha512-obkYzIgEC75r8+9Pnfiiqy3y/x1bc3QLE5B7qvv9wi9Kj0R5tGQFC6QMBg1154WQ9lAVypuQDGyp3hNpp15gQQ==", + "dependencies": { + "@octokit/types": "^9.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.1.tgz", + "integrity": "sha512-zfJzyXLHC42sWcn2kS+oZ/DRvFZBYCCbfInZtwp1Uopl1qh6pRg4NSP/wFX1xCOpXvEkctiG1sxlSlkZmzvxdw==", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-5.2.3.tgz", + "integrity": "sha512-C9CFg9mrf6cugneKiaI841iG8DOv6P5XXkjmiNNut+swePxQ7RWEdAZRp5rJoE1hjsIqiYcKa/ZkOQ+ujPI39Q==", + "dependencies": { + "@octokit/types": "^9.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": "^4.0.0" + } + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.1.tgz", + "integrity": "sha512-zfJzyXLHC42sWcn2kS+oZ/DRvFZBYCCbfInZtwp1Uopl1qh6pRg4NSP/wFX1xCOpXvEkctiG1sxlSlkZmzvxdw==", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, "node_modules/@octokit/request": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", @@ -866,6 +924,11 @@ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==" + }, "node_modules/boxen": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.0.tgz", @@ -5787,14 +5850,14 @@ } }, "node_modules/tuf-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.6.tgz", - "integrity": "sha512-CXwFVIsXGbVY4vFiWF7TJKWmlKJAT8TWkH4RmiohJRcDJInix++F0dznDmoVbtJNzZ8yLprKUG4YrDIhv3nBMg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", "dev": true, "dependencies": { "@tufjs/models": "1.0.4", "debug": "^4.3.4", - "make-fetch-happen": "^11.1.0" + "make-fetch-happen": "^11.1.1" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -6656,6 +6719,54 @@ "deprecation": "^2.3.1" } }, + "@octokit/plugin-retry": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-4.1.6.tgz", + "integrity": "sha512-obkYzIgEC75r8+9Pnfiiqy3y/x1bc3QLE5B7qvv9wi9Kj0R5tGQFC6QMBg1154WQ9lAVypuQDGyp3hNpp15gQQ==", + "requires": { + "@octokit/types": "^9.0.0", + "bottleneck": "^2.15.3" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" + }, + "@octokit/types": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.1.tgz", + "integrity": "sha512-zfJzyXLHC42sWcn2kS+oZ/DRvFZBYCCbfInZtwp1Uopl1qh6pRg4NSP/wFX1xCOpXvEkctiG1sxlSlkZmzvxdw==", + "requires": { + "@octokit/openapi-types": "^18.0.0" + } + } + } + }, + "@octokit/plugin-throttling": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-5.2.3.tgz", + "integrity": "sha512-C9CFg9mrf6cugneKiaI841iG8DOv6P5XXkjmiNNut+swePxQ7RWEdAZRp5rJoE1hjsIqiYcKa/ZkOQ+ujPI39Q==", + "requires": { + "@octokit/types": "^9.0.0", + "bottleneck": "^2.15.3" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" + }, + "@octokit/types": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.1.tgz", + "integrity": "sha512-zfJzyXLHC42sWcn2kS+oZ/DRvFZBYCCbfInZtwp1Uopl1qh6pRg4NSP/wFX1xCOpXvEkctiG1sxlSlkZmzvxdw==", + "requires": { + "@octokit/openapi-types": "^18.0.0" + } + } + } + }, "@octokit/request": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", @@ -6981,6 +7092,11 @@ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, + "bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==" + }, "boxen": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.0.tgz", @@ -10691,14 +10807,14 @@ "dev": true }, "tuf-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.6.tgz", - "integrity": "sha512-CXwFVIsXGbVY4vFiWF7TJKWmlKJAT8TWkH4RmiohJRcDJInix++F0dznDmoVbtJNzZ8yLprKUG4YrDIhv3nBMg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", "dev": true, "requires": { "@tufjs/models": "1.0.4", "debug": "^4.3.4", - "make-fetch-happen": "^11.1.0" + "make-fetch-happen": "^11.1.1" }, "dependencies": { "make-fetch-happen": { diff --git a/package.json b/package.json index fc84939..2853244 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,8 @@ "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", + "@octokit/plugin-throttling": "^5.2.3", + "@octokit/plugin-retry": "^4.1.6", "joi": "^17.9.2" }, "devDependencies": { diff --git a/src/index.js b/src/index.js index 59b0da4..1858311 100644 --- a/src/index.js +++ b/src/index.js @@ -2,11 +2,12 @@ const core = require('@actions/core'); const github = require('@actions/github'); const schema = require('./schema'); +const {getClient} = require('./utils'); async function run() { try { const config = getConfig(); - const client = github.getOctokit(config['github-token']); + const client = getClient(config['github-token']); const app = new App(config, client); await app.lockThreads(); diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..54ed5bc --- /dev/null +++ b/src/utils.js @@ -0,0 +1,36 @@ +const core = require('@actions/core'); +const github = require('@actions/github'); +const {retry} = require('@octokit/plugin-retry'); +const {throttling} = require('@octokit/plugin-throttling'); + +function getClient(token) { + const rateLimitRetries = 3; + + const rateLimitCallback = function ( + retryAfter, + options, + octokit, + retryCount + ) { + core.info( + `Request quota exhausted for request ${options.method} ${options.url}` + ); + + if (retryCount < rateLimitRetries) { + core.info(`Retrying after ${retryAfter} seconds`); + + return true; + } + }; + + const options = { + throttle: { + onSecondaryRateLimit: rateLimitCallback, + onRateLimit: rateLimitCallback + } + }; + + return github.getOctokit(token, options, retry, throttling); +} + +module.exports = {getClient};