Skip to content

fix: stop unbounded pagination in check_rate_limit when run exceeds threshold - #48972

Merged
pelikhan merged 4 commits into
mainfrom
copilot/aw-failures-fix-rate-limit-check
Jul 29, 2026
Merged

fix: stop unbounded pagination in check_rate_limit when run exceeds threshold#48972
pelikhan merged 4 commits into
mainfrom
copilot/aw-failures-fix-rate-limit-check

Conversation

Copilot AI commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

listWorkflowRuns returns runs newest-first, so the first run found older than the threshold means all remaining runs (current page and beyond) are also past it. The loop was continue-ing anyway, causing every AI Moderator invocation to page through the entire run history — confirmed reaching page 250 with runs back to January 2026 before CI force-cancelled the step (37% failure rate over 6h).

Change

In actions/setup/js/check_rate_limit.cjs, replace continue with hasMore = false; break when a run predates the threshold:

// Before — kept scanning despite guaranteed-stale remaining pages
if (runCreatedAt < thresholdTime) {
  core.info(`   Skipping run ${run.id} - created before threshold (${run.created_at})`);
  continue;
}

// After — stops pagination immediately
if (runCreatedAt < thresholdTime) {
  core.info(`   Stopping pagination - run ${run.id} created before threshold (${run.created_at})`);
  hasMore = false;
  break;
}

Run: https://github.com/github/gh-aw/actions/runs/30488631737

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 9.5 AIC · ⌖ 6.31 AIC · ⊞ 7.8K ·
Comment /souschef to run again

…than threshold

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix AI Moderator rate-limit check for unbounded pagination timeout fix: stop unbounded pagination in check_rate_limit when run exceeds threshold Jul 29, 2026
Copilot AI requested a review from pelikhan July 29, 2026 19:48
@pelikhan
pelikhan marked this pull request as ready for review July 29, 2026 19:51
Copilot AI review requested due to automatic review settings July 29, 2026 19:51
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #48972 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100). The single changed file is not in a monitored business logic directory.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Stops rate-limit pagination once workflow runs exceed the time window, preventing costly full-history scans.

Changes:

  • Detects the first stale run in newest-first results.
  • Stops processing and pagination immediately.
Show a summary per file
File Description
actions/setup/js/check_rate_limit.cjs Terminates pagination at the time-window boundary.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Medium

continue;
core.info(` Stopping pagination - run ${run.id} created before threshold (${run.created_at})`);
hasMore = false;
break;
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Warning

threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.

Details

The threat detection engine failed to produce results.

Review the workflow run logs for details.

No behavioral tests were added or modified in this PR. The change is a production-only bug fix to check_rate_limit.cjs. Test Quality Sentinel review completed and comment posted. No test quality verdict applicable.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is correct and minimal. Since listWorkflowRuns returns runs newest-first, the first run older than thresholdTime guarantees all remaining runs (and future pages) are also past the threshold. Replacing continue with hasMore = false; break correctly short-circuits the outer pagination loop, eliminating the unbounded scan that was causing 250-page walks and 37% CI failures. No issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 11.3 AIC · ⌖ 5.92 AIC · ⊞ 5.3K

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — one actionable finding, otherwise clean.

📋 Key Themes & Highlights

Key Themes

  • Missing regression test: The fix correctly stops pagination but there is no test that asserts listWorkflowRuns is called only once when a stale run is encountered. The existing threshold test validates the count of matched runs, not whether pagination halts — so a future continue reintroduction would pass silently.

Positive Highlights

  • ✅ Root cause is fully addressed: the API ordering guarantee (newest-first) is now leveraged to stop early, not just skip.
  • hasMore = false + break is the correct dual-signal idiom for this loop structure — both the inner for and the outer while are terminated.
  • ✅ Updated log message (Stopping pagination vs. Skipping run) clearly communicates the new intent.
  • ✅ Surgical 4-line change with zero risk of collateral damage.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 26.3 AIC · ⌖ 5 AIC · ⊞ 7K
Comment /matt to run again

continue;
core.info(` Stopping pagination - run ${run.id} created before threshold (${run.created_at})`);
hasMore = false;
break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The existing test "should exclude runs older than the time window" does not assert that pagination stops — it only checks the count. With the old continue the test would still pass, meaning this regression can silently reappear.

