@@ -3,9 +3,31 @@ name: Claude PR Review
33on :
44 pull_request :
55 types : [opened, synchronize, ready_for_review, reopened]
6-
6+ # Callable so this repository's own CI can run this file and prove it starts. That is not a
7+ # theoretical worry: an org ruleset injects this workflow into every repo resolved from
8+ # `main`, so a pull request here is reviewed by main's copy and never by the copy it is
9+ # changing. Twice in one day a file that Actions refuses to parse merged green -- an empty
10+ # expression delimiter in a shell comment, then a `run:` block past the 21,000-character
11+ # expression limit -- because nothing in CI had ever executed the version under review.
12+ #
13+ # tests.yml calls this with `uses: ./...`, which resolves from the calling commit, so the
14+ # smoke run is the pull request's copy. A copy Actions cannot load fails the caller too, which
15+ # is the whole point: "does it start" is exactly what both outages got wrong.
16+ workflow_call :
17+ inputs :
18+ dry_run :
19+ description : >-
20+ Everything except the review itself. Set by tests.yml, never on the production path,
21+ where `inputs` is empty and this reads as false.
22+ type : boolean
23+ default : false
24+
25+ # Distinct groups for the smoke run and the live review, because a called workflow inherits the
26+ # caller's `github` context: both would otherwise compute pr-review-<same number> on the same
27+ # pull request, and cancel-in-progress would have each cancelling the other. A smoke test that
28+ # kills real reviews is worse than no smoke test.
729concurrency :
8- group : pr-review-${{ github.event.pull_request.number }}
30+ group : pr-review-${{ inputs.dry_run && 'smoke' || 'live' }}-${{ github.event.pull_request.number }}
931 cancel-in-progress : true
1032
1133jobs :
@@ -509,8 +531,19 @@ jobs:
509531 PR_TITLE : ${{ github.event.pull_request.title }}
510532 PR_BODY : ${{ github.event.pull_request.body }}
511533
534+ # The only step a dry run skips, and the only one it needs to: every step after this one
535+ # is already gated on this step's outcome or its outputs, so skipping it silences the whole
536+ # write side of the workflow without a second condition anywhere.
537+ #
538+ # Reduce execution log -- needs steps.review.outputs.execution_file, empty when skipped
539+ # Upload tool usage -- needs steps.tool-usage.outcome == 'success', which is 'skipped'
540+ # Notify on failure -- needs outcome 'failure' or 'cancelled', and this is 'skipped'
541+ #
542+ # So a smoke run posts no review, no comment and no artifact. Everything before this step
543+ # still runs against the live API: the app token, the cross-repo prompt checkout, and the
544+ # nine context reads with the job's real permissions.
512545 - uses : anthropics/claude-code-action@v1
513- if : github.event.pull_request.user.login != 'dependabot[bot]'
546+ if : github.event.pull_request.user.login != 'dependabot[bot]' && !inputs.dry_run
514547 id : review
515548 continue-on-error : true
516549 with :
0 commit comments