Skip to content

pr-review-sweep: event-driven re-trigger to close the ci-pending→green latency gap (#898) - #914

Merged
don-petry merged 4 commits into
mainfrom
claude/pr-review-retrigger
Jun 23, 2026
Merged

pr-review-sweep: event-driven re-trigger to close the ci-pending→green latency gap (#898)#914
don-petry merged 4 commits into
mainfrom
claude/pr-review-retrigger

Conversation

@don-petry

@don-petry don-petry commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Closes #898. Part of the pr-review reliability work (related: #573, #619, #463, #617).

TL;DR — the issue's root cause was wrong; this fixes the real one

I traced the pr-review state machine against the #892 evidence (details in the investigation comment on #898):

  • The ci-pending skip exits 100 at review-one-pr.sh:184, before the idempotency check at :290, and writes no pr-review-agent v1 sha=… marker. So it's already non-terminal — the prescribed "don't persist the marker for reason=ci-pending" fix would be a no-op.
  • The "No-op (already reviewed)" line in the issue is just review-batch.sh:256's generic label for any exit-100, not a persisted marker.
  • The selection logic that re-reviews a stuck-green PR (REVIEW_REQUIRED + CI green + no marker) is correct and already covered (test_sweep_stuck_reviews.bats:74).

What actually stalled #892 was latency. The only thing that re-reviews a PR which goes green after the last trigger fired is the stuck-review sweep (#573), which ran hourly — so the PR could sit green-but-unreviewed for up to an hour. The human force-reviewed before the next tick. (I watched this same rate-limit/sweep machinery carry #905 to merge.)

The fix — two layered, robust triggers on pr-review-sweep.yml

Layer Trigger Role
Backstop cron tightened hourly → every 15 min Guaranteed upper bound on re-review latency; zero fragility
Fast path workflow_run: completed on the core CI workflows Near-instant: when CI finishes, the sweep runs scoped to just that run's PR(s) and re-reviews in seconds
  • sweep-stuck-reviews.sh gains a pure, unit-tested helper prs_from_workflow_run_event that derives the PR(s) from the event payload (.workflow_run.pull_requests[]), so the event path inspects one PR, not the whole fleet.
  • Per-branch cancel-in-progress concurrency collapses the multi-workflow burst, so the sweep effectively runs once, after the last-finishing keyed workflow (the one most likely to observe green).
  • The fast path can never strand a PR. If it matches nothing — fork PR, branch push, CI still pending, or a workflow rename — the scheduled sweep still catches it. The same REVIEW_REQUIRED + green + no-marker gate (and the rate-limited-marker handling) decides in every path.

Safety / cost notes for review

  • No change to pr-review-trigger.yml (thin caller stub) or to review-one-pr.sh's authoritative gating — only the sweep's when and candidate scoping.
  • Re-dispatch still requires GH_PAT_WORKFLOWS (GITHUB_TOKEN can't start dispatched runs); unchanged.
  • The workflows: name list is best-effort (must match each workflow's name:); it's not load-bearing because the cron backstops any miss.

Tests

  • 5 new cases in tests/test_sweep_stuck_reviews.bats for the workflow_run path: ci-pending→green dispatches (scoped to the event), empty pull_requests is a clean no-op, a too-early fire (CI still pending) does not dispatch, an already-reviewed-at-head PR is not re-dispatched, and a multi-PR run evaluates each independently.
  • All 26 sweep tests green (21 existing unchanged); shellcheck --severity=warning -x clean; workflow YAML validated.
  • AGENTS.md exception note updated to describe both triggers.

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • Chores

    • Updated PR review sweep automation to run every 15 minutes instead of hourly
    • Added event-driven trigger that activates when CI workflows complete
    • Improved workflow concurrency handling to prevent cross-branch interference
    • Updated documentation for workflow behavior changes
  • Tests

    • Added comprehensive test coverage for event-driven review sweep functionality

…n latency gap (#898)

Reframes #898 from its (incorrect) marker hypothesis to the real cause. The
ci-pending skip in review-one-pr.sh exits 100 BEFORE the idempotency check and
writes no marker, so it is already non-terminal; the selection logic that
re-reviews a stuck-green PR (REVIEW_REQUIRED + CI green + no marker) is correct
and already covered by tests. What stalled #892 was purely LATENCY: the only
thing that re-reviews a PR which goes green after the last trigger fired was the
hourly stuck-review sweep (#573), so the PR could sit green-but-unreviewed for up
to an hour (the human force-reviewed before the next tick).

Close the gap with two robust, layered triggers on pr-review-sweep.yml:

- Scheduled cron tightened from hourly to every 15 min — the GUARANTEED backstop
  bounding worst-case re-review latency, with zero fragility.
- A `workflow_run: completed` fast path keyed on the broadly-run CI workflows.
  When CI finishes, the sweep runs SCOPED to just that run's PR(s) —
  sweep-stuck-reviews.sh derives them from the event payload
  (`prs_from_workflow_run_event`, pure/unit-tested) instead of enumerating the
  fleet — so a PR that just went green is re-reviewed in seconds. Per-branch
  `cancel-in-progress` concurrency collapses the multi-workflow burst so the
  sweep effectively runs once, after the last-finishing workflow (most likely to
  observe green). The fast path can never strand a PR: if it matches nothing
  (fork PR, branch push, CI still pending, or a workflow rename) the scheduled
  sweep still catches it, and the same REVIEW_REQUIRED + green + no-marker gate
  decides in every path.

Tests: 5 new cases in tests/test_sweep_stuck_reviews.bats exercise the
workflow_run path — ci-pending→green dispatches (scoped to the event), empty
pull_requests is a clean no-op, a too-early fire (CI still pending) does not
dispatch, an already-reviewed-at-head PR is not re-dispatched, and a multi-PR
run evaluates each independently. shellcheck clean; existing 21 sweep tests
unchanged and green. AGENTS.md exception note updated to describe both triggers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Y3xW3cnB5wscv4SmjSNEr
@don-petry
don-petry requested a review from a team as a code owner June 23, 2026 17:30
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e5d385fd-19ae-460a-9495-b7d0b7d8c4b3

📥 Commits

Reviewing files that changed from the base of the PR and between 2888396 and 4dfe428.

📒 Files selected for processing (4)
  • .github/workflows/pr-review-sweep.yml
  • AGENTS.md
  • scripts/sweep-stuck-reviews.sh
  • tests/test_sweep_stuck_reviews.bats

📝 Walkthrough

Walkthrough

Adds an event-driven fast path to pr-review-sweep.yml and sweep-stuck-reviews.sh: a workflow_run: completed trigger fires the sweep immediately after selected CI workflows finish, scoping candidates to the PRs listed in the event payload via a new prs_from_workflow_run_event helper. The scheduled cron is tightened to 15 minutes, the concurrency group is made branch/event-derived, and bats tests plus AGENTS.md are updated.

Changes

Event-driven stuck-review sweep

Layer / File(s) Summary
Workflow triggers, schedule, and concurrency
.github/workflows/pr-review-sweep.yml
Replaces hourly cron with a 15-minute offset-based schedule, adds workflow_run trigger for selected CI workflow names with types: [completed], updates inline docs describing the dual-trigger design, and changes concurrency.group to a branch/event-derived key.
Script candidate-gathering fast path
scripts/sweep-stuck-reviews.sh
Adds prs_from_workflow_run_event helper reading GITHUB_EVENT_PATH JSON and extracting unique PR URLs via jq; introduces an elif branch so workflow_run events use that scoped list instead of the full list-prs.sh enumeration.
Tests and docs
tests/test_sweep_stuck_reviews.bats, AGENTS.md
Adds write_event/ghp_event_url test helpers and five bats tests covering dispatch, no-op, pending-CI skip, already-reviewed skip, and multi-PR scenarios for the fast path; updates AGENTS.md to describe the dual-trigger behavior.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main objective: implementing an event-driven re-trigger mechanism for pr-review-sweep to reduce CI-pending→green latency, which matches the core changes across all modified files.
Linked Issues check ✅ Passed The PR fully addresses issue #898 by implementing two-layer triggers (15-min cron + workflow_run fast-path), maintaining existing gating logic, adding comprehensive test coverage for the new fast-path, and documenting both triggers.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the event-driven mechanism: workflow configuration, helper script functions, tests, and documentation updates—no unrelated modifications present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/pr-review-retrigger

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) June 23, 2026 17:31
@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-06-23T18:31:34Z.

@don-petry
don-petry disabled auto-merge June 23, 2026 17:32
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (no-changes)

Agent reasoning
Issues addressed: 0
- (No issues found; Quality Gate passed)
Files changed: None
Skipped (informational): N/A
```
**No changes required.** The PR is clean and ready.

@don-petry
don-petry enabled auto-merge (squash) June 23, 2026 17:32

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an event-driven fast path to the stuck-review sweep script, triggered by 'workflow_run: completed' events, allowing PRs that just went green to be re-reviewed quickly. It also adds comprehensive unit tests and updates the documentation. The reviewer suggested optimizing the 'prs_from_workflow_run_event' helper function to parse the JSON file with a single 'jq' pipeline instead of two, and to explicitly validate positional parameters to prevent unbound variable errors.

Comment thread scripts/sweep-stuck-reviews.sh
@don-petry
don-petry disabled auto-merge June 23, 2026 17:33
Address gemini-code-assist's medium-priority note on #914: parse the
workflow_run event payload exactly once. Bind .repository.full_name inside the
jq program and `select` it out (empty stream) when absent, instead of a
separate jq invocation + shell guard — one process, one read, same behavior.
The positional-arg guard (`${1:-}`, set -u-safe) and the URL output are
unchanged; all 26 sweep tests still pass and shellcheck is clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Y3xW3cnB5wscv4SmjSNEr
@don-petry
don-petry enabled auto-merge (squash) June 23, 2026 17:36
@don-petry
don-petry disabled auto-merge June 23, 2026 17:37
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — waiting on PR blockers (intent: review-changes)

PR: #914
No changes were committed, but the PR still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews). The retry cron will re-attempt automatically. Next attempt after: 2026-06-23T18:10:12Z

@don-petry

Copy link
Copy Markdown
Collaborator Author

Note

@don-petry I reviewed this PR and no code changes were needed, but it still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews), so I cannot mark it done yet. I'll re-check automatically.
Next attempt after: 2026-06-23T18:10:12Z

@don-petry
don-petry enabled auto-merge (squash) June 23, 2026 17:40
@don-petry
don-petry disabled auto-merge June 23, 2026 18:24
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) June 23, 2026 18:24
@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-06-23T19:28:53Z.

@sonarqubecloud

Copy link
Copy Markdown

@don-petry
don-petry disabled auto-merge June 23, 2026 19:26
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — waiting on PR blockers (intent: review-changes)

PR: #914
No changes were committed, but the PR still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews). The retry cron will re-attempt automatically. Next attempt after: 2026-06-23T19:56:23Z

@don-petry

Copy link
Copy Markdown
Collaborator Author

Note

@don-petry I reviewed this PR and no code changes were needed, but it still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews), so I cannot mark it done yet. I'll re-check automatically.
Next attempt after: 2026-06-23T19:56:23Z

@don-petry
don-petry enabled auto-merge (squash) June 23, 2026 19:26
@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-06-23T20:29:15Z.

@don-petry
don-petry disabled auto-merge June 23, 2026 20:21
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) June 23, 2026 20:21

@donpetry-bot donpetry-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.

Automated review — APPROVED ✓

Risk: MEDIUM
Reviewed commit: 4dfe4284c56a7f4f2386f6cf1f9828848ce24a66
Review mode: triage-approved (single reviewer)

Summary

Adds an event-driven fast path to the stuck-review sweep: a workflow_run:completed trigger (keyed on core CI workflows) re-runs the sweep scoped to just the completing run's PR(s), tightens the cron backstop from hourly to every 15 min, and makes the concurrency group per-branch/event. A new pure, unit-tested helper prs_from_workflow_run_event derives PR URLs from the event payload. Authoritative gating in review-one-pr.sh is unchanged. Confirms the triage low-risk assessment.

Linked issue analysis

Closes #898. The PR substantively addresses the issue by reframing its (incorrect) marker hypothesis to the real cause — re-review latency — and closing the gap with two layered triggers (15-min cron backstop + workflow_run fast path). Linked-issue gate satisfied.

Findings

No blocking findings.

  • Security: workflow_run runs against the trusted default-branch workflow definition and checks out only the agent repo (no untrusted PR-code execution). permissions remain contents: read. PR numbers are taken from .workflow_run.pull_requests[].number, validated as integers via jq — no injection vector. github.event.workflow_run.head_branch is used only as a YAML concurrency-group key, never in a shell context. Fork-PR/branch-push runs carry an empty pull_requests array and are correctly excluded; the scheduled sweep backstops any miss.
  • Review threads: gemini-code-assist's medium-priority note (single jq pass + set -u-safe positional guard) was addressed in commit 752af09. CodeRabbit APPROVED at head; SonarCloud Quality Gate passed.
  • Advisory bots: the earlier 'rate-limited' markers were Codex usage-limit notices (external billing), not code findings.
  • Secret-scan MCP tool unavailable in this environment; not run (diff contains no secret material; gitleaks CI check passed).
  • Tests: 5 new bats cases cover dispatch-on-green, empty no-op, too-early/CI-pending skip, already-reviewed-at-head skip, and multi-PR evaluation; shellcheck clean.

CI status

All required checks green (CI/Lint/ShellCheck/bats/unit-tests, CodeQL, AgentShield, SonarCloud, gitleaks, Holdout Guard, Test-Deletion Guard, Dev-Lead); dependency-audit ecosystem jobs SKIPPED as expected. No failing or cancelled checks. mergeStateStatus is BLOCKED solely on the REVIEW_REQUIRED gate (org-leads).


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pr-review self-review deadlock: ci-pending skip + "already reviewed" marker blocks approval once CI goes green

3 participants