Skip to content

Claude Code Review #397

Claude Code Review

Claude Code Review #397

name: Claude Code Review
on:
workflow_run:
workflows: ["Prepare Claude Review"]
types: [completed]
issue_comment:
types: [created]
jobs:
# PATH A: Auto-trigger via workflow_run (trusted authors, or label-approved fork PRs)
claude-review-auto:
if: |
github.event_name == 'workflow_run' &&
github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
actions: read
steps:
- name: Download PR metadata
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: pr-metadata
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Validate PR metadata
id: pr
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WORKFLOW_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
REPO: ${{ github.repository }}
run: |
PR_NUMBER=$(cat pr_number.txt)
# Validate PR number is a positive integer (defense against artifact tampering)
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
echo "::error::Invalid PR number in artifact: not an integer"
exit 1
fi
# Cross-reference: verify the PR's head SHA matches the workflow_run's head SHA
# github.event.workflow_run.head_sha is set by GitHub and cannot be modified by forks
ACTUAL_SHA=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json headRefOid -q '.headRefOid')
if [ "$ACTUAL_SHA" != "$WORKFLOW_HEAD_SHA" ]; then
echo "::error::SHA mismatch -- artifact PR ($ACTUAL_SHA) != workflow trigger ($WORKFLOW_HEAD_SHA)"
echo "::error::This may indicate artifact tampering. Aborting."
exit 1
fi
echo "number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
echo "Validated PR #$PR_NUMBER (SHA: $WORKFLOW_HEAD_SHA)"
- name: Checkout base branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 1
- name: Run Claude Code Review
uses: anthropics/claude-code-action@3ac52d0da9f8ec9ca7b4dc23bb477e36ef9c77a9 # v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
plugin_marketplaces: "https://github.com/anthropics/claude-code.git"
plugins: "code-review@claude-code-plugins"
prompt: "/code-review:code-review ${{ github.repository }}/pull/${{ steps.pr.outputs.number }}"
# PATH B: Manual trigger via /claude-review comment on a PR
claude-review-manual:
if: |
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
(
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR' ||
github.event.comment.author_association == 'OWNER'
) &&
contains(github.event.comment.body, '/claude-review')
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
steps:
- name: Checkout base branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 1
- name: Run Claude Code Review
uses: anthropics/claude-code-action@3ac52d0da9f8ec9ca7b4dc23bb477e36ef9c77a9 # v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
plugin_marketplaces: "https://github.com/anthropics/claude-code.git"
plugins: "code-review@claude-code-plugins"
prompt: "/code-review:code-review ${{ github.repository }}/pull/${{ github.event.issue.number }}"