Skip to content
Merged
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
5 changes: 4 additions & 1 deletion .github/workflows/claude-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ on:
issue_comment:
types: [created]

# Workflow concurrency applies before the job `if`, so every PR comment joins
# the group, including Claude's own summary comment. Comments that are not
# `@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) || '' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

cancel-in-progress: true

jobs:
Expand Down
Loading