Claude Code CI/CD Integration: GitHub Actions Auto Review & Test Generation
🩺 Summary
PR submitted. Waiting for human review. Reviewer says "code ...
📝 Details
PR submitted. Waiting for human review. Reviewer says "code style doesn't match." Fix and push. Wait for round two. A simple PR can stall in review limbo for three days. Claude Code writes code fast, but your team's CI/CD pipeline is still stuck in the manual era. This isn't an efficiency gap—it's a workflow fracture. Here's how to build a full CI pipeline with Claude Code + GitHub Actions: auto-review, auto-testing, auto-description. Code goes from commit to merge without a single human formatting nitpick.
## 1. The Fastest CI: Embed Claude Code in GitHub Actions
Claude Code has no official GitHub Action, but Anthropic ships a CLI tool. One command: `npx @anthropic-ai/claude-code`. Drop it into GitHub Actions and you've got the lightest CI integration possible.
### 1.1 Quick Start: Auto PR Summary
Every PR gets an auto-generated summary as a comment:
```yaml
name: Claude PR Summary
on:
pull_request:
types: [opened, synchronize]
jobs:
summarize:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate PR Summary
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git diff origin/${{ github.base_ref }}...HEAD | \
npx @anthropic-ai/claude-code -p \
"Summarize this PR in 3 bullet points:
- What changed
- Why it changed
- Risk level (low/medium/high)"
- uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const summary = fs.readFileSync('summary.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🤖 Claude Code PR Summary\n\n${summary}`
});
```
**Result**: Every PR opens with a structured summary. Reviewers see what changed before reading the diff.
### 1.2 Auto Code Review Pipeline
The real time-saver: let Claude Code catch all formatting and convention issues first, so humans only review business logic:
```yaml
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Claude Auto Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git diff origin/${{ github.base_ref }}...HEAD | \
npx @anthropic-ai/claude-code review - \
--context CLAUDE.md --output review.md
- name: Post Review Comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('review.md', 'utf8');
if (review.includes('⚠️') || review.includes('CRITICAL')) {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🔍 Claude Code Review\n\n${review}\n\n---\n*Fix these before requesting human review*`
});
} else {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## ✅ Claude Code Review Passed\n\n${review}`
});
}
```
### 1.3 Write Solid Review Rules in CLAUDE.md
Review quality depends on your CLAUDE.md rules. Here's a universal checklist:
```markdown
## Auto Review Rules
### Blockers
- Hardcoded API keys, passwords, tokens
- SQL injection risk (non-parameterized queries)
- Overly permissive file permissions (chmod 777)
- Unhandled exceptions (bare except, no except)
### Warnings
- Missing type annotations
- Unexplained magic numbers
- Functions over 50 lines
- Messy import ordering
- Missing logging or error handling
### Suggestions
- Consider caching
- Use enums instead of string constants
- Improve test coverage
```
**Key**: The more specific your rules, the better Claude's reviews. "Bad code style" is too vague. "Functions under 50 lines" is actionable.
## 2. Auto-Generate Tests
### 2.1 PR Auto-Test Generation
Claude Code's test-writing ability is wildly underrated. Auto-generate tests for changed files:
```yaml
- name: Generate Tests
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
CHANGED_FILES=$(git diff --name-only origin/main...HEAD)
for file in $CHANGED_FILES; do
if [[ $file == *.py ]] || [[ $file == *.ts ]] || [[ $file == *.js ]]; then
echo "Generating tests for $file..."
cat $file | npx @anthropic-ai/claude-code -p \
"Write pytest unit tests for this module. Output only test code."
fi
done
```
**⚠️ Note**: Human-review generated tests before merging. Claude may miss edge cases.
### 2.2 Coverage Gate
```yaml
- name: Coverage Check
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
pytest --cov=./ --cov-report=xml
cat coverage.xml | npx @anthropic-ai/claude-code -p \
"Review this coverage report. Top 3 lowest-coverage files and what to test."
```
## 3. Auto-Complete PR Descriptions
The #1 developer annoyance: writing PR descriptions. Let Claude do it:
```yaml
- name: Auto PR Description
if: github.event.action == 'opened'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
COMMIT_MSGS=$(git log --oneline origin/main...HEAD)
FILES=$(git diff --name-only origin/main...HEAD)
echo "$COMMIT_MSGS" | npx @anthropic-ai/claude-code -p \
"Write a PR description.
Format:
## What
## Why
## Testing" > PR_DESCRIPTION.md
gh pr edit ${{ github.event.number }} --body "$(cat PR_DESCRIPTION.md)"
```
## 4. Full Pipeline: One CI Workflow
Combine everything into one complete workflow:
```yaml
name: Claude CI Pipeline
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Code Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git diff origin/main...HEAD | \
npx @anthropic-ai/claude-code review \
--context CLAUDE.md --output review.md
- uses: actions/upload-artifact@v4
with: { name: review, path: review.md }
generate-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Generate Tests
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
# Test generation logic
run-tests:
needs: generate-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Tests
run: npm test || pytest
summarize:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Generate Summary
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
# Summary generation logic
```
## 5. Tips & Pitfalls
### 5.1 API Key Security
- Never hardcode ANTHROPIC_API_KEY in YAML
- Add it in GitHub Settings → Secrets → Actions
- Use `${{ secrets.ANTHROPIC_API_KEY }}`
### 5.2 Cost
| Operation | Tokens/PR | Cost for 100 PRs/mo |
|:----------|:----------|:--------------------|
| PR Summary | ~500 | ~$0.01 |
| Code Review | ~2000 | ~$0.04 |
| Test Gen | ~3000 | ~$0.06 |
| **Total/PR** | ~5500 | **~$0.11/PR** |
With Claude Haiku, costs are even lower. 100 PRs for ~$11 — cheaper than 30 minutes of a mid-level engineer.
### 5.3 Gotchas
- **Don't auto-merge** — AI catches formatting, not business logic
- **Maintain CLAUDE.md** — update review rules as conventions evolve
- **Cold start** — npx downloads Claude Code CLI on first run. Pre-warm with `npx @anthropic-ai/claude-code --version`
- **Use timeout-minutes** — large diffs can be slow. Set `timeout-minutes: 10`
### 5.4 Cache Optimization
```yaml
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- name: Pre-warm Claude
run: npx @anthropic-ai/claude-code --version
```
---
*More from the Claude Code series:*
- [Hands-on: Build a Web App in 10 Minutes](/post/claude-code-todo-project-2026)
- [Advanced: CLAUDE.md & MCP Config](/post/claude-code-advanced-2026)
- [Pitfalls: 10 Mistakes Beginners Make](/post/claude-code-pitfalls-2026)
- [2026 AI Coding Tools Guide](/post/ai-coding-tools-guide-2026)
- [Team Collaboration Guide](/post/claude-code-team-collaboration-2026)
- [Can Claude Code Be Used in Hong Kong?](/post/claude-code-xianggang-2026)
💬 Comments (0)