Skip to content
Merged
Show file tree
Hide file tree
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
75 changes: 0 additions & 75 deletions .github/dependabot.yml

This file was deleted.

132 changes: 132 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Claude code review.
#
# This complements — it does not replace — the automatic Copilot review that
# runs on every PR via the "Code Quality Copilot review for default branch"
# ruleset. Copilot does the fast first pass; Claude does the deeper one, and
# only when asked, so routine PRs cost nothing.
#
# Two ways in:
# 1. Mention @claude in an issue, a PR comment, or a review comment.
# 2. Add the `deep-review` label to a PR for a full review pass.
#
# Requires an ANTHROPIC_API_KEY secret (org-level is easiest — one secret
# covers every repo). Without it both jobs fail fast with a clear message
# rather than reviewing silently with no credentials.
name: Claude Code Review

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
pull_request_review:
types: [submitted]
issues:
types: [opened, assigned, labeled]
pull_request:
types: [labeled]

# Never run two reviews on the same PR at once; a new trigger supersedes the
# one in flight.
concurrency:
group: claude-review-${{ github.event.pull_request.number || github.event.issue.number || github.ref }}
cancel-in-progress: true

jobs:
# ── 1. On-demand: someone wrote @claude ──────────────────────────────────
mention:
if: |
github.event_name != 'pull_request' && (
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
)
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
steps:
- name: Check credentials
env:
KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
if [ -z "$KEY" ]; then
echo "::error::ANTHROPIC_API_KEY is not set. Add it as an organisation or repository secret."
exit 1
fi

- uses: actions/checkout@v6
with:
fetch-depth: 1

- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
use_sticky_comment: true

# ── 2. Full pass: PR labelled `deep-review` ──────────────────────────────
deep-review:
if: github.event_name == 'pull_request' && github.event.label.name == 'deep-review'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
pull-requests: write
id-token: write
steps:
- name: Check credentials
env:
KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
if [ -z "$KEY" ]; then
echo "::error::ANTHROPIC_API_KEY is not set. Add it as an organisation or repository secret."
exit 1
fi

- uses: actions/checkout@v6
with:
fetch-depth: 1

- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
use_sticky_comment: true
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}

Review this pull request. The PR branch is already checked out in
the working directory.

This repository follows the standards in its own CLAUDE.md,
QUALITY.md, TESTING.md, SECURITY.md and VERIFY.md — read the ones
that apply to the changed files and review against them, not
against generic style preferences.

Prioritise, in this order:
1. Correctness — logic errors, unhandled failure paths, integer
overflow/underflow, memory safety, race conditions.
2. Security — unvalidated input crossing a boundary, injection,
authorization that checks only authentication, secrets in
source or logs.
3. Tests — does a new behaviour have a test that would actually
fail without the fix? Flag assertions that cannot fail, and
tests that only check the negative case.
4. Maintainability — only where it genuinely impedes a reader.

Report what you verified and what you could not. Say plainly when
a concern is unverified rather than implying you checked it. If
nothing needs changing, say so in one line — do not manufacture
findings.

Use `gh pr comment` for top-level feedback.
Use `mcp__github_inline_comment__create_inline_comment` (with
`confirmed: true`) for specific lines.
Only post GitHub comments — do not return review text as a message.

claude_args: |
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr checks:*)"
Loading