Skip to content

Fire the Claude code-review routine when a pull request is ready - #1273

Merged
tobyhede merged 4 commits into
mainfrom
claude/project-thread-p2p4dl
Oct 19, 2026
Merged

tobyhede merged 4 commits into
mainfrom
claude/project-thread-p2p4dl

Conversation

@tobyhede

@tobyhede tobyhede commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Toby

Before: the only automated review in this repo is claude-review.yml, which runs claude-code-action in CI and is off unless CLAUDE_REVIEW_ENABLED is set.

After: when a pull request is opened, reopened or marked ready for review, a new Code review workflow fires a Claude code-review routine with the PR's URL and number, and the routine's session reviews it. Drafts, bots' PRs (Dependabot, release-plz) and forks are skipped. There is no synchronize trigger, so mark a PR draft and then ready again to get a fresh review.

How: one curl POST to the routine's /fire endpoint. jq builds the body, the bearer token goes in on stdin rather than on the command line, and the trigger id is checked against ^trig_[A-Za-z0-9]+$ before it goes into the URL. It doesn't retry, because a request that timed out may already have started a session. The workflow is ported from tobyhede/zod's code-review.yml, with the trigger id moved into a repository variable.

Setup needed before this works:

  • A code-review routine for this repo.
  • Secret CLAUDE_ROUTINE_TOKEN, the routine's bearer token.
  • Variable CLAUDE_ROUTINE_TRIGGER_ID, the routine's trig_… id.

Until those exist, the job fails with an error saying which one is missing. If claude-review.yml is turned on as well, each PR will be reviewed twice.

Tests: scripts/__tests__/code-review-workflow.test.mjs pins the triggers, the empty permissions and the secret and variable the workflow reads. It also runs the step's script against a stub curl and checks that the token is passed only on stdin, that quotes in PR fields stay inside the JSON body, and that a missing token or a malformed trigger id is refused before curl runs. The job's if: now uses the canonical fork-guard clause, and the job is listed in workflow-dispatch-job-conditions.test.mjs, which caught the old spelling.

The workflow tests and claude-review-workflow.test.mjs pass locally (199 tests), and so do actionlint, zizmor and biome. I didn't run the whole test:scripts suite: bench-index-expressions.test.mjs needs the workspace packages, which I didn't install.

Closes #1292.

Summary by CodeRabbit

  • New Features
    • Eligible pull requests now automatically trigger an AI-assisted code review when opened, reopened, or marked ready for review.
    • Draft pull requests, bot-authored pull requests, and pull requests from forks are excluded from automatic reviews. Changes pushed to an existing pull request do not trigger a new review.
    • Reviews run one at a time for each pull request, helping avoid overlapping review requests. Each eligible event triggers a single review request.

Generated by Claude Code

Ported from tobyhede/zod: on opened, reopened and ready_for_review (never
a draft, a bot's or a fork's pull request), POST the pull request's URL
and number to the Claude code-review routine. The trigger id is the
repository variable CLAUDE_ROUTINE_TRIGGER_ID and the bearer token the
secret CLAUDE_ROUTINE_TOKEN.
@tobyhede tobyhede self-assigned this Oct 19, 2026
@changeset-bot

changeset-bot Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 20843cf

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: c9ec4993-2874-4133-93d6-1d132c2e6308
📥 Commits

Reviewing files that changed from the base of the PR and between c3fde53 and 20843cf.

📒 Files selected for processing: 2
  • .github/workflows/code-review.yml
  • scripts/__tests__/code-review-workflow.test.mjs

Included review availability: This review used your included allowance. 4 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.

📝 Walkthrough

Adds a GitHub Actions workflow that sends pull-request details to a review routine. The workflow filters eligible pull requests, validates its configuration, and makes one timed request. Tests cover workflow conditions, request construction, and failure cases.

Changes: Code review workflow

Layer / File(s) Summary
Workflow triggers and eligibility
.github/workflows/code-review.yml, scripts/__tests__/code-review-workflow.test.mjs, scripts/__tests__/workflow-dispatch-job-conditions.test.mjs
The workflow runs for selected pull-request events and excludes forks, drafts, and bot authors. Tests check triggers, job conditions, concurrency, permissions, and fork guards.
Routine request and validation
.github/workflows/code-review.yml, scripts/__tests__/code-review-workflow.test.mjs
The request step validates its token and trigger ID, builds a JSON body, and sends one timed POST. Tests check token handling, request contents, escaping, retries, and failure cases.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant RequestStep
  participant RoutineEndpoint
  GitHubActions->>RequestStep: Start workflow for eligible pull request
  RequestStep->>RequestStep: Validate token and trigger ID
  RequestStep->>RoutineEndpoint: Send pull-request details
  RoutineEndpoint-->>RequestStep: Return request result
Loading
Merge Risk: ⚪ Minimal · up to 20843

The workflow only sends an advisory review request for eligible same-repository pull requests. Request failures do not turn the pull request check red. No merge-blocking risk remains.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly identifies the main change: triggering the Claude code-review routine when a pull request is ready for review. It is concise and related to the workflow changes.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files. (1 skipped: 1 unsupported.)

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

code-review-workflow.test.mjs pins the triggers (no synchronize), the
empty permissions, the secret and variable it reads, and runs the step's
script against a stub curl: the token only on stdin, the body built by
jq, and a missing token or a malformed trigger id refused before curl.

The fork guard now takes the canonical spelling and the job is listed in
workflow-dispatch-job-conditions.test.mjs, which caught the old one.
@tobyhede
tobyhede marked this pull request as ready for review October 19, 2026 03:40
@tobyhede
tobyhede requested a review from a team as a code owner October 19, 2026 03:40

@cipherstash-agent cipherstash-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review attestation

Source: Claude Code routine, /code-review medium followed by /cross-check-review-findings, on head ce01c85.

Result: no findings. Nothing critical or blocking.

Scope: .github/workflows/code-review.yml, its test, and the fork-guard allowlist entry.

Checked, and found sound:

  • Token handling: permissions: {}. The routine token reaches curl only on stdin (-H @-), never on the command line.
  • Injection: PR fields go through env and jq --arg, with no ${{ }} in the script. The trigger id is regex-validated before it goes into the URL.
  • Triggers and guards: no synchronize, so there is one review per event. The job skips drafts, bots and forks. The allowlist entry in workflow-dispatch-job-conditions.test.mjs matches.
  • No retry: a timed-out request can't start a second session.

Not verified: I did not run the vitest suites, because dependencies aren't installed in this environment. CI should confirm them.

Non-blocking note: there is no concurrency group, so a quick reopen followed by ready-for-review could start two review sessions. Acceptable given the documented manual re-run model.


Generated by Claude Code

@cipherstash-agent cipherstash-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review attestation: /code-review medium followed by /cross-check-review-findings, run against head ce01c85. Source: Claude Code scheduled review routine.

Critical / blocking: none.

Findings (2 survived cross-check, both non-blocking):

  • Medium: the job has no enable gate. It fails every PR until CLAUDE_ROUTINE_TOKEN and CLAUDE_ROUTINE_TRIGGER_ID are set (inline, line 31).
  • Low: no concurrency group, so draft/ready toggles can start duplicate review sessions (inline, line 21).

Checked and found fine:

  • Secrets reach the script only through env, never expanded into it.
  • Token goes on stdin, not the command line.
  • The jq-built body is injection-safe.
  • The trigger id is validated before it goes into the URL.
  • Fork and bot guards are in place.
  • Job permissions are {}.

Dropped as intentional or documented in the PR: no synchronize trigger, no retry, and duplicate review when claude-review.yml is also enabled.

I did not run the tests or the workflow.


Generated by Claude Code

Comment thread .github/workflows/code-review.yml
Comment thread .github/workflows/code-review.yml

@auxesis auxesis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thanks for the fix @tobyhede. ❤️

@cipherstash-bot cipherstash-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Recommendation: 🟢 merge as it is

Nothing in this review must change before merge. The three findings are test gaps, and a follow-up pull request can fix them.

This review does not cover two points that the pull request discussion already raises: a missing enable condition and a missing concurrency group. This review does not decide if those two points must be fixed before merge. Before merge, read the discussion to learn what each point means and to decide if it must be fixed.

The three findings are test gaps. In each case, the workflow behaves correctly today:

  • The test checks the text of the job's if: condition, but it does not evaluate it.
  • No test runs the step with a failed curl request.
  • No trigger id test case checks the ^ anchor of the regex.

I checked each finding directly:

  • I ran runsWhen on an edited if: condition.
  • I ran the step's script under bash with a curl stub that exits 22.
  • I ran bash on the regex with each anchor removed.

I did not run the vitest suites, because the workspace dependencies are not installed.

How this review was made
Agent Model Review type Result
claude claude-opus-5-5 test-gap 3 found, 3 posted
codex gpt-5.6-terra test-gap 1 found, 1 posted

Synthesis: claude-opus-5-5 merged the findings, removed duplicates and dropped findings it could not confirm in the code. 1 posted finding(s) were raised by two or more models.

Plain language: claude-opus-5-5 read every comment as a new reader would. No comment had a problem that stopped the reader acting, so none was rewritten. It also rewrote the review body.

Stack: not part of a stack.

Context loaded: the description, 0 linked issue(s) and 6 discussion entries.

Comment thread scripts/__tests__/code-review-workflow.test.mjs
Comment thread scripts/__tests__/code-review-workflow.test.mjs
Comment thread scripts/__tests__/code-review-workflow.test.mjs
A reopen or a draft/ready toggle in quick succession fired one routine
session per event. A concurrency group keyed on the pull request queues
the second run instead, and a third replaces the queued one, so a burst
fires at most twice. It does not cancel a running request, which may
already have started a session.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TP99TH97eaf1rX12JSRae
The review is advisory, so the step now has continue-on-error: an outage
or a revoked token shows as a failed step in the run, not as a red check.

The tests also cover three gaps a review found: the job's if: is
evaluated with runsWhen rather than string-matched, a curl that exits 22
must fail the step, and a path before trig_ must be refused, which pins
the regex's ^ anchor.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TP99TH97eaf1rX12JSRae
@tobyhede
tobyhede merged commit 6e9f1ee into main Oct 19, 2026
28 checks passed
@tobyhede
tobyhede deleted the claude/project-thread-p2p4dl branch October 19, 2026 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pull requests get no automated review while claude-review.yml is off: fire a Claude code-review routine instead

5 participants