Dashboard/Phase 5: Advanced Patterns
🔬 Lab20 min25 XP

Lesson 42: Lab — CI Pipeline with Claude Code

Day 42 of 50 · ~20 min hands-on · Phase 5: Advanced Patterns


The Mission

Build a working GitHub Actions CI/CD pipeline that uses Claude Code to:

  1. Automatically review pull requests when they're created
  2. Analyze code quality (security, style, efficiency)
  3. Leave comments with suggestions
  4. Optionally auto-fix simple issues (formatting, linting)

All hands-off. No human in the loop. Claude Code runs on your CI infrastructure and does the work.


What You'll Practice

  • Headless mode (Lesson 36): Claude Code running without interactive prompts
  • Permissions (Lesson 17): Setting what Claude can and cannot do
  • Git workflows (Lesson 13): Creating commits and PRs
  • Hooks (Lesson 27): Triggering Claude Code on events
  • Security (Lesson 39): Reviewing what headless Claude is allowed to do

Setup

Prerequisites

  • A GitHub repository (public or private)
  • GitHub Actions enabled
  • Claude Code installed locally
  • A working .env with ANTHROPIC_API_KEY

Files You'll Create

  1. .github/workflows/claude-review.yml — GitHub Actions workflow
  2. .claude-code/review-config.md — Claude Code configuration
  3. scripts/claude-review.sh — Helper script

Step 1: Configure Claude Code Permissions

Create .claude-code/review-config.md:

# Claude Code PR Review Configuration

## What Claude Can Read
- All `.js`, `.ts`, `.py`, `.go` files in `src/` and `tests/`
- `package.json`, `pyproject.toml`, `go.mod` (dependencies)
- `README.md` (context)
- NOT: `.env`, secrets, credentials, private keys

## What Claude Can Edit
- Nothing in production code initially (review-only mode)
- Can create comments on GitHub PRs
- Can log findings to review-report.md

## What Claude Can Execute
- `git` commands (read-only: diff, log, show)
- Analysis tools: `npm test`, `python -m pytest` (read-only)
- NOT: `npm publish`, `git push`, any destructive commands

## Review Criteria
1. Security issues (eval, SQL injection, unsafe parsing)
2. Performance problems (N+1 queries, memory leaks)
3. Code style (consistency with project standards)
4. Test coverage (are critical functions tested?)
5. Documentation (docstrings, comments where needed)

## Output Format
Create a GitHub comment with:
- Summary: [N] findings across [M] files
- Issues: [list by severity]
- Suggestions: [actionable fixes]

Save this in your repo. Claude Code will read it before analyzing PRs.


Step 2: Create the GitHub Actions Workflow

Create .github/workflows/claude-review.yml:

name: Claude Code PR Review

on:
  pull_request:
    types: [opened, synchronize]
    paths:
      - 'src/**'
      - 'tests/**'
      - '*.json'
      - '*.ts'
      - '*.js'

jobs:
  review:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for context

      - name: Set up Claude Code
        uses: anthropics/claude-code-action@v2
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}

      - name: Run PR Review
        run: |
          # Get the PR diff
          DIFF=$(git diff origin/main...HEAD)
          
          # Run Claude Code in headless mode
          claude --headless \
            --task "review-pr" \
            --context "$(cat .claude-code/review-config.md)" \
            --input "$DIFF" \
            --output ./review-report.txt

      - name: Comment on PR
        uses: actions/github-script@v7
        if: always()
        with:
          script: |
            const fs = require('fs');
            const reviewReport = fs.readFileSync('./review-report.txt', 'utf8');
            
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '## Claude Code Review\n\n' + reviewReport
            });

      - name: Fail if critical issues
        run: |
          if grep -q "CRITICAL" ./review-report.txt; then
            echo "Critical issues found. Please fix before merging."
            exit 1
          fi

This workflow:

  1. Triggers on every PR to src/ or test files
  2. Runs Claude Code in headless mode
  3. Posts a comment with findings
  4. Fails the check if critical issues are found

Step 3: Create a Helper Script

Create scripts/claude-review.sh:

#!/bin/bash
# Helper script to run Claude Code review locally (for testing)

set -e

# Get the current branch
BRANCH=$(git rev-parse --abbrev-ref HEAD)
MAIN_BRANCH=${1:-main}

if [ "$BRANCH" = "$MAIN_BRANCH" ]; then
  echo "Error: Run this on a feature branch, not main"
  exit 1
fi

# Get the diff
DIFF=$(git diff "$MAIN_BRANCH"...HEAD)

# Run Claude Code review
echo "Running Claude Code PR review..."
claude --headless \
  --task "review-pr" \
  --context "$(cat .claude-code/review-config.md)" \
  --input "$DIFF" \
  --print > /tmp/review-preview.txt

echo "Review preview (no changes made):"
cat /tmp/review-preview.txt

echo ""
echo "To run the review (will post to GitHub):"
echo "  git push origin $BRANCH"
echo "  # GitHub Actions will run the review and comment on the PR"

Make it executable: chmod +x scripts/claude-review.sh


Step 4: Set Up the GitHub Secret

  1. Generate a new ANTHROPIC_API_KEY at https://console.anthropic.com
  2. Go to your GitHub repo → Settings → Secrets and variables → Actions
  3. Create new secret: ANTHROPIC_API_KEY with your API key

Step 5: Test the Workflow

Local Test:

# Create a feature branch
git checkout -b feature/test-review

# Make a change (intentionally bad code)
cat > src/test.js << 'EOF'
// Bad practice: using eval
const userCode = req.body.code;
eval(userCode);  // SECURITY ISSUE

// Bad practice: no error handling
const data = JSON.parse(input);
EOF

git add src/test.js
git commit -m "Test: intentionally bad code"

# Run the local review script
./scripts/claude-review.sh

# You should see Claude identify:
# - SECURITY: eval() is dangerous
# - ERROR HANDLING: no try/catch
# - SUGGESTION: validate input first

Real Test:

# Push your feature branch
git push origin feature/test-review

# Create a PR on GitHub
# GitHub Actions will run automatically
# Claude Code will review and comment on the PR

Reflect

After running the workflow, think about these questions:

  1. Did Claude Code find real issues? Were the suggestions helpful or false positives?

  2. How long did it take? Was it faster than manual review? How does it scale to larger PRs?

  3. What permissions matter most? Which restrictions protect you vs. slow you down?

  4. Would you trust this in production? What additional safeguards would you add?

  5. What's missing? What else should Claude Code check for in your codebase?


Bonus Challenge

Once you have the basic workflow working:

Challenge 1: Auto-Fix Simple Issues

Extend Claude Code to automatically fix formatting and linting errors:

claude --headless \
  --task "review-and-fix-simple-issues" \
  --context "Fix only: formatting, unused imports, variable naming"

Then create a new commit:

git add -A
git commit -m "refactor: auto-format with Claude Code"
git push

Challenge 2: Performance Analysis

Add a performance analysis step:

claude --headless \
  --task "analyze-performance" \
  --context "Look for: N+1 queries, memory leaks, inefficient loops"

Challenge 3: Custom Rules

Create a .claude-code/custom-rules.md with your team's specific rules:

# Custom Linting Rules for [Project]

## Required patterns:
- All API endpoints must have error handling
- All async functions must have try/catch
- Database queries must use prepared statements

## Forbidden patterns:
- eval() or Function() constructor
- global variables outside of singletons
- console.log in production code

Then have Claude Code check against these rules automatically.

Challenge 4: Multi-Language Support

Extend the workflow to handle Python, Go, or other languages:

paths:
  - 'src/**/*.py'  # Python files
  - 'src/**/*.go'  # Go files

Claude Code should automatically detect the language and use appropriate analysis.


Key Takeaways

  • Headless mode lets you integrate Claude Code into CI/CD pipelines
  • Permissions are critical — specify exactly what Claude can do
  • GitHub Actions is a natural home for automated code review
  • Preview mode (--print) is your safety net before running headless
  • Iterative improvement — start simple, add features gradually

← Back to Curriculum · Lesson 43 →