Remove/re-request d-morrison review around AI review runs (#132)#133
Remove/re-request d-morrison review around AI review runs (#132)#133d-morrison wants to merge 6 commits into
Conversation
Closes #132. claude.yml: drop the head-SHA gating; remove d-morrison's review request before Claude starts and always re-request it after, so each Claude run on a PR produces a fresh review notification (even when Claude errors out or makes comment-only changes). claude-code-review.yml: same pattern. Bump pull-requests permission from read to write so the workflow can manage reviewers. copilot-review-request-handling.yml (new): mirrors the behavior for Copilot — remove d-morrison when Copilot is added as a reviewer, re-request when Copilot submits its review. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Removes the head-SHA gating in the Claude workflows so that d-morrison's review request is always dropped before AI work and always restored afterward, and introduces an analogous workflow for Copilot reviews. Together these implement the behavior requested in issue #132: a fresh review notification on every AI run, with the request suppressed while AI work is in progress.
Changes:
claude.yml: replace SHA-capture / SHA-diff logic with unconditional remove-before / re-request-after steps.claude-code-review.yml: add matching remove/re-request steps and upgradepull-requestspermission fromreadtowrite.- New
copilot-review-request-handling.yml: mirrors the same remove/re-request cycle around Copilot reviews usingreview_requestedandpull_request_reviewtriggers.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| .github/workflows/claude.yml | Drops SHA gating; always removes d-morrison before Claude runs and re-requests after. |
| .github/workflows/claude-code-review.yml | Adds remove/re-request steps around Claude review job; bumps PR permission to write. |
| .github/workflows/copilot-review-request-handling.yml | New workflow that performs the same remove/re-request cycle around Copilot reviews. |
Comments suppressed due to low confidence (1)
.github/workflows/copilot-review-request-handling.yml:29
- Same overly permissive substring match issue here:
contains(github.event.review.user.login, 'opilot')will also match logins liketropilotor any other string containing "opilot". Prefer an explicit check against the known Copilot reviewer login(s).
if: |
github.event_name == 'pull_request_review' &&
contains(github.event.review.user.login, 'opilot')
Five Copilot review comments on PR #133: 1. Substring match `contains(..., 'opilot')` was overly broad — replaced with explicit equality against the two known Copilot reviewer logins (`Copilot` and `copilot-pull-request-reviewer[bot]`). 2,4. Re-request fired unconditionally on every AI completion, including PRs where d-morrison was never a reviewer. The issue text says "any review requests aimed at me" — implying d-morrison is already a reviewer — so gate the re-request on whether d-morrison was a reviewer when the run started. For claude.yml and claude-code-review.yml that state lives within a single workflow run, so use a step output (`had_reviewer`). For the Copilot workflow `start` and `finish` are separate events, so use a label (`ai-review-in-progress`) as cross-event state. 3. Replaced silent `|| true` swallowing on every gh api call with `|| echo "::warning::..."` so failures surface as workflow annotations. 5. Added `github.event.pull_request.number` guard to the re-request step in claude-code-review.yml, matching the style in claude.yml. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@claude review |
|
Claude finished @d-morrison's task in 1m 50s —— View job Code Review
The Copilot-identified issues were all addressed cleanly in
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
.github/workflows/copilot-review-request-handling.yml:39
- The
startjob adds theai-review-in-progresslabel viaPOST /repos/{owner}/{repo}/issues/{N}/labels. GitHub's API will return 422 if the label does not already exist in the repository — it does not create the label on the fly. Because the call is followed by|| echo "::warning::...", the failure will be silently surfaced only as a workflow warning, but more importantly thefinishjob (which gates oncontains(github.event.pull_request.labels.*.name, 'ai-review-in-progress')) will never re-request d-morrison, breaking the round-trip. Consider creating the label in the repository (or via a pre-step usinggh label create ai-review-in-progress --force) so the marker mechanism works reliably.
gh api -X POST \
"repos/${{ github.repository }}/issues/$PR_NUMBER/labels" \
-f "labels[]=ai-review-in-progress" \
|| echo "::warning::failed to add ai-review-in-progress label to PR #$PR_NUMBER"
| if: | | ||
| github.event_name == 'pull_request' && | ||
| (github.event.requested_reviewer.login == 'Copilot' || | ||
| github.event.requested_reviewer.login == 'copilot-pull-request-reviewer[bot]') && | ||
| contains(github.event.pull_request.requested_reviewers.*.login, 'd-morrison') |
| @@ -42,3 +57,16 @@ jobs: | |||
| # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md | |||
| # or https://code.claude.com/docs/en/cli-reference for available options | |||
|
|
|||
| - name: Re-request review from d-morrison when Claude finishes reviewing | |||
| if: | | |||
| always() && | |||
| github.event.pull_request.number && | |||
| steps.remove_reviewer.outputs.had_reviewer == 'true' | |||
| env: | |||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |||
| run: | | |||
| gh api -X POST \ | |||
| "repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers" \ | |||
| -f "reviewers[]=d-morrison" \ | |||
| || echo "::warning::failed to re-request d-morrison as reviewer on PR #${{ github.event.pull_request.number }}" | |||
…bel) Five issues from the @claude review on PR #133: 1. (copilot workflow) Race condition: Copilot can submit a review faster than the `start` job queues. Previously, if `finish` ran first it checked `github.event.pull_request.labels.*.name` from the event payload (no label yet), exited, and then `start` ran late and removed d-morrison without anyone re-adding them. Fix: `finish` now queries live label state via the API instead of the event payload. `start` gains a recovery step that re-checks for an existing Copilot review after applying the label — if found, it undoes the remove. The two paths converge regardless of order. 2. (copilot workflow) `copilot-pull-request-reviewer[bot]` was likely dead code — GitHub's REST `login` field strips the `[bot]` suffix. Removed the `[bot]` variant from both `start` and `finish` conditions. 3. (copilot workflow) `ai-review-in-progress` label was assumed to exist. Added a `gh label create --force` step at the top of `start`. 4. (copilot workflow) No cleanup if a PR closes without Copilot ever submitting a review (the label would linger). Added a `cleanup_on_close` job triggered by `pull_request.closed`. 5. (claude.yml) The HAD_REVIEWER `gh api` call could fail and leave the variable empty — the re-request step (gated on `== 'true'`) would silently skip, leaving d-morrison removed. Default to "false" on any API error or empty result. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Addressed in 9aa2442:
The inconsistency between |
|
@claude review and then fix |
|
Claude finished @d-morrison's task in 2m 39s —— View job Review (post-9aa2442)
All issues from the first review round and all items addressed in 9aa2442 look correct. Two items from Copilot's second review were not addressed and are the main remaining concerns.
|
- claude-code-review.yml: skip the remove/re-request steps on fork PRs. GITHUB_TOKEN is downgraded to read-only for fork events regardless of the declared `pull-requests: write` permission, so both gh api calls would 403 and emit noisy warnings. The Claude review action itself still runs (uses its own OAuth token). - copilot-review-request-handling.yml: guard the `finish` job against PRs authored by d-morrison. If a label somehow lands on a d-morrison PR, the re-request POST would return 422 (can't request the author). - claude.yml: clarify the HAD_REVIEWER fallback comment — the prior wording implied a scenario that can't happen (transient failure leaving d-morrison removed; the DELETE only runs when HAD_REVIEWER is "true", so an upstream GET failure can't have removed anything). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The race-recovery step in copilot-review-request-handling.yml's `start` job was using a non-paginated `gh api .../reviews` call (default 30 per page). On a PR with more than 30 reviews where Copilot's submission isn't on page 1, the recovery silently misses it and leaves d-morrison removed. Switch to `--paginate` and use `head -n1` to short-circuit on the first match across all pages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| start: | ||
| if: | | ||
| github.event_name == 'pull_request' && | ||
| github.event.action == 'review_requested' && |
|
Summary
claude.yml: drop the head-SHA gating; remove d-morrison's review request before Claude starts and always re-request after — every Claude run now produces a fresh review notification, even on error or comment-only runs.claude-code-review.yml: same pattern; bumppull-requestspermission towriteso the workflow can manage reviewers.copilot-review-request-handling.yml: mirrors the behavior for Copilot — removes d-morrison while Copilot is reviewing, re-requests when Copilot submits.Closes #132.
Test plan
@claude <task>on a PR with d-morrison already requested — confirm the review request disappears at job start and reappears at job end (even if Claude errors)claude-code-review.yml) — confirm same remove/re-request cycle around the review job🤖 Generated with Claude Code