💡 Suggested regression test
it("should stop pagination when a run predates the threshold", async () => {
  // First page has one stale run (older than window)
  mockGithub.rest.actions.listWorkflowRuns
    .mockResolvedValueOnce({
      data: {
        workflow_runs: [{
          id: 999,
          run_number: 1,
          created_at: new Date(Date.now() - 120 * 60 * 1000).toISOString(),
          actor: { login: "test-user" },
          status: "completed",
        }],
      },
    })
    .mockResolvedValue({ data: { workflow_runs: [] } });

  await checkRateLimit.main();

  // Must only call once — page 2 should never be fetched
  expect(mockGithub.rest.actions.listWorkflowRuns).toHaveBeenCalledTimes(1);
  expect(mockCore.info).toHaveBeenCalledWith(
    expect.stringContaining("Stopping pagination")
  );
});

Without this, a future continue reintroduction would go undetected.

@copilot please address this.

@github-actions

Copy link
Copy Markdown
Contributor

Warning

threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.

Details

The threat detection engine failed to produce results.

Review the workflow run logs for details.

🧪 Test Quality Sentinel Report

Test Quality Score: N/A — No Test Changes

This PR modifies only production code (actions/setup/js/check_rate_limit.cjs). No test files were added or modified.

Summary

Item Status
Test files added 0
Test files modified 0
Behavioral tests added 0
🚨 Violations 0

Context

This PR fixes an unbounded pagination bug in check_rate_limit.cjs by stopping (instead of skipping) when a run is older than the time threshold. While this is a behavioral fix, no corresponding test changes were made.

Verdict

Passed. No tests to evaluate — this is a production-only change. Consider adding or updating integration tests for the pagination logic in a follow-up PR if not already covered.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 7.79 AIC · ⊞ 8.4K ·
Comment /review to run again

@github-actions github-actions Bot mentioned this pull request Jul 29, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: Approve with a minor test-coverage suggestion

The fix is logically correct: since listWorkflowRuns returns runs newest-first, hitting one run older than the threshold means all subsequent runs are also stale, so hasMore = false; break correctly halts pagination instead of the old continue which scanned the full run history.

💡 Themes
  • No regression test added for the specific incident (unbounded pagination). See inline comment.
  • The newest-first ordering assumption from the GitHub API is relied upon implicitly; worth a comment or assertion in tests.
  • Change is minimal, scoped, and matches the described root cause.

🔎 Code quality review by PR Code Quality Reviewer · aut00 · 27.6 AIC · ⌖ 7.11 AIC · ⊞ 7.8K
Comment /review to run again

core.info(` Skipping run ${run.id} - created before threshold (${run.created_at})`);
continue;
core.info(` Stopping pagination - run ${run.id} created before threshold (${run.created_at})`);
hasMore = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct fix logically, but no regression test was added for this exact incident (unbounded pagination when a run predates the threshold) — the bug that caused a 37% failure rate for 6h will have no test guarding against reintroduction.

💡 Add a targeted test

The fix relies on the undocumented-in-code assumption that listWorkflowRuns returns runs newest-first (true by API default, but not enforced/asserted anywhere). A test mocking a paginated response where an early run in page 1 is older than thresholdTime, followed by mock pages that would need many more calls if pagination continued, would catch a future regression to continue and also validate this ordering assumption. Consider asserting github.rest.actions.listWorkflowRuns is called exactly once in that scenario.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the skill, investigate the failed check below, and rerun the relevant checks once fixed.

Failed checks:

Run: https://github.com/github/gh-aw/actions/runs/30488631737

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 9.5 AIC · ⌖ 6.31 AIC · ⊞ 7.8K ·
Comment /souschef to run again

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the skill, investigate the failed check below, and rerun the relevant checks once fixed.

Failed checks:...

Fixed in commit fix: reorder test fixture to newest-first and add pagination assertion. The should exclude runs older than the time window test fixture now lists runs in newest-first order (recent run 222222 before old run 111111) to match the API contract. Also switched to mockResolvedValueOnce and added toHaveBeenCalledTimes(1) to assert that hitting the old run on page 1 prevents page 2 from being fetched. All 31 tests pass locally.

Copilot AI requested a review from gh-aw-bot July 29, 2026 20:41
@pelikhan
pelikhan merged commit 6d8c50b into main Jul 29, 2026
8 of 9 checks passed
@pelikhan
pelikhan deleted the copilot/aw-failures-fix-rate-limit-check branch July 29, 2026 20:46
Copilot stopped work on behalf of pelikhan due to an error July 29, 2026 20:46
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.84.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[aw-failures] Fix AI Moderator rate-limit check: unbounded pagination times out pre_activation (7 failures/6h)

4 participants