Skip to content

Commit 500c480

Browse files
committed
Add Claude PR review workflow
1 parent cd5dbd1 commit 500c480

3 files changed

Lines changed: 654 additions & 22 deletions

File tree

‎.github/workflows/claude.yml‎

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: Claude Code
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
claude_model:
7+
description: 'Claude model used for manual @claude requests'
8+
type: string
9+
required: false
10+
default: claude-opus-4-8
11+
claude_max_turns:
12+
description: 'Maximum Claude Code turns for manual @claude requests'
13+
type: number
14+
required: false
15+
default: 10
16+
claude_trigger_phrase:
17+
description: 'Phrase that triggers Claude in comments, reviews, issues, and issue titles'
18+
type: string
19+
required: false
20+
default: '@claude'
21+
claude_allowed_tools:
22+
description: 'Comma-separated Claude Code tools allowed during manual @claude requests'
23+
type: string
24+
required: false
25+
default: Read,Edit,MultiEdit,Write,Bash(git diff:*),Bash(git status:*),Bash(git rev-parse:*),Bash(git log:*),Bash(git show:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*)
26+
claude_extra_args:
27+
description: 'Additional raw Claude Code CLI arguments'
28+
type: string
29+
required: false
30+
default: ''
31+
outputs:
32+
test_ref:
33+
description: 'Pull request branch ref that a caller can pass to its local CI workflow'
34+
value: ${{ jobs.resolve_test_ref.outputs.ref }}
35+
36+
jobs:
37+
claude:
38+
if: |
39+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, inputs.claude_trigger_phrase)) ||
40+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, inputs.claude_trigger_phrase)) ||
41+
(github.event_name == 'pull_request_review' && contains(github.event.review.body || '', inputs.claude_trigger_phrase)) ||
42+
(github.event_name == 'issues' && (contains(github.event.issue.body || '', inputs.claude_trigger_phrase) || contains(github.event.issue.title || '', inputs.claude_trigger_phrase)))
43+
runs-on: ubuntu-latest
44+
permissions:
45+
contents: write
46+
pull-requests: write
47+
issues: write
48+
id-token: write
49+
actions: read
50+
steps:
51+
- name: Checkout repository
52+
uses: actions/checkout@v6
53+
with:
54+
fetch-depth: 1
55+
56+
- name: Run Claude Code
57+
id: claude
58+
uses: anthropics/claude-code-action@v1
59+
with:
60+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
61+
trigger_phrase: ${{ inputs.claude_trigger_phrase }}
62+
additional_permissions: |
63+
actions: read
64+
claude_args: |
65+
--model ${{ inputs.claude_model }}
66+
--max-turns ${{ inputs.claude_max_turns }}
67+
--allowedTools "${{ inputs.claude_allowed_tools }}"
68+
--append-system-prompt "## General\n\nIf requirements are genuinely ambiguous and you cannot make a reasonable assumption, post all your questions in a single comment and stop. Do not ask about things you can decide yourself or infer from the codebase.\n\n## Pull request\n\nWhen creating or updating a pull request, use this PR template for the body:\n\n```\n## Summary\n\nCloses #<issue_number>\n\nDescribe the change.\n\n## Security implications\n\n- [ ] No security impact\n- [ ] Has security impact - described as:\n\n## Testing\n\nDescribe how this was tested.\n\n## Checklist\n\n- [ ] Linked to an issue\n- [ ] Tested\n- [ ] Asked for a review\n```\n\nFill in the template with the relevant details for the PR."
69+
${{ inputs.claude_extra_args }}
70+
71+
resolve_test_ref:
72+
needs: claude
73+
if: |
74+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, inputs.claude_trigger_phrase)) ||
75+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, inputs.claude_trigger_phrase)) ||
76+
(github.event_name == 'pull_request_review' && contains(github.event.review.body || '', inputs.claude_trigger_phrase))
77+
runs-on: ubuntu-latest
78+
permissions:
79+
pull-requests: read
80+
outputs:
81+
ref: ${{ steps.resolve.outputs.ref }}
82+
steps:
83+
- name: Resolve test ref
84+
id: resolve
85+
uses: actions/github-script@v8
86+
with:
87+
script: |
88+
let ref = '';
89+
90+
if (context.eventName === 'issue_comment' && context.payload.issue?.pull_request?.url) {
91+
const { data: pullRequest } = await github.request(context.payload.issue.pull_request.url);
92+
ref = pullRequest.head.ref;
93+
} else {
94+
ref = context.payload.pull_request?.head?.ref || context.payload.repository?.default_branch || '';
95+
}
96+
97+
core.setOutput('ref', ref);

0 commit comments

Comments
 (0)