Skip to content

Commit 4ced537

Browse files
Copilotpelikhan
andauthored
refactor: extract isRateLimitError helper into error_helpers.cjs
Move the rate limit detection regex into a dedicated isRateLimitError() helper in error_helpers.cjs, following the same pattern as isLockedError(). Update check_skip_if_check_failing.cjs to use the helper. Add tests for isRateLimitError in error_helpers.test.cjs. Agent-Logs-Url: https://github.com/github/gh-aw/sessions/294a40fd-3964-43aa-a722-81fbd321cd18 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
1 parent e568e2c commit 4ced537

3 files changed

Lines changed: 49 additions & 4 deletions

File tree

actions/setup/js/check_skip_if_check_failing.cjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @ts-check
22
/// <reference types="@actions/github-script" />
33

4-
const { getErrorMessage } = require("./error_helpers.cjs");
4+
const { getErrorMessage, isRateLimitError } = require("./error_helpers.cjs");
55
const { ERR_API } = require("./error_codes.cjs");
66
const { getBaseBranch } = require("./get_base_branch.cjs");
77

@@ -217,7 +217,7 @@ async function main() {
217217
// due to transient GitHub API availability issues. When multiple workflows run
218218
// simultaneously, they can exhaust the installation API rate limit, causing this
219219
// check to fail. Failing open matches the behavior of other pre-activation checks.
220-
if (/\bapi rate limit\b|\brate limit exceeded\b/i.test(errorMsg)) {
220+
if (isRateLimitError(error)) {
221221
core.warning(`⚠️ API rate limit exceeded while checking CI status for ref "${ref}": ${errorMsg}`);
222222
core.warning(`Allowing workflow to proceed (fail-open on rate limit)`);
223223
core.setOutput("skip_if_check_failing_ok", "true");

actions/setup/js/error_helpers.cjs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,18 @@ function isLockedError(error) {
4040
return hasLockedMessage;
4141
}
4242

43-
module.exports = { getErrorMessage, isLockedError };
43+
/**
44+
* Check if an error is due to a GitHub API rate limit being exceeded.
45+
* This includes both installation-level and user-level rate limits.
46+
* Used to determine if a check should fail-open (allow workflow to proceed)
47+
* rather than hard-failing when the error is transient.
48+
*
49+
* @param {unknown} error - The error value to check
50+
* @returns {boolean} True if error is due to API rate limiting, false otherwise
51+
*/
52+
function isRateLimitError(error) {
53+
const errorMessage = getErrorMessage(error);
54+
return /\bapi rate limit\b|\brate limit exceeded\b/i.test(errorMessage);
55+
}
56+
57+
module.exports = { getErrorMessage, isLockedError, isRateLimitError };

actions/setup/js/error_helpers.test.cjs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, it, expect } from "vitest";
2-
import { getErrorMessage, isLockedError } from "./error_helpers.cjs";
2+
import { getErrorMessage, isLockedError, isRateLimitError } from "./error_helpers.cjs";
33

44
describe("error_helpers", () => {
55
describe("getErrorMessage", () => {
@@ -89,4 +89,35 @@ describe("error_helpers", () => {
8989
expect(isLockedError(error)).toBe(true);
9090
});
9191
});
92+
93+
describe("isRateLimitError", () => {
94+
it("should return true for 'API rate limit exceeded' message", () => {
95+
expect(isRateLimitError(new Error("API rate limit exceeded for installation"))).toBe(true);
96+
});
97+
98+
it("should return true for 'rate limit exceeded' message", () => {
99+
expect(isRateLimitError(new Error("rate limit exceeded: please retry after 60 seconds"))).toBe(true);
100+
});
101+
102+
it("should return true for mixed-case 'API Rate Limit' message", () => {
103+
expect(isRateLimitError(new Error("API Rate Limit exceeded"))).toBe(true);
104+
});
105+
106+
it("should return false for unrelated API errors", () => {
107+
expect(isRateLimitError(new Error("Network connection error"))).toBe(false);
108+
});
109+
110+
it("should return false for null error", () => {
111+
expect(isRateLimitError(null)).toBe(false);
112+
});
113+
114+
it("should return false for undefined error", () => {
115+
expect(isRateLimitError(undefined)).toBe(false);
116+
});
117+
118+
it("should return false for non-rate-limit 403 errors", () => {
119+
const error = new Error("Forbidden: insufficient permissions");
120+
expect(isRateLimitError(error)).toBe(false);
121+
});
122+
});
92123
});

0 commit comments

Comments
 (0)