Add Claude Code GitHub Workflow#613
Conversation
There was a problem hiding this comment.
Pull request overview
Adds Anthropic Claude Code GitHub Actions workflows to enable invoking Claude via GitHub events and to run an automated PR code review job.
Changes:
- Introduces a
Claude Codeworkflow that runs when@claudeis detected on several issue/PR-related events. - Introduces a
Claude Code Reviewworkflow that runs Claude-based review automatically on PR lifecycle events.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
.github/workflows/claude.yml |
New workflow to run Claude Code when @claude is detected across comments/reviews/issues. |
.github/workflows/claude-code-review.yml |
New workflow to run an automatic Claude-driven code review on PR open/sync events. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| pull_request_review_comment: | ||
| types: [created] | ||
| issues: | ||
| types: [opened, assigned] |
There was a problem hiding this comment.
Including issues: types: [opened, assigned] means that if an issue title/body contains @claude, the workflow will re-run every time the issue is assigned (even when no new mention was made). If the desired trigger is “only when someone asks Claude,” consider removing assigned (and/or using issue_comment only), or add additional checks so only newly-created comments/mentions trigger a run.
| types: [opened, assigned] | |
| types: [opened] |
| claude: | ||
| if: | | ||
| (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 | ||
| permissions: | ||
| contents: read | ||
| pull-requests: read | ||
| issues: read | ||
| id-token: write |
There was a problem hiding this comment.
The workflow can be triggered by anyone who can create an issue/PR comment containing @claude, but there is no guard to restrict execution to users with write/maintain/admin permissions (or at least repo collaborators). This is a security/cost risk because the job runs with repository read access and id-token: write. Add an explicit permission check (e.g., via github.event.sender + repos.getCollaboratorPermissionLevel in a preliminary step, and gate the job) and consider removing id-token: write unless the action strictly requires OIDC.
| claude: | |
| if: | | |
| (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 | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| issues: read | |
| id-token: write | |
| permission-check: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| has_permission: ${{ steps.check-permission.outputs.has_permission }} | |
| steps: | |
| - name: Check if sender has sufficient permissions | |
| id: check-permission | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ github.token }} | |
| script: | | |
| const sender = context.payload.sender && context.payload.sender.login; | |
| if (!sender) { | |
| core.setOutput('has_permission', 'false'); | |
| return; | |
| } | |
| try { | |
| const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| username: sender, | |
| }); | |
| const level = data.permission; | |
| const allowedLevels = ['admin', 'maintain', 'write']; | |
| const hasPermission = allowedLevels.includes(level); | |
| core.setOutput('has_permission', hasPermission ? 'true' : 'false'); | |
| } catch (error) { | |
| // If the user is not a collaborator or an error occurs, deny by default | |
| core.info(`Permission check failed or user is not a collaborator: ${error.message}`); | |
| core.setOutput('has_permission', 'false'); | |
| } | |
| claude: | |
| needs: permission-check | |
| if: | | |
| needs.permission-check.outputs.has_permission == 'true' && | |
| ( | |
| (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 | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| issues: read |
| on: | ||
| issue_comment: | ||
| types: [created] | ||
| pull_request_review_comment: | ||
| types: [created] | ||
| issues: | ||
| types: [opened, assigned] | ||
| pull_request_review: | ||
| types: [submitted] | ||
|
|
There was a problem hiding this comment.
This workflow is configured to trigger on issues opened/assigned and pull_request_review submitted events (and it scans issue titles/bodies and review bodies), but the PR description says the integration is invoked by mentioning @claude in an issue/PR comment. Either narrow the triggers to match the documented behavior (comments only), or update the PR description to reflect that opening/assigning issues and submitting PR reviews can also trigger runs.
| on: | ||
| pull_request: | ||
| types: [opened, synchronize, ready_for_review, reopened] | ||
| # Optional: Only run on specific file changes | ||
| # paths: | ||
| # - "src/**/*.ts" | ||
| # - "src/**/*.tsx" | ||
| # - "src/**/*.js" | ||
| # - "src/**/*.jsx" | ||
|
|
||
| jobs: | ||
| claude-review: | ||
| # Optional: Filter by PR author | ||
| # if: | | ||
| # github.event.pull_request.user.login == 'external-contributor' || | ||
| # github.event.pull_request.user.login == 'new-developer' || | ||
| # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' | ||
|
|
||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| pull-requests: read | ||
| issues: read | ||
| id-token: write | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 1 | ||
|
|
||
| - name: Run Claude Code Review | ||
| id: claude-review | ||
| uses: anthropics/claude-code-action@v1 | ||
| with: | ||
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | ||
| plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' | ||
| plugins: 'code-review@claude-code-plugins' |
There was a problem hiding this comment.
pull_request workflows do not receive repository secrets for PRs coming from forks, so secrets.CLAUDE_CODE_OAUTH_TOKEN will be empty and this job will fail on fork-based contributions. If you want to support external PRs, add a fork guard (e.g., only run when github.event.pull_request.head.repo.full_name == github.repository) or switch to a safer pull_request_target pattern with additional hardening.
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| pull-requests: read | ||
| issues: read | ||
| id-token: write | ||
|
|
There was a problem hiding this comment.
The permissions in this workflow are read-only (pull-requests: read, contents: read, issues: read). With these scopes, the action cannot create PR comments/reviews or push branches/commits, which conflicts with the PR description’s claim that Claude can “create comments, branches, and commits.” Either adjust the permissions (and document the security implications) or update the PR description/expectations to reflect read-only behavior.
| permissions: | ||
| contents: read | ||
| pull-requests: read | ||
| issues: read | ||
| id-token: write |
There was a problem hiding this comment.
The job permissions here are read-only (pull-requests: read, issues: read, contents: read). If the intent is for Claude to post replies back to the PR/issue thread (as described in the PR), this workflow won’t be able to do so using GITHUB_TOKEN. Either grant the minimum required write permissions (e.g., issues: write / pull-requests: write) or update the PR description to reflect that Claude will only run without posting back to GitHub.
🤖 Installing Claude Code GitHub App
This PR adds a GitHub Actions workflow that enables Claude Code integration in our repository.
What is Claude Code?
Claude Code is an AI coding agent that can help with:
How it works
Once this PR is merged, we'll be able to interact with Claude by mentioning @claude in a pull request or issue comment.
Once the workflow is triggered, Claude will analyze the comment and surrounding context, and execute on the request in a GitHub action.
Important Notes
Security
There's more information in the Claude Code action repo.
After merging this PR, let's try mentioning @claude in a comment on any PR to get started!