ci: keep the fork review to forks

The fork job never checked where the head branch lived. It was written
as the fork path and reads like one, but `pull_request_target` fires on
every pull request, so labelling one of ours landed there too --
silently, and with the weaker review: no plugin, no whole-repo context,
read-only tools. #389 got that instead of the review it should have had.

Also corrects the `labeled` comment in claude-code-review.yml, which
promised exactly the case that cannot work. A `pull_request` workflow is
read from the PR's merge ref, and GitHub recomputes that on a push and
not otherwise, so a PR whose last push predates the file has a merge ref
without it and no label can summon it. Pushing fixes it, and also
triggers synchronize by itself -- which is why the empty commit worked
and the label looked broken.
This commit is contained in:
l0ng-ai
2026-08-07 22:22:54 +07:00
parent 51ea055d2a
commit cae334fc98
2 changed files with 30 additions and 10 deletions
+15 -4
View File
@@ -17,10 +17,21 @@ name: Claude Code Review
on:
pull_request:
# `labeled` is the manual re-run: a PR opened before this workflow existed
# has no run to re-run from the Actions tab, and reopening fires `reopened`
# rather than `opened`. Applying the label needs write access, so the same
# label doubles as the approval gate in claude-review-fork.yml.
# `labeled` is the manual re-run: reopening a PR fires `reopened`, not
# `opened`, and a PR that predates this file has no run to restart from the
# Actions tab. Applying the label needs write access, so the same label
# doubles as the approval gate in claude-review-fork.yml.
#
# It does not reach the PRs that need it most, and the reason is worth
# knowing before you conclude the label is broken. A `pull_request` workflow
# is read from the PR's merge ref, which GitHub recomputes on a push and not
# otherwise. A PR whose last push predates this file therefore has a merge
# ref that does not contain it, and no label will summon a workflow that,
# from that ref's point of view, does not exist. Push to the branch and the
# merge ref catches up -- though by then the push has triggered
# `synchronize` anyway, which is why the empty-commit trick works and the
# label appears not to. `claude-review-fork.yml` is exempt: a
# `pull_request_target` workflow is read from the base branch.
types: [opened, synchronize, labeled]
# Same reasoning as ci.yml: a superseded review is dead weight, and unlike a
+15 -6
View File
@@ -69,13 +69,22 @@ jobs:
name: claude review (fork)
runs-on: ubuntu-latest
timeout-minutes: 30
# `labeled` carries the label that was just applied; `synchronize` carries
# none, so it has to look at what the PR is already wearing. The two need
# separate clauses: testing only the label list would spend a review every
# time any other label -- `bug`, `blocked` -- landed on a subscribed PR.
# First clause: forks only. Everything below trades review quality for
# safety against code we do not control -- no plugin, no whole-repo context,
# read-only tools -- and a branch in this repository has earned none of that.
# `pull_request_target` does not care where the head is, so if this job does
# not say so, labelling one of our own PRs lands it here and it silently
# gets the weaker review instead of the one in claude-code-review.yml.
#
# Then: `labeled` carries the label that was just applied; `synchronize`
# carries none, so it has to look at what the PR is already wearing. Those
# two need separate clauses, because testing only the label list would spend
# a review every time an unrelated label -- `bug`, `blocked` -- landed on a
# subscribed PR.
if: >-
(github.event.action == 'labeled' && github.event.label.name == 'claude-review') ||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'claude-review'))
github.event.pull_request.head.repo.full_name != github.repository &&
((github.event.action == 'labeled' && github.event.label.name == 'claude-review') ||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'claude-review')))
permissions:
contents: read
pull-requests: write # the last step posts the review comment