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
71 changes: 66 additions & 5 deletions .github/workflows/claude-review.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,39 @@
name: Claude Code Review with Progress Tracking

# Trigger Claude review on PR lifecycle events and explicit mentions

on:
# Trigger when a new issue comment is created (for @claude mentions)
issue_comment:
types: [created]
# Trigger when a PR review comment is created/edited/deleted (for @claude mentions)
pull_request_review_comment:
types: [created, edited, deleted]
# Trigger on new or assigned issues (for future extension or automation)
issues:
types: [opened, assigned]
# Trigger when a PR review is submitted (for @claude in the review body)
pull_request_review:
types: [submitted]
# Main trigger for PR events, using pull_request_target for elevated permissions
pull_request_target:
types: [opened, synchronize, reopened]

permissions:
# Read repository contents needed for code review
contents: read
# Allow Claude to post review comments on pull requests
pull-requests: write
# Allow Claude to interact with issues if needed
issues: write
# Allow this workflow to manage its own actions if required
actions: write

jobs:
claude-review-with-tracking:
runs-on: ubuntu-latest

# Only run for trusted authors or when explicitly mentioned by them
if: |
(
github.event_name == 'pull_request_target' &&
Expand Down Expand Up @@ -51,30 +63,79 @@
)

steps:
# Checkout the repository at the appropriate commit for review
- name: Checkout repository
uses: actions/checkout@v4
with:
# Use PR head SHA for pull_request_target, fallback to current SHA otherwise
fetch-depth: 0
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}

# Handle fork branches for pull_request_target events
- name: Setup Fork Remote (for pull_request_target)
if: ${{ github.event_name == 'pull_request_target' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
HEAD_REF="${{ github.event.pull_request.head.ref }}"

Check failure

Code scanning / CodeQL

Code injection Critical

Potential code injection in
${ github.event.pull_request.head.ref }
, which may be controlled by an external user (
pull_request_review_comment
).
Potential code injection in
${ github.event.pull_request.head.ref }
, which may be controlled by an external user (
pull_request_review
).
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex Please try to fix the security issue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Testing

  • ⚠️ Not run (workflow-only changes).

View task →

HEAD_OWNER="${{ github.event.pull_request.head.repo.owner.login }}"
HEAD_REPO="${{ github.event.pull_request.head.repo.name }}"
CURRENT_OWNER="${{ github.repository_owner }}"

# For forked PRs, temporarily change origin URL to fork repository
# This allows claude-code-action to fetch the PR branch correctly
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "This allows claude-code-action to fetch the PR branch correctly" but this is misleading. The git remote manipulation happens in the GitHub Actions runner's context, not within the claude-code-action itself. The action will use the already-checked-out state. Consider revising to: "This ensures the correct PR branch is available for claude-code-action to review".

Suggested change
# This allows claude-code-action to fetch the PR branch correctly
# This ensures the correct PR branch is available for claude-code-action to review

Copilot uses AI. Check for mistakes.
if [ "$HEAD_OWNER" != "$CURRENT_OWNER" ]; then
echo "PR is from fork: $HEAD_OWNER/$HEAD_REPO"
FORK_URL="https://github.com/$HEAD_OWNER/$HEAD_REPO.git"
echo "Temporarily changing origin URL to fork: $FORK_URL"
git remote set-url origin "$FORK_URL"
git fetch origin "$HEAD_REF"
git branch "$HEAD_REF" "origin/$HEAD_REF" 2>/dev/null || git branch -f "$HEAD_REF" "origin/$HEAD_REF"
fi
Comment on lines +88 to +95
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After changing the remote URL to point to the fork, the workflow doesn't restore it back to the original repository. This could cause issues if subsequent steps or actions expect the origin to point to the base repository. Consider adding a step to restore the original remote URL after the Claude review completes, or document why this is intentional.

Copilot uses AI. Check for mistakes.

# For comment-driven triggers, ensure we have the correct PR branch checked out
- name: Checkout PR Branch (for comments)
if: ${{ github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr checkout ${{ github.event.issue.number || github.event.pull_request.number }}

PR_NUMBER=${{ github.event.issue.number || github.event.pull_request.number }}

# Fetch PR metadata: head branch name and source repository
PR_DATA=$(gh pr view $PR_NUMBER --json headRefName,headRepositoryOwner,headRepository,baseRefName)
HEAD_REF=$(echo "$PR_DATA" | jq -r '.headRefName')
HEAD_OWNER=$(echo "$PR_DATA" | jq -r '.headRepositoryOwner.login')
HEAD_REPO=$(echo "$PR_DATA" | jq -r '.headRepository.name')
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable HEAD_REPO is extracted but never used in this step. It appears to be extracted for consistency with the fork setup logic above, but since it's not referenced anywhere in the subsequent commands, it represents unnecessary work. Consider removing this extraction or documenting why it's needed for future use.

Copilot uses AI. Check for mistakes.
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BASE_BRANCH variable is extracted from the PR metadata but never used in this step. This represents unnecessary processing since the value isn't referenced in any subsequent commands. Consider removing this extraction unless it's needed for future functionality.

Suggested change
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')

Copilot uses AI. Check for mistakes.
CURRENT_OWNER="${{ github.repository_owner }}"

# For forked PRs, temporarily change origin URL to fork repository
# This allows claude-code-action to fetch the PR branch correctly
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "This allows claude-code-action to fetch the PR branch correctly" but this is misleading. The git remote manipulation happens in the GitHub Actions runner's context, not within the claude-code-action itself. The action will use the already-checked-out state. Consider revising to: "This ensures the correct PR branch is available for claude-code-action to review".

Suggested change
# This allows claude-code-action to fetch the PR branch correctly
# This ensures the correct PR branch is available for claude-code-action to review

Copilot uses AI. Check for mistakes.
if [ "$HEAD_OWNER" != "$CURRENT_OWNER" ]; then
echo "PR is from fork: $HEAD_OWNER/$HEAD_REPO"
FORK_URL="https://github.com/$HEAD_OWNER/$HEAD_REPO.git"
echo "Temporarily changing origin URL to fork: $FORK_URL"
git remote set-url origin "$FORK_URL"
fi
Comment on lines +115 to +120
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After changing the remote URL to point to the fork, the workflow doesn't restore it back to the original repository. This could cause issues if subsequent steps or actions expect the origin to point to the base repository. Consider adding a step to restore the original remote URL after the Claude review completes, or document why this is intentional.

Copilot uses AI. Check for mistakes.

# Fetch and checkout the PR branch
git fetch origin "$HEAD_REF"
git branch "$HEAD_REF" "origin/$HEAD_REF" 2>/dev/null || git branch -f "$HEAD_REF" "origin/$HEAD_REF"
git checkout "$HEAD_REF"

# Invoke Claude to perform an automated PR review with progress tracking
- name: PR Review with Progress Tracking
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}

# Enable progress tracking
# Enable progress tracking and show full Claude output in logs
track_progress: true
show_full_output: true

# Your custom review instructions
# Custom review instructions passed to Claude
prompt: |
REPO: ${{ github.repository }}

Expand Down Expand Up @@ -108,6 +169,6 @@
Provide detailed feedback using inline comments for specific issues.
Use top-level comments for general observations or praise.

# Tools for comprehensive PR review
# Restrict tools that Claude can use during the review
claude_args: |
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"
Loading