Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion action/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -230025,7 +230025,9 @@ async function fetchRulesets(client, basePath, budget) {
`${basePath}?per_page=${PER_PAGE3}&page=${page}`
);
} catch (err) {
if (err instanceof Error && err.message.includes("404")) return [];
if (err instanceof Error && (err.message.includes("404") || err.message.includes("403"))) {
return [];
}
throw err;
}
if (!Array.isArray(batch) || batch.length === 0) break;
Expand Down
10 changes: 10 additions & 0 deletions src/cycles/rulesets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ describe("fetchRulesets", () => {
expect(live).toEqual([]);
});

it("returns empty on a 403 (App lacks permission for this rulesets scope)", async () => {
const client: MockClient = makeMockClient();
client.request = async <T = unknown>(method: string, path: string): Promise<T> => {
client.calls.push({ method, path });
throw new Error("GET /orgs/test-org/rulesets returned 403: Resource not accessible by integration");
};
const live = await fetchRulesets(client, "/orgs/test-org/rulesets", makeBudget());
expect(live).toEqual([]);
});

it("charges the budget: one list page + one detail per ruleset", async () => {
const client = makeMockClient({
"GET /orgs/test-org/rulesets?per_page=100&page=1": [
Expand Down
8 changes: 6 additions & 2 deletions src/cycles/rulesets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ const PER_PAGE = 100;
* `/repos/{o}/{r}/rulesets`): list (paginated) then GET each ruleset's detail
* so `rules`/`conditions`/`bypassActors` are populated for diffing. Charges the
* budget per request and stops when exhausted. A 404 (rulesets unsupported /
* repo missing) yields an empty list.
* repo missing) or 403 (the App lacks permission for this rulesets scope — e.g.
* org rulesets) yields an empty list rather than aborting the cycle, so an
* inaccessible org-rulesets read never blocks repo-rulesets reconciliation.
*/
export async function fetchRulesets(
client: AppClient,
Expand All @@ -102,7 +104,9 @@ export async function fetchRulesets(
`${basePath}?per_page=${PER_PAGE}&page=${page}`,
);
} catch (err) {
if (err instanceof Error && err.message.includes("404")) return [];
if (err instanceof Error && (err.message.includes("404") || err.message.includes("403"))) {
return [];
}
throw err;
}
if (!Array.isArray(batch) || batch.length === 0) break;
Expand Down
Loading