Skip to content

Commit def89e1

Browse files
igerberclaude
andcommitted
Split AI review checkout by PR state (open vs closed)
Three rounds of review feedback have surfaced overlapping checkout robustness concerns. Picking one approach and unifying behind it. Closed/merged PR path (the audit-campaign use case): Use `refs/pull/<N>/head` from the base repo. GitHub keeps this mirror durably regardless of whether the original branch is deleted, the fork is removed, or the merge was rebase/squash. Replaces the prior `refs/pull/<N>/merge` checkout, which is garbage-collected on close. Open PR path: Use `head_sha` from `head_repo_full_name`. For owner PRs the head repo equals github.repository so this is identical to a base-repo checkout. For fork PRs it avoids the documented race where the base repo has not yet mirrored a freshly API-created fork PR's head (.claude/commands/submit-pr.md:327-345). base_sha lives on github.repository regardless of which checkout path runs, so the prefetch step continues to add a `base` remote explicitly. `git diff BASE_SHA HEAD_SHA` therefore finds both trees locally in every covered scenario. The PR state is sourced from `pulls.get` in the existing metadata step (works for both `pull_request` and `issue_comment` events). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3c02cab commit def89e1

1 file changed

Lines changed: 21 additions & 13 deletions

File tree

.github/workflows/ai_pr_review.yml

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,29 +83,37 @@ jobs:
8383
core.setOutput("base_ref", pr.data.base.ref);
8484
core.setOutput("head_ref", pr.data.head.ref);
8585
core.setOutput("head_repo_full_name", headRepoFullName);
86+
core.setOutput("state", pr.data.state);
8687
88+
# Closed/merged PR (e.g. `/ai-review` rerun on a merged PR):
89+
# use the base-repo mirror of the PR head, which GitHub keeps
90+
# durably even after the fork is deleted or branches removed.
91+
# The previous workflow used `refs/pull/<N>/merge`, which is
92+
# garbage-collected on closed PRs — this path replaces that.
8793
- uses: actions/checkout@v6
94+
if: steps.pr.outputs.state != 'open'
95+
with:
96+
ref: refs/pull/${{ steps.pr.outputs.number }}/head
97+
98+
# Open PR: check out by head_sha from the head repo (= base repo
99+
# for owner PRs, = the fork for fork PRs). This avoids the
100+
# documented race where `refs/pull/<N>/head` on the base repo
101+
# has not yet mirrored a freshly API-created PR's head
102+
# (see .claude/commands/submit-pr.md:327-345). head_sha is
103+
# guaranteed to exist on the head repo for an open PR.
104+
- uses: actions/checkout@v6
105+
if: steps.pr.outputs.state == 'open'
88106
with:
89-
# Check out the PR head by SHA from the head repo (which equals
90-
# github.repository for owner-created PRs and points at the fork
91-
# for fork PRs). The previous workflow used `refs/pull/<N>/merge`,
92-
# which GitHub garbage-collects on closed/merged PRs and breaks
93-
# `/ai-review` reruns post-merge. Switching to head_sha avoids that,
94-
# and pointing at the head repo also avoids the documented race
95-
# where `refs/pull/<N>/head` on the base repo has not yet mirrored
96-
# a fresh fork PR's head (see .claude/commands/submit-pr.md:327-345).
97-
# The diff the reviewer sees is unchanged: it's computed from
98-
# BASE_SHA/HEAD_SHA below, captured in the same metadata step.
99107
repository: ${{ steps.pr.outputs.head_repo_full_name }}
100108
ref: ${{ steps.pr.outputs.head_sha }}
101109

102110
- name: Pre-fetch base SHA
103111
run: |
104112
set -euo pipefail
105113
# base_sha lives on the base repo (github.repository), which differs
106-
# from origin when this is a fork PR. Add an explicit `base` remote
107-
# so `git diff BASE_SHA HEAD_SHA` always finds the base-side tree,
108-
# regardless of whether origin points at the fork or the base repo.
114+
# from origin when this is an open fork PR. Add an explicit `base`
115+
# remote so `git diff BASE_SHA HEAD_SHA` finds the base-side tree
116+
# regardless of which checkout path ran.
109117
git remote add base "https://github.com/${{ github.repository }}.git"
110118
git fetch --no-tags --depth=1 base "${{ steps.pr.outputs.base_sha }}"
111119

0 commit comments

Comments
 (0)