## Summary - Add prek auto-fix step (format/lint changed files, commit & push) - Add coverage analysis step (compare PR vs main, enforce 75% for new code) - Add uv setup and dependency install to pr-review job - Change pr-review permissions to allow pushing fixes Syncs with recent improvements made to the CLI repo.
188 lines
8.3 KiB
YAML
188 lines
8.3 KiB
YAML
name: Claude Code
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, synchronize, ready_for_review, reopened]
|
|
issue_comment:
|
|
types: [created]
|
|
pull_request_review_comment:
|
|
types: [created]
|
|
issues:
|
|
types: [opened, assigned]
|
|
pull_request_review:
|
|
types: [submitted]
|
|
|
|
jobs:
|
|
# Automatic PR review (can fix linting issues and push)
|
|
pr-review:
|
|
if: github.event_name == 'pull_request'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
issues: read
|
|
id-token: write
|
|
actions: read
|
|
defaults:
|
|
run:
|
|
working-directory: django/aiservice
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.event.pull_request.head.ref }}
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v6
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
uv venv --seed
|
|
uv sync
|
|
|
|
- name: Run Claude Code
|
|
id: claude
|
|
uses: anthropics/claude-code-action@v1
|
|
with:
|
|
use_foundry: "true"
|
|
use_sticky_comment: true
|
|
prompt: |
|
|
REPO: ${{ github.repository }}
|
|
PR NUMBER: ${{ github.event.pull_request.number }}
|
|
EVENT: ${{ github.event.action }}
|
|
|
|
IMPORTANT: This repo has Python code in `django/aiservice/`. Run uv/prek commands from that directory.
|
|
|
|
## STEP 1: Run pre-commit checks and fix issues
|
|
|
|
First, run `cd django/aiservice && uv run prek run --from-ref origin/main` to check for linting/formatting issues on files changed in this PR.
|
|
|
|
If there are any issues:
|
|
- For SAFE auto-fixable issues (formatting, import sorting, trailing whitespace, etc.), run the command again to auto-fix them
|
|
- Stage the fixed files with `git add`
|
|
- Commit with message "style: auto-fix linting issues"
|
|
- Push the changes with `git push`
|
|
|
|
Do NOT attempt to fix:
|
|
- Type errors that require logic changes
|
|
- Complex refactoring suggestions
|
|
- Anything that could change behavior
|
|
|
|
## STEP 2: Review the PR
|
|
|
|
${{ github.event.action == 'synchronize' && 'This is a RE-REVIEW after new commits. First, get the list of changed files in this latest push using `gh pr diff`. Review ONLY the changed files. Check ALL existing review comments and resolve ones that are now fixed.' || 'This is the INITIAL REVIEW.' }}
|
|
|
|
Review this PR focusing ONLY on:
|
|
1. Critical bugs or logic errors
|
|
2. Security vulnerabilities
|
|
3. Breaking API changes
|
|
4. Test failures (methods with typos that wont run)
|
|
|
|
IMPORTANT:
|
|
- First check existing review comments using `gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/comments`. For each existing comment, check if the issue still exists in the current code.
|
|
- If an issue is fixed, use `gh api --method PATCH repos/${{ github.repository }}/pulls/comments/COMMENT_ID -f body="✅ Fixed in latest commit"` to resolve it.
|
|
- Only create NEW inline comments for HIGH-PRIORITY issues found in changed files.
|
|
- Limit to 5-7 NEW comments maximum per review.
|
|
- Use CLAUDE.md for project-specific guidance.
|
|
- Use `gh pr comment` for summary-level feedback.
|
|
- Use `mcp__github_inline_comment__create_inline_comment` sparingly for critical code issues only.
|
|
|
|
## STEP 3: Coverage analysis
|
|
|
|
Analyze test coverage for changed files:
|
|
|
|
1. Get the list of Python files changed in this PR (excluding tests):
|
|
`git diff --name-only origin/main...HEAD -- '*.py' | grep -v test`
|
|
|
|
2. Run tests with coverage on the PR branch (from django/aiservice):
|
|
`cd django/aiservice && uv run coverage run -m pytest -q --tb=no`
|
|
`cd django/aiservice && uv run coverage json -o coverage-pr.json`
|
|
|
|
3. Get coverage for changed files only:
|
|
`cd django/aiservice && uv run coverage report --include="<changed_files_comma_separated>"`
|
|
|
|
4. Compare with main branch coverage:
|
|
- Checkout main: `git checkout origin/main`
|
|
- Run coverage: `cd django/aiservice && uv run coverage run -m pytest -q --tb=no && uv run coverage json -o coverage-main.json`
|
|
- Checkout back: `git checkout -`
|
|
|
|
5. Analyze the diff to identify:
|
|
- NEW FILES: Files that don't exist on main (require good test coverage)
|
|
- MODIFIED FILES: Files with changes (changes must be covered by tests)
|
|
|
|
6. Report in PR comment with a markdown table:
|
|
- Coverage % for each changed file (PR vs main)
|
|
- Overall coverage change
|
|
- For NEW files: Flag if coverage is below 75%
|
|
- For MODIFIED files: Flag if the changed lines are not covered by tests
|
|
- Flag if overall coverage decreased
|
|
|
|
Coverage requirements:
|
|
- New implementations/files: Must have ≥75% test coverage
|
|
- Modified code: Changed lines should be exercised by existing or new tests
|
|
- No coverage regressions: Overall coverage should not decrease
|
|
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 list:*),Bash(gh issue view:*),Bash(gh issue list:*),Bash(gh api:*),Bash(cd django/aiservice*),Bash(uv run prek *),Bash(uv run coverage *),Bash(uv run pytest *),Bash(git status*),Bash(git add *),Bash(git commit *),Bash(git push*),Bash(git diff *),Bash(git checkout *),Read,Glob,Grep"'
|
|
additional_permissions: |
|
|
actions: read
|
|
env:
|
|
ANTHROPIC_FOUNDRY_API_KEY: ${{ secrets.ANTHROPIC_FOUNDRY_API_KEY }}
|
|
ANTHROPIC_FOUNDRY_BASE_URL: ${{ secrets.ANTHROPIC_FOUNDRY_BASE_URL }}
|
|
|
|
# @claude mentions (can edit and push)
|
|
claude-mention:
|
|
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: write
|
|
pull-requests: write
|
|
issues: read
|
|
id-token: write
|
|
actions: read
|
|
defaults:
|
|
run:
|
|
working-directory: django/aiservice
|
|
steps:
|
|
- name: Get PR head ref
|
|
id: pr-ref
|
|
working-directory: .
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
# For issue_comment events, we need to fetch the PR info
|
|
if [ "${{ github.event_name }}" = "issue_comment" ]; then
|
|
PR_REF=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }} --jq '.head.ref')
|
|
echo "ref=$PR_REF" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "ref=${{ github.event.pull_request.head.ref || github.head_ref }}" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ steps.pr-ref.outputs.ref }}
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v6
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
uv venv --seed
|
|
uv sync
|
|
|
|
- name: Run Claude Code
|
|
id: claude
|
|
uses: anthropics/claude-code-action@v1
|
|
with:
|
|
use_foundry: "true"
|
|
claude_args: '--allowedTools "Read,Edit,Write,Glob,Grep,Bash(git status*),Bash(git diff*),Bash(git add *),Bash(git commit *),Bash(git push*),Bash(git log*),Bash(cd django/aiservice*),Bash(uv run prek *),Bash(prek *),Bash(uv run ruff *),Bash(uv run pytest *),Bash(uv run mypy *),Bash(uv run coverage *),Bash(gh pr comment*),Bash(gh pr view*),Bash(gh pr diff*)"'
|
|
additional_permissions: |
|
|
actions: read
|
|
env:
|
|
ANTHROPIC_FOUNDRY_API_KEY: ${{ secrets.ANTHROPIC_FOUNDRY_API_KEY }}
|
|
ANTHROPIC_FOUNDRY_BASE_URL: ${{ secrets.ANTHROPIC_FOUNDRY_BASE_URL }}
|