Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 33 additions & 12 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,42 @@
workflow_call:
inputs:
runs-on:
description: "Runner label(s) as a JSON array string (parsed with fromJSON). Defaults to a GitHub-hosted image; pass '[\"self-hosted\", \"linux\", \"x64\"]' to use a self-hosted pool instead."
description: "Runner label(s) as a JSON array string (parsed with fromJSON). Defaults to the self-hosted pool. Public/open-source repos opt out by passing '[\"ubuntu-24.04\"]'."
type: string
# GitHub-hosted by default. This job reads the PR diff and calls the
# Claude API -- it needs no private-network access, no local toolchain
# and no persistent state, so a self-hosted runner buys it nothing.
# Self-hosted by default since 2026-09-20, matching claude.yml.
#
# It cost quite a lot, though: on a contended pool the review queued
# 40-77 minutes for 3-6 minutes of work, routinely finishing after the
# PR had already merged, and failed outright at runner assignment
# roughly one run in six. Both faults are queueing artefacts, not
# review problems.
# On the merits, hosted is the better fit: this job reads the PR diff
# and calls the Claude API, so it needs no private-network access, no
# local toolchain and no persistent state, and a self-hosted runner
# buys it nothing. It cost quite a lot, too -- on a contended pool the
# review queued 40-77 minutes for 3-6 minutes of work, routinely
# finishing after the PR had already merged, and failed outright at
# runner assignment roughly one run in six. Both are queueing
# artefacts, not review problems, and both are still true.
#
# Pinned to a dated image rather than ubuntu-latest so a GitHub-side
# image bump is an intentional, reviewable change.
default: '["ubuntu-24.04"]'
# What changed is that a hosted job may not run AT ALL. With Actions
# credits exhausted, every hosted job fails about two seconds after
# queueing with "The job was not started because recent account
# payments have failed or your spending limit needs to be increased".
# Across HordiaLabs, Sproncy and Regularmusic that is 41 private repos
# whose review check went permanently red on a default they never
# chose -- and because every OTHER workflow in those repos already
# passes a self-hosted `runs-on`, it reads as one flaky reviewer
# rather than as a billing stop.
#
# A slow, occasionally flaky review beats no review, and this one is
# advisory regardless: the claude-code-action step below is
# continue-on-error, so it cannot block a PR on either runner.
#
# PUBLIC REPOS SHOULD OPT OUT, and not only for the free minutes:
# running fork PRs on a self-hosted pool is the hazard GitHub warns
# about. No public repo consumes this reusable today (checked across
# the three orgs and nkg/*), so the default is safe as it stands --
# but a new public consumer must pass '["ubuntu-24.04"]'.
#
# Revisit when credits reset; hosted is the right default the moment
# it can actually start a job.
default: '["self-hosted", "linux", "x64"]'
timeout-minutes:
type: number
default: 30
Expand All @@ -36,7 +57,7 @@
type: boolean
default: false
plugin-marketplace:
description: "Optional plugin marketplace. Empty by default — the code-review plugin is broken on current Claude Code (spawns a non-existent claude-haiku agent), so we use a direct review prompt instead."

Check warning on line 60 in .github/workflows/claude-code-review.yml

View workflow job for this annotation

GitHub Actions / lint / yamllint

60:201 [line-length] line too long (212 > 200 characters)
type: string
default: ""
plugins:
Expand Down Expand Up @@ -103,10 +124,10 @@
# on Claude Code 2.1.x — it spawns a non-existent claude-haiku agent
# and posts nothing). Single line so it survives format(); a caller
# passing `prompt` overrides it.
prompt: ${{ inputs.prompt != '' && inputs.prompt || format('Review pull request {0}#{1} for bugs, security issues, performance problems, and missing test coverage. Follow the repo''s CLAUDE.md conventions if present. Post each specific problem as an inline comment with the mcp__github_inline_comment__create_inline_comment tool, and leave one short top-level summary via `gh pr comment`. Only flag real issues; if there are none, say so briefly.', github.repository, github.event.pull_request.number) }}

Check warning on line 127 in .github/workflows/claude-code-review.yml

View workflow job for this annotation

GitHub Actions / lint / yamllint

127:201 [line-length] line too long (514 > 200 characters)
# Without an explicit --allowedTools the inline-comment MCP tool is
# denied, so Claude runs but posts nothing ("No buffered inline
# comments" + permission_denials). Default to Anthropic's documented
# PR-review tool set (examples/pr-review-comprehensive.yml); a caller
# passing claude-args overrides it entirely.
claude_args: ${{ inputs.claude-args != '' && inputs.claude-args || '--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"' }}

Check warning on line 133 in .github/workflows/claude-code-review.yml

View workflow job for this annotation

GitHub Actions / lint / yamllint

133:201 [line-length] line too long (208 > 200 characters)
Loading