Skip to content

Commit aa60f67

Browse files
committed
fix: Use '@octokit/plugin-throttling' to avoid rate limits
1 parent 6e121fd commit aa60f67

File tree

9 files changed

+146
-12
lines changed

9 files changed

+146
-12
lines changed

.github/actions/file/package-lock.json

Lines changed: 24 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/actions/file/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
"type": "module",
1515
"dependencies": {
1616
"@actions/core": "^1.11.1",
17-
"@octokit/core": "^7.0.3"
17+
"@octokit/core": "^7.0.3",
18+
"@octokit/plugin-throttling": "^11.0.1"
1819
},
1920
"devDependencies": {
2021
"@types/node": "^24.3.0",
2122
"typescript": "^5.8.3"
2223
}
23-
}
24+
}

.github/actions/file/src/index.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import type { Finding } from "./types.d.js";
22
import process from "node:process";
33
import core from "@actions/core";
4-
import { Octokit } from '@octokit/core';
4+
import { Octokit } from "@octokit/core";
5+
import { throttling } from "@octokit/plugin-throttling";
56
import { toFindingsMap } from "./toFindingsMap.js"
67
import { closeIssueForFinding } from "./closeIssueForFinding.js";
78
import { openIssueForFinding } from "./openIssueForFinding.js";
9+
const OctokitWithThrottling = Octokit.plugin(throttling);
810

911
export default async function () {
1012
core.info("Started 'file' action");
@@ -19,7 +21,25 @@ export default async function () {
1921
const findingsMap = toFindingsMap(findings);
2022
const cachedFindingsMap = toFindingsMap(cachedFindings);
2123

22-
const octokit = new Octokit({ auth: token });
24+
const octokit = new OctokitWithThrottling({
25+
auth: token,
26+
throttle: {
27+
onRateLimit: (retryAfter, options, octokit, retryCount) => {
28+
octokit.log.warn(`Request quota exhausted for request ${options.method} ${options.url}`);
29+
if (retryCount < 3) {
30+
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
31+
return true;
32+
}
33+
},
34+
onSecondaryRateLimit: (retryAfter, options, octokit, retryCount) => {
35+
octokit.log.warn(`Secondary rate limit hit for request ${options.method} ${options.url}`);
36+
if (retryCount < 3) {
37+
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
38+
return true;
39+
}
40+
},
41+
}
42+
});
2343
const closedIssueUrls = [];
2444
const openedIssueUrls = [];
2545
const repeatIssueUrls = [];

.github/actions/fix/package-lock.json

Lines changed: 24 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/actions/fix/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
"type": "module",
1515
"dependencies": {
1616
"@actions/core": "^1.11.1",
17-
"@octokit/core": "^7.0.3"
17+
"@octokit/core": "^7.0.3",
18+
"@octokit/plugin-throttling": "^11.0.1"
1819
},
1920
"devDependencies": {
2021
"@types/node": "^24.3.0",
2122
"typescript": "^5.8.3"
2223
}
23-
}
24+
}

.github/actions/fix/src/index.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import process from "node:process";
22
import core from "@actions/core";
3-
import { Octokit } from '@octokit/core';
3+
import { Octokit } from "@octokit/core";
4+
import { throttling } from "@octokit/plugin-throttling";
45
import { fixIssue } from "./fixIssue.js";
6+
const OctokitWithThrottling = Octokit.plugin(throttling);
57

68
export default async function () {
79
core.info("Started 'fix' action");
@@ -11,7 +13,25 @@ export default async function () {
1113
core.debug(`Input: 'issue_urls: ${JSON.stringify(issueUrls)}'`);
1214
core.debug(`Input: 'repository: ${repoWithOwner}'`);
1315

14-
const octokit = new Octokit({ auth: token });
16+
const octokit = new OctokitWithThrottling({
17+
auth: token,
18+
throttle: {
19+
onRateLimit: (retryAfter, options, octokit, retryCount) => {
20+
octokit.log.warn(`Request quota exhausted for request ${options.method} ${options.url}`);
21+
if (retryCount < 3) {
22+
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
23+
return true;
24+
}
25+
},
26+
onSecondaryRateLimit: (retryAfter, options, octokit, retryCount) => {
27+
octokit.log.warn(`Secondary rate limit hit for request ${options.method} ${options.url}`);
28+
if (retryCount < 3) {
29+
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
30+
return true;
31+
}
32+
},
33+
}
34+
});
1535
for (const issueUrl of issueUrls) {
1636
try {
1737
await fixIssue(octokit, repoWithOwner, issueUrl);

package-lock.json

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
"devDependencies": {
1919
"@actions/core": "^1.11.1",
2020
"@octokit/core": "^7.0.3",
21+
"@octokit/plugin-throttling": "^11.0.1",
2122
"@octokit/types": "^14.1.0",
2223
"@types/node": "^24.3.0",
2324
"vitest": "^3.2.4"
2425
}
25-
}
26+
}

tests/site-with-errors.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import type { Finding } from "./types.d.js";
33
import fs from "node:fs";
44
import { describe, it, expect, beforeAll } from "vitest";
55
import { Octokit } from "@octokit/core";
6+
import { throttling } from "@octokit/plugin-throttling";
7+
const OctokitWithThrottling = Octokit.plugin(throttling);
68

79
describe("site-with-errors", () => {
810
let findings: Finding[];
@@ -99,7 +101,25 @@ describe("site-with-errors", () => {
99101
let pullRequests: Endpoints["GET /repos/{owner}/{repo}/pulls/{pull_number}"]["response"]["data"][];
100102

101103
beforeAll(async () => {
102-
octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
104+
octokit = new OctokitWithThrottling({
105+
auth: process.env.GITHUB_TOKEN,
106+
throttle: {
107+
onRateLimit: (retryAfter, options, octokit, retryCount) => {
108+
octokit.log.warn(`Request quota exhausted for request ${options.method} ${options.url}`);
109+
if (retryCount < 3) {
110+
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
111+
return true;
112+
}
113+
},
114+
onSecondaryRateLimit: (retryAfter, options, octokit, retryCount) => {
115+
octokit.log.warn(`Secondary rate limit hit for request ${options.method} ${options.url}`);
116+
if (retryCount < 3) {
117+
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
118+
return true;
119+
}
120+
},
121+
}
122+
});
103123
// Fetch issues referenced in the findings file
104124
issues = await Promise.all(findings.map(async ({ issueUrl }) => {
105125
expect(issueUrl).toBeDefined();

0 commit comments

Comments
 (0)