Project 24: Headless Pipeline - CI/CD Integration
Project 24: Headless Pipeline - CI/CD Integration
Build a CI/CD pipeline using Claude Code headless mode: automated code review on PRs, commit message validation, changelog generation, and documentation updates. Runs in GitHub Actions.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Intermediate |
| Time Estimate | 1 week |
| Language | Bash + YAML (Alternatives: Python, TypeScript) |
| Prerequisites | Basic Claude Code usage, CI/CD understanding |
| Key Topics | Headless mode, -p flag, GitHub Actions, JSON output, automation |
| Main Book | โContinuous Deliveryโ by Jez Humble & David Farley |
1. Learning Objectives
By completing this project, you will:
- Master Claude Code headless mode: Use the
-pflag for non-interactive automation in pipelines - Integrate AI into CI/CD workflows: Embed Claude into GitHub Actions for automated code review
- Parse structured output: Handle
--output-format jsonfor programmatic result processing - Control costs in automation: Use
--max-turnsand model selection for budget management - Build production-ready workflows: Create robust error handling and graceful degradation
- Understand secrets management: Securely handle API keys in CI environments
- Design effective prompts for automation: Craft prompts that produce consistent, actionable output
2. Real World Outcome
When complete, youโll have a working GitHub Actions workflow that automatically reviews pull requests:
# .github/workflows/claude-review.yml
name: Claude Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Run Code Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
# Get changed files
CHANGED_FILES=$(git diff --name-only origin/main...HEAD)
# Run Claude review
claude -p "Review these changes for bugs and improvements: $CHANGED_FILES" \
--output-format json \
--max-turns 5 \
> review.json
- name: Post Review Comment
uses: actions/github-script@v7
with:
script: |
const review = require('./review.json');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: review.result
});
Example Output on a Pull Request
## Claude Code Review
### Summary
This PR adds user authentication with JWT tokens. Overall the implementation looks solid, but I've identified a few areas for improvement.
### Issues Found
**Security Concerns:**
- Line 45 in `auth/login.ts`: Password comparison using `==` instead of timing-safe comparison
- Line 78 in `auth/login.ts`: JWT secret appears to be hardcoded
**Code Quality:**
- Line 23 in `api/users.ts`: Missing null check before accessing user.email
- Line 56 in `utils/validate.ts`: Regex can be simplified
### Recommendations
1. Use `crypto.timingSafeEqual()` for password comparison
2. Move JWT secret to environment variables
3. Add input validation for email format
3. The Core Question Youโre Answering
โHow do I integrate Claude Code into automated CI/CD pipelines for code review, documentation, and quality checks?โ
Headless mode transforms Claude from an interactive assistant into an automation component. This project teaches you to use Claude in build pipelines, PR checks, and automated workflows - without requiring human interaction during execution.
Why This Matters
Traditional code review is a bottleneck in software development:
- Human reviewers have limited bandwidth
- Review quality varies by time of day and workload
- Junior developers may miss subtle issues
AI-assisted review provides:
- Consistent, tireless review coverage
- Immediate feedback on every PR
- Pattern detection across the entire codebase
- Educational explanations for flagged issues
4. Concepts You Must Understand First
Stop and research these before coding:
4.1 Headless Mode Flags
Understanding Claude Codeโs non-interactive mode is essential:
# Basic headless execution
claude -p "Your prompt here"
# With JSON output for parsing
claude -p "Review this code" --output-format json
# Limit turns to control costs
claude -p "Quick review" --max-turns 3
# Use a cheaper model for automated tasks
claude -p "Review" --model haiku
Key Questions:
- What does
-pdo differently from interactive mode? - What output formats are available (
text,json,stream-json)? - How do you limit turns and control costs?
- Whatโs in the JSON output object?
Reference: Claude Code documentation - โHeadless Modeโ
4.2 GitHub Actions Fundamentals
# Workflow syntax essentials
name: Workflow Name # Display name
on: [push, pull_request] # Trigger events
jobs:
job-name:
runs-on: ubuntu-latest # Runner environment
steps:
- uses: actions/checkout@v4 # Pre-built action
- name: Custom Step
run: echo "Hello" # Shell command
env:
SECRET: ${{ secrets.MY_SECRET }} # Secret access
Key Questions:
- What events can trigger workflows?
- How do you pass data between steps?
- How are secrets stored and accessed?
- What permissions does the workflow need?
Reference: GitHub Actions documentation
4.3 Structured Output Parsing
// Example claude --output-format json response
{
"session_id": "abc123",
"result": "The code review findings...",
"cost": {
"input_tokens": 1250,
"output_tokens": 450,
"total_cost": 0.0032
},
"duration_ms": 4500,
"num_turns": 2
}
Key Questions:
- How do you extract the
resultfield reliably? - What happens if the JSON is malformed?
- How do you handle empty or error responses?
Reference: Claude Code documentation - โโoutput-formatโ
5. Questions to Guide Your Design
Before implementing, think through these architectural decisions:
5.1 What to Automate?
| Task | Trigger | Complexity | Value |
|---|---|---|---|
| Code review on PRs | pull_request |
Medium | High |
| Commit message validation | push |
Low | Medium |
| Changelog generation | release |
Medium | High |
| Documentation updates | File changes | High | Medium |
| Security scanning | pull_request |
Medium | Very High |
5.2 Error Handling Strategy
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ERROR HANDLING TREE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Claude invocation fails โ
โ โ โ
โ โโโ API key invalid โโโบ Fail workflow immediately โ
โ โ โ
โ โโโ Rate limited โโโบ Retry with exponential backoff โ
โ โ โ
โ โโโ Timeout โโโบ Retry once, then post warning โ
โ โ โ
โ โโโ Malformed output โโโบ Post "review unavailable" โ
โ โ
โ Claude returns output โ
โ โ โ
โ โโโ Valid JSON โโโบ Parse and post comment โ
โ โ โ
โ โโโ Invalid JSON โโโบ Log error, post raw text โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
5.3 Cost Control
Budget considerations for automated pipelines:
# Cost-conscious configuration
- name: Claude Review
run: |
claude -p "$PROMPT" \
--model haiku \ # Cheaper model for routine reviews
--max-turns 3 \ # Limit iterations
--output-format json
timeout-minutes: 5 # Hard timeout
Questions to answer:
- Whatโs your monthly budget for AI reviews?
- Which PRs need full Opus review vs. Haiku?
- Should you limit reviews to certain file types?
6. Thinking Exercise
Design the Complete Pipeline
Before writing code, sketch out your pipeline:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CI/CD PIPELINE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ PR Created/Updated โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 1. CHECKOUT โ Get PR code with full history โ
โ โ fetch-depth: 0 โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 2. GET DIFF โ git diff origin/main...HEAD โ
โ โ Find changed โ Filter by file type โ
โ โ files โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 3. INSTALL โ npm install -g @anthropic-ai/claude-code โ
โ โ CLAUDE โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 4. CLAUDE โ claude -p "Review these changes" โ
โ โ REVIEW โ --output-format json โ
โ โ โ --max-turns 5 โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 5. PARSE โ Extract review from JSON โ
โ โ OUTPUT โ Handle errors gracefully โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 6. POST โ github.rest.issues.createComment โ
โ โ COMMENT โ Format as markdown โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Design Questions
- What happens if the diff is too large?
- Claude has context limits
- Consider summarizing or chunking large diffs
- Maybe review only the most critical files
- Should you run different models for different tasks?
- Haiku for routine reviews
- Opus for security-critical changes
- Sonnet as a good middle ground
- How do you handle rate limits?
- Exponential backoff
- Queue PRs during high traffic
- Consider a review queue service
7. The Interview Questions Theyโll Ask
Prepare for these common questions:
7.1 โHow would you integrate an AI assistant into a CI/CD pipeline?โ
Good answer structure:
- Identify the automation target (code review, docs, etc.)
- Choose headless mode with appropriate flags
- Parse structured output for downstream processing
- Handle errors gracefully (donโt block PRs on AI failures)
- Control costs with model selection and turn limits
7.2 โWhatโs headless mode and why is it important for automation?โ
Key points:
- Headless mode (
-pflag) runs Claude without interactive input - Essential for CI/CD where no human is present
- Returns immediately with output (or streams it)
- Can output in structured formats (JSON) for parsing
7.3 โHow do you handle costs in automated AI workflows?โ
Strategies:
- Use cheaper models (Haiku) for routine tasks
- Limit turns with
--max-turns - Filter which PRs get AI review
- Monitor usage and set budget alerts
- Cache repeated analyses
7.4 โWhat are the security considerations for AI in CI/CD?โ
Considerations:
- Never expose API keys in logs
- Use GitHub secrets for credentials
- Be careful about what context you send to the API
- Consider data sensitivity (donโt review files with secrets)
- Rate limit to prevent abuse
7.5 โHow do you handle failures in AI-powered automation?โ
Best practices:
- Never block PRs on AI failures (graceful degradation)
- Retry with exponential backoff for transient errors
- Post informative comments when review unavailable
- Log failures for monitoring
- Have fallback to human review
8. Hints in Layers
Use these hints progressively if you get stuck:
Hint 1: Start with a Simple Review
Donโt try to build everything at once. Start with the simplest possible workflow:
- name: Simple Review
run: |
echo "Changed files: $(git diff --name-only origin/main...HEAD)"
claude -p "Review this code for bugs" --output-format text
Hint 2: Add JSON Output
Once basic review works, switch to JSON for parsing:
- name: Structured Review
run: |
claude -p "Review these changes" \
--output-format json \
> review.json
# Debug: see what we got
cat review.json | jq .
Hint 3: Limit Costs
Add cost controls before you accidentally spend too much:
- name: Cost-Controlled Review
run: |
claude -p "Review" \
--output-format json \
--max-turns 3 \
--model haiku \
> review.json
Hint 4: Handle Errors
Make the workflow robust:
- name: Robust Review
run: |
if ! claude -p "Review" --output-format json > review.json 2>&1; then
echo '{"result": "Review unavailable - Claude error"}' > review.json
fi
# Validate JSON
if ! jq -e . review.json > /dev/null 2>&1; then
echo '{"result": "Review unavailable - invalid output"}' > review.json
fi
9. Books That Will Help
| Topic | Book | Chapter/Section |
|---|---|---|
| CI/CD patterns | โContinuous Deliveryโ by Humble & Farley | Ch. 5: Anatomy of the Deployment Pipeline |
| CI/CD patterns | โContinuous Deliveryโ by Humble & Farley | Ch. 6: Build and Deployment Scripting |
| CI/CD patterns | โContinuous Deliveryโ by Humble & Farley | Ch. 7: The Commit Stage |
| Automation | โThe Phoenix Projectโ by Kim, Behr, Spafford | Ch. 10-15: Build automation |
| DevOps | โAccelerateโ by Forsgren, Humble, Kim | All: Metrics-driven improvement |
| GitHub Actions | GitHub Actions Documentation | Workflow syntax and examples |
10. Implementation Guide
10.1 Complete Workflow Example
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for diff
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Get Changed Files
id: changed
run: |
FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | tr '\n' ' ')
echo "files=$FILES" >> $GITHUB_OUTPUT
echo "Changed files: $FILES"
- name: Check if Files to Review
id: check
run: |
if [ -z "${{ steps.changed.outputs.files }}" ]; then
echo "skip=true" >> $GITHUB_OUTPUT
else
echo "skip=false" >> $GITHUB_OUTPUT
fi
- name: Claude Review
if: steps.check.outputs.skip != 'true'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "
Review these changed files for:
1. Bugs or potential issues
2. Code quality improvements
3. Security concerns
4. Performance issues
Files: ${{ steps.changed.outputs.files }}
Format your response as markdown with clear sections.
Be concise and actionable.
" --output-format json --max-turns 3 --model haiku > review.json
- name: Post Comment
if: steps.check.outputs.skip != 'true'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
let body;
try {
const review = JSON.parse(fs.readFileSync('review.json', 'utf8'));
body = `## Claude Code Review\n\n${review.result || 'No issues found.'}`;
} catch (e) {
body = '## Claude Code Review\n\n_Review unavailable - please check workflow logs._';
}
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body
});
- name: Skip Notice
if: steps.check.outputs.skip == 'true'
run: echo "No files to review"
10.2 Extended Features
Once the basic review works, consider adding:
Commit Message Validation:
- name: Validate Commit Messages
run: |
COMMITS=$(git log origin/${{ github.base_ref }}..HEAD --format="%s")
claude -p "Check if these commit messages follow conventional commits: $COMMITS" \
--output-format json > commit-check.json
Changelog Generation:
- name: Generate Changelog Entry
run: |
DIFF=$(git diff origin/${{ github.base_ref }}...HEAD)
claude -p "Generate a changelog entry for these changes: $DIFF" \
--output-format json > changelog.json
Security Scanning:
- name: Security Scan
run: |
claude -p "Scan these files for security vulnerabilities: $FILES" \
--output-format json \
--model opus \ # Use Opus for security
> security.json
11. Learning Milestones
Track your progress:
| Milestone | Description | Verification |
|---|---|---|
| 1 | Workflow runs on PR | See workflow in Actions tab |
| 2 | Claude executes successfully | Check step logs for output |
| 3 | JSON output is valid | jq .result review.json works |
| 4 | Comment appears on PR | See comment on test PR |
| 5 | Costs are controlled | Check Anthropic dashboard |
| 6 | Error handling works | Force a failure and verify graceful handling |
12. Common Pitfalls
12.1 Missing Permissions
# WRONG: No permissions specified
jobs:
review:
runs-on: ubuntu-latest
# Claude runs but can't post comments!
# RIGHT: Explicit permissions
jobs:
review:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
12.2 Shallow Clone
# WRONG: Shallow clone can't compute diff
- uses: actions/checkout@v4
# Default fetch-depth: 1
# RIGHT: Full history for diff
- uses: actions/checkout@v4
with:
fetch-depth: 0
12.3 Exposing Secrets in Logs
# WRONG: Secret might appear in error messages
- run: |
echo "Using key: $ANTHROPIC_API_KEY" # NEVER DO THIS
claude -p "Review"
# RIGHT: Let the tool read from env
- run: |
claude -p "Review"
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
12.4 Not Handling Large Diffs
# Problem: diff too large for Claude context
DIFF=$(git diff origin/main...HEAD) # Could be huge
# Solution: limit to file list and let Claude read them
FILES=$(git diff --name-only origin/main...HEAD | head -20)
claude -p "Review files: $FILES" # Claude reads files itself
13. Extension Ideas
Once the basic pipeline works:
- Multi-stage review: Run Haiku first, escalate to Opus for issues
- Review caching: Skip re-review if files unchanged
- Metrics dashboard: Track issues found, false positives, cost
- Custom rules: Train Claude on your style guide
- IDE integration: Preview reviews before pushing
- Review queue: Handle high PR volume gracefully
14. Summary
This project teaches you to:
- Use Claude Code in headless mode for automation
- Integrate AI into GitHub Actions workflows
- Parse structured JSON output
- Control costs and handle errors gracefully
- Build production-ready CI/CD components
The skills transfer directly to any CI/CD platform (GitLab, Azure DevOps, Jenkins) and any automation task where you need AI analysis without human interaction.
Key takeaway: Headless mode (-p flag) transforms Claude from an interactive tool into an automation component. Combined with structured output (--output-format json), you can build sophisticated AI-powered pipelines that integrate seamlessly with existing DevOps workflows.