Repository navigation
Stop PR comments from cancelling the Claude review - #210
Conversation
Workflow-level concurrency is evaluated before the job's if, so every comment on a PR joined claude-review-<N> and cancelled the running review. Claude's own summary comment did this at the end of every review, so each run on #202 and #207 ended as cancelled (red) even though its comments were posted. A human comment mid-review would kill it outright. Comments that are not '@claude review' now get a per-run group. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| # `@claude review` get a group of their own, so they cannot cancel a review. | ||
| concurrency: | ||
| group: claude-review-${{ github.event.pull_request.number || github.event.issue.number }} | ||
| group: claude-review-${{ github.event.pull_request.number || github.event.issue.number }}${{ github.event_name == 'issue_comment' && !startsWith(github.event.comment.body, '@claude review') && format('-{0}', github.run_id) || '' }} |
There was a problem hiding this comment.
The concurrency key only looks at the comment text. The job if (lines 32–34) also requires github.event.issue.pull_request and an OWNER/MEMBER/COLLABORATOR author_association. Because concurrency is applied before the job if, an @claude review comment from anyone without those roles still joins the shared claude-review-<N> group. That includes a fork PR author or any user on this public repo. With cancel-in-progress: true, the comment cancels a running review, and its own run is then skipped. So the self-cancel bug is fixed, but anyone can still cancel a review just by commenting. Use the same author_association check in the concurrency condition, so only comments that would actually start a review share the group. For example:
group: claude-review-${{ github.event.pull_request.number || github.event.issue.number }}${{ github.event_name == 'issue_comment' && !(startsWith(github.event.comment.body, '@claude review') && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) && format('-{0}', github.run_id) || '' }}A smaller version of the same problem: pull_request reopened/ready_for_review events on fork PRs still use the shared group, so they can cancel a maintainer-requested review even though their own job is skipped by the head.repo.full_name check.
|
Claude review: 1 finding. The concurrency key checks only the comment text, not the job's author_association/PR checks. So an |
Why
Every Claude review run ends as cancelled (red ✗), even when it posted its full review: #207 (run 36825421844, both attempts) and #202 (run 36720540789).
Annotation: "Canceling since a higher priority waiting request for claude-review-207 exists".
concurrencyis set at workflow level, and GitHub evaluates it before the jobif:. So every comment on a PR starts a run inclaude-review-<N>and cancels the active review. That run's own job is then skipped. The last thing a review does is post its summary withgh pr comment, so each review cancels itself 2–4 s later:A human comment during the 3–4 min review would also kill it mid-run.
Change
Comments that don't start with
@claude reviewgo into a per-run group (claude-review-<N>-<run_id>), so they can't cancel anything. PR open/reopen/ready events and@claude reviewkeep the shared per-PR group, so a new review request still replaces a running one.Rollout
The action only runs when the PR's
claude-review.ymlis byte-identical to main's. This change goes in twice, with the identical file:patch→ main andci/claude-review-concurrency-dev→ dev. Neither PR will get a real review run before the main one is merged.Checks
@claude reviewon a PR should end success. The summary comment's run should be skipped in its own group, and a plain comment mid-review should leave the review running.🤖 Generated with Claude Code