Claude Code CI/CD Integration: GitHub Actions Auto Review & Test Generation

📘 AI Tutorials 💬 🔥 Trending

🩺 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)