CI/CD Integration
Integrate Claude Code into your CI/CD pipelines for automated code review, testing, quality gates, and release automation.
Quick Reference
| Integration |
Tool |
Use Case |
| GitHub Actions |
claude -p |
Automated PR review, test fixing |
| Pre-commit |
hooks |
Local validation before push |
| Quality Gates |
Claude API |
PR approval requirements |
| Release Automation |
headless mode |
Changelog, versioning |
Core Concept
Claude Code's headless mode (-p flag) enables non-interactive execution in CI pipelines. Combined with GitHub Actions and hooks, you can automate code review, testing, and release workflows.
# Basic CI usage
claude -p "Review this PR diff for issues" --output-format json
GitHub Actions Basics
Minimal Workflow
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Run Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
gh pr diff ${{ github.event.pull_request.number }} | \
claude -p "Review this diff for bugs and improvements" \
--output-format json > review.json
Key Environment Variables
| Variable |
Purpose |
ANTHROPIC_API_KEY |
API authentication |
GITHUB_TOKEN |
GitHub API access (auto-provided) |
CI=true |
Indicates CI environment |
See GITHUB-ACTIONS.md for complete workflow examples.
Pre-commit Integration
Quick Setup
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: claude-review
name: Claude Code Review
entry: claude -p "Check this diff for obvious issues" --max-turns 1
language: system
stages: [pre-commit]
pass_filenames: false
Staged Files Review
#!/bin/bash
# .git/hooks/pre-commit
staged_files=$(git diff --cached --name-only)
if [ -n "$staged_files" ]; then
git diff --cached | claude -p "Quick review of staged changes. Report only critical issues." \
--max-turns 1 --output-format text
fi
See AUTOMATION.md for more automation patterns.
Quality Gates
PR Approval Gate
- name: Quality Gate
run: |
result=$(claude -p "Analyze PR #${{ github.event.pull_request.number }} \
for security issues, breaking changes, and test coverage. \
Output JSON: {\"approved\": boolean, \"blockers\": string[]}" \
--output-format json --json-schema '...')
if [ "$(echo $result | jq -r '.structured_output.approved')" != "true" ]; then
echo "Quality gate failed"
exit 1
fi
Test Coverage Gate
- name: Coverage Analysis
run: |
bun test --coverage > coverage.txt
claude -p "Analyze coverage report. Fail if coverage < 80% \
or critical paths uncovered." < coverage.txt
See PIPELINES.md for pipeline integration patterns.
Automated Review Workflow
Standard PR Review
name: Automated PR Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get PR Diff
run: gh pr diff ${{ github.event.pull_request.number }} > diff.txt
env:
GH_TOKEN: ${{ github.token }}
- name: Claude Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
review=$(claude -p "Review this PR diff. Focus on:
- Security vulnerabilities
- Logic errors
- Performance issues
- Missing error handling
Format as markdown with sections." < diff.txt)
gh pr comment ${{ github.event.pull_request.number }} --body "$review"
env:
GH_TOKEN: ${{ github.token }}
Test Automation
Fix Failing Tests
- name: Run Tests
id: tests
continue-on-error: true
run: bun test 2>&1 | tee test-output.txt
- name: Fix Failing Tests
if: steps.tests.outcome == 'failure'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "Fix the failing tests. Test output:
$(cat test-output.txt)
Make minimal changes to fix the tests." \
--allowedTools "Read,Edit,Bash(bun test:*)"
Generate Missing Tests
- name: Generate Tests for Changed Files
run: |
changed_files=$(git diff --name-only origin/main...HEAD -- '*.ts' '*.tsx')
for file in $changed_files; do
claude -p "Generate comprehensive tests for $file if none exist" \
--allowedTools "Read,Write,Glob"
done
Release Automation
Changelog Generation
- name: Generate Changelog
run: |
claude -p "Generate changelog from commits since last release:
$(git log $(git describe --tags --abbrev=0)..HEAD --oneline)
Format: Conventional changelog with Breaking, Features, Fixes sections." \
--output-format text > CHANGELOG_ENTRY.md
Version Bumping
- name: Determine Version Bump
run: |
bump=$(claude -p "Analyze commits since last tag. Output only: major, minor, or patch
$(git log $(git describe --tags --abbrev=0)..HEAD --oneline)" \
--output-format text)
npm version $bump --no-git-tag-version
Security Scanning
Code Security Review
- name: Security Scan
run: |
claude -p "Security audit of changes in this PR:
$(gh pr diff ${{ github.event.pull_request.number }})
Check for:
- SQL injection
- XSS vulnerabilities
- Hardcoded secrets
- Insecure dependencies
- Authentication issues
Output JSON: {\"secure\": boolean, \"issues\": [{\"severity\": string, \"description\": string, \"line\": number}]}" \
--output-format json > security.json
Best Practices
CI Performance
| Practice |
Benefit |
Use --max-turns 1-3 |
Predictable execution time |
Limit tools with --allowedTools |
Faster, safer execution |
| Cache Claude installation |
Faster workflow starts |
Use --output-format json |
Reliable parsing |
Security
| Practice |
Implementation |
| Store API keys as secrets |
${{ secrets.ANTHROPIC_API_KEY }} |
| Limit tool permissions |
--allowedTools "Read,Grep" |
Avoid --dangerously-skip-permissions |
Use explicit tool lists |
| Validate Claude output |
Parse JSON, check structure |
Cost Management
| Practice |
Benefit |
| Filter files before review |
Fewer tokens |
| Use targeted prompts |
Focused analysis |
Set --max-turns |
Bounded execution |
| Skip generated files |
Reduce noise |
Common Patterns
Conditional Review
- name: Check for High-Risk Changes
id: risk
run: |
if gh pr diff ${{ github.event.pull_request.number }} | grep -q "security\|auth\|password"; then
echo "high_risk=true" >> $GITHUB_OUTPUT
fi
- name: Deep Security Review
if: steps.risk.outputs.high_risk == 'true'
run: claude -p "Deep security review..." --max-turns 5
Multi-Stage Review
jobs:
quick-check:
runs-on: ubuntu-latest
steps:
- name: Fast Lint Check
run: claude -p "Quick lint check" --max-turns 1
deep-review:
needs: quick-check
runs-on: ubuntu-latest
steps:
- name: Comprehensive Review
run: claude -p "Full code review" --max-turns 5
Troubleshooting
| Issue |
Solution |
| API key not found |
Check secrets.ANTHROPIC_API_KEY is set |
| Timeout in CI |
Add --max-turns limit |
| Permission denied |
Use --allowedTools instead of skip-permissions |
| JSON parse error |
Use jq to validate output |
| PR comment fails |
Check permissions: pull-requests: write |
Reference Files