Claude Code GitHub Actions: AI-Powered CI/CD Automation
By Learnia Team
Claude Code GitHub Actions: AI-Powered CI/CD Automation
This article is written in English. Our training modules are available in French.
GitHub Actions brings Claude Code into your CI/CD pipeline. Automate code reviews, generate PR descriptions, triage issues, and even implement features—all triggered by GitHub events. This is AI-powered development at scale.
What Can Claude Code Do in CI/CD?
| Use Case | Trigger | Action |
|---|---|---|
| Code Review | Pull Request | Review changes, suggest improvements |
| PR Description | Pull Request | Generate detailed PR descriptions |
| Issue Triage | Issue Created | Categorize, prioritize, assign |
| Bug Fixing | Issue Labeled | Analyze and create fix PR |
| Documentation | Code Changed | Update docs automatically |
| Test Generation | Code Changed | Create tests for new code |
| Security Scan | Pull Request | Check for vulnerabilities |
| Dependency Updates | Schedule | Review and update dependencies |
Getting Started
Prerequisites
- →GitHub repository
- →Anthropic API key
- →GitHub App installed (optional, for enhanced features)
Install GitHub App
The easiest setup uses the Claude GitHub App:
> /install-github-app
Opening GitHub to install Claude Code App...
1. Select repositories to grant access
2. Confirm permissions
3. Copy the installation token
Installation complete. Your workflows can now use Claude Code.
Manual Setup
For API key-based access:
- →
Add your Anthropic API key to repository secrets:
- →Go to Settings → Secrets → Actions
- →Add
ANTHROPIC_API_KEY
- →
Create workflow file in
.github/workflows/
Basic Workflow Structure
# .github/workflows/claude-code.yml
name: Claude Code
on:
pull_request:
types: [opened, synchronize]
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 Claude Code
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude --print --dangerously-skip-permissions \
-p "Review the changes in this PR and comment on issues"
Code Review Workflow
Automated code review on every pull request:
# .github/workflows/code-review.yml
name: AI Code Review
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
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: Get changed files
id: changed
run: |
echo "files=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | tr '\n' ' ')" >> $GITHUB_OUTPUT
- name: Review code
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude --print --dangerously-skip-permissions \
-p "Review these changed files for:
- Code quality issues
- Potential bugs
- Security vulnerabilities
- Performance concerns
- Style guide compliance
Files: ${{ steps.changed.outputs.files }}
Format your review as markdown with sections for each category.
Include line numbers for specific issues." > review.md
- name: Post review comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('review.md', 'utf8');
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `## 🤖 AI Code Review\n\n${review}`
});
Enhanced Review with Inline Comments
- name: Review with inline comments
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
claude --print --dangerously-skip-permissions \
-p "Review this PR and for each issue found, output JSON:
{\"file\": \"path/to/file\", \"line\": 42, \"comment\": \"Issue description\"}
One JSON object per line." > issues.jsonl
# Post inline comments
while IFS= read -r line; do
file=$(echo "$line" | jq -r '.file')
line_num=$(echo "$line" | jq -r '.line')
comment=$(echo "$line" | jq -r '.comment')
gh pr comment ${{ github.event.pull_request.number }} \
--body "**Line $line_num in $file**: $comment"
done < issues.jsonl
PR Description Generator
Auto-generate detailed PR descriptions:
# .github/workflows/pr-description.yml
name: Generate PR Description
on:
pull_request:
types: [opened]
permissions:
pull-requests: write
jobs:
describe:
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: Generate description
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git diff origin/${{ github.base_ref }}...HEAD > changes.diff
claude --print --dangerously-skip-permissions \
-p "Based on this diff, generate a detailed PR description:
$(cat changes.diff)
Include:
## Summary
Brief overview of changes
## Changes Made
- Bullet points of specific changes
## Testing
How to test these changes
## Screenshots
(if UI changes, note what screenshots would be helpful)
## Related Issues
Mention any issue numbers if apparent from code" > description.md
- name: Update PR description
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const description = fs.readFileSync('description.md', 'utf8');
github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
body: description
});
Issue Triage Bot
Automatically categorize and assign issues:
# .github/workflows/issue-triage.yml
name: Issue Triage
on:
issues:
types: [opened]
permissions:
issues: write
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Analyze issue
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude --print --dangerously-skip-permissions \
-p "Analyze this GitHub issue and provide triage:
Title: ${{ github.event.issue.title }}
Body: ${{ github.event.issue.body }}
Return JSON only:
{
\"labels\": [\"bug\"|\"feature\"|\"documentation\"|\"question\"],
\"priority\": \"low\"|\"medium\"|\"high\"|\"critical\",
\"component\": \"frontend\"|\"backend\"|\"api\"|\"infra\"|\"other\",
\"summary\": \"One line summary\",
\"suggested_assignee\": \"team-area or null\"
}" > triage.json
- name: Apply triage
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const triage = JSON.parse(fs.readFileSync('triage.json', 'utf8'));
// Add labels
const labels = [...triage.labels, `priority:${triage.priority}`];
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: labels
});
// Add triage comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `🤖 **Automated Triage**\n\n` +
`**Summary:** ${triage.summary}\n` +
`**Component:** ${triage.component}\n` +
`**Priority:** ${triage.priority}`
});
Automated Bug Fixing
Create fix PRs for labeled issues:
# .github/workflows/auto-fix.yml
name: Auto Fix Bug
on:
issues:
types: [labeled]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
fix:
if: github.event.label.name == 'auto-fix'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Create fix branch
run: |
git checkout -b fix/issue-${{ github.event.issue.number }}
- name: Analyze and fix
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude --dangerously-skip-permissions \
-p "Fix this issue:
Title: ${{ github.event.issue.title }}
Description: ${{ github.event.issue.body }}
1. Find the relevant code
2. Implement the fix
3. Add or update tests
4. Ensure code passes linting
Make the minimal changes needed to fix the issue."
- name: Commit and push
run: |
git config user.name "Claude Code Bot"
git config user.email "claude@example.com"
git add -A
git commit -m "Fix: ${{ github.event.issue.title }}" || exit 0
git push origin fix/issue-${{ github.event.issue.number }}
- name: Create pull request
uses: actions/github-script@v7
with:
script: |
const pr = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Fix: ${{ github.event.issue.title }}`,
body: `Automated fix for #${{ github.event.issue.number }}\n\nGenerated by Claude Code`,
head: `fix/issue-${{ github.event.issue.number }}`,
base: 'main'
});
// Link PR to issue
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `🤖 Created fix PR: #${pr.data.number}`
});
Test Generation
Generate tests for new code:
# .github/workflows/generate-tests.yml
name: Generate Tests
on:
pull_request:
types: [opened, synchronize]
paths:
- 'src/**/*.ts'
- 'src/**/*.js'
permissions:
contents: write
pull-requests: write
jobs:
generate-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Install dependencies
run: npm install
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Get changed source files
id: changed
run: |
files=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -E 'src/.*\.(ts|js)$' | grep -v '\.test\.' | tr '\n' ' ')
echo "files=$files" >> $GITHUB_OUTPUT
- name: Generate tests
if: steps.changed.outputs.files != ''
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude --dangerously-skip-permissions \
-p "Generate comprehensive tests for these changed files:
${{ steps.changed.outputs.files }}
For each file:
1. Create a corresponding .test.ts file if it doesn't exist
2. Add tests for new functions/methods
3. Include edge cases and error scenarios
4. Follow existing test patterns in the codebase
Run 'npm test' to verify tests pass."
- name: Commit test files
run: |
git config user.name "Claude Code Bot"
git config user.email "claude@example.com"
git add -A '*.test.*'
git commit -m "Add generated tests" || exit 0
git push
Documentation Updates
Keep docs in sync with code:
# .github/workflows/update-docs.yml
name: Update Documentation
on:
push:
branches: [main]
paths:
- 'src/api/**'
permissions:
contents: write
jobs:
update-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Update API docs
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude --dangerously-skip-permissions \
-p "Update the API documentation in docs/API.md:
1. Scan all files in src/api/
2. Extract endpoint definitions
3. Document request/response formats
4. Include example usage
5. Note any breaking changes
Keep the existing documentation structure."
- name: Commit doc updates
run: |
git config user.name "Claude Code Bot"
git config user.email "claude@example.com"
git add docs/
git commit -m "Update API documentation" || exit 0
git push
Security Scanning
AI-powered security review:
# .github/workflows/security-scan.yml
name: Security Scan
on:
pull_request:
types: [opened, synchronize]
permissions:
pull-requests: write
security-events: write
jobs:
security:
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: Security analysis
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git diff origin/${{ github.base_ref }}...HEAD > changes.diff
claude --print --dangerously-skip-permissions \
-p "Perform a security review of these changes:
$(cat changes.diff)
Check for:
1. SQL injection vulnerabilities
2. XSS vulnerabilities
3. Exposed secrets or credentials
4. Insecure dependencies
5. Authentication/authorization issues
6. Data validation problems
7. CSRF vulnerabilities
8. Path traversal risks
Format as:
## Security Review
### Critical Issues
(blocking issues)
### Warnings
(should fix)
### Notes
(informational)
### Verdict
PASS / FAIL" > security.md
- name: Post security review
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('security.md', 'utf8');
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `## 🔒 Security Review\n\n${review}`
});
- name: Check for failures
run: |
if grep -q "### Verdict" security.md && grep -q "FAIL" security.md; then
echo "Security review failed"
exit 1
fi
Scheduled Tasks
Run Claude Code on a schedule:
# .github/workflows/weekly-audit.yml
name: Weekly Code Audit
on:
schedule:
- cron: '0 9 * * 1' # Monday 9 AM
workflow_dispatch:
permissions:
issues: write
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Run audit
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude --print --dangerously-skip-permissions \
-p "Perform a comprehensive code audit:
1. Check for TODO/FIXME comments that are stale
2. Identify unused exports and dead code
3. Find potential performance issues
4. Check for outdated dependencies
5. Review error handling completeness
6. Identify code duplication
Provide a summary report with actionable items." > audit.md
- name: Create audit issue
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const audit = fs.readFileSync('audit.md', 'utf8');
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Weekly Code Audit - ${new Date().toISOString().split('T')[0]}`,
body: audit,
labels: ['audit', 'automated']
});
Workflow Tips
Caching for Speed
- name: Cache Claude Code
uses: actions/cache@v4
with:
path: ~/.npm
key: claude-code-${{ runner.os }}
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
Rate Limiting
Prevent excessive API usage:
jobs:
review:
# Only run on real PRs, not drafts
if: github.event.pull_request.draft == false
# Concurrency prevents parallel runs
concurrency:
group: claude-${{ github.ref }}
cancel-in-progress: true
Environment Variables
Pass context to Claude:
- name: Run with context
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
BASE_BRANCH: ${{ github.base_ref }}
run: |
claude --print --dangerously-skip-permissions \
-p "Review this PR titled '$PR_TITLE' by $PR_AUTHOR..."
Conditional Execution
- name: Review only large PRs
if: github.event.pull_request.additions > 100
run: claude ...
- name: Skip bot PRs
if: "!contains(github.event.pull_request.user.login, 'bot')"
run: claude ...
Security Considerations
API Key Protection
# Use GitHub Secrets
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
# Never echo keys
- run: echo "Key length: ${#ANTHROPIC_API_KEY}" # OK
- run: echo "$ANTHROPIC_API_KEY" # NEVER DO THIS
Permission Scoping
# Minimal permissions
permissions:
contents: read
pull-requests: write
# Not this
permissions: write-all
Sandboxed Execution
# Claude runs with --dangerously-skip-permissions
# Ensure workflows can't escape their scope
- name: Run in isolated directory
run: |
mkdir -p /tmp/workspace
cp -r . /tmp/workspace
cd /tmp/workspace
claude --dangerously-skip-permissions ...
Review Generated Code
Always require human approval for generated changes:
# Create PR instead of direct push
- name: Create PR
run: |
gh pr create --title "AI Generated Changes" \
--body "⚠️ Review required - generated by Claude Code"
Integration with Other Features
Using MCP in Actions
- name: Setup MCP
run: |
claude mcp add github --transport http https://api.github.com/mcp/
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
See Model Context Protocol (MCP) for Claude Code: Complete Guide.
Using Custom Commands
- name: Run custom command
run: |
claude --dangerously-skip-permissions -p "/review"
See Custom Slash Commands in Claude Code: Build Your Own.
Headless SDK Usage
For complex workflows, use the SDK:
- name: Run SDK script
run: node scripts/claude-workflow.js
See Headless & Programmatic Claude Code: SDK & Automation.
Key Takeaways
- →
Automate reviews: Let AI catch issues before humans review.
- →
Generate content: PR descriptions, docs, tests—all automated.
- →
Triage at scale: Handle issues automatically.
- →
Security first: Use minimal permissions, protect API keys.
- →
Human in the loop: AI creates PRs; humans approve them.
Master AI-Powered Automation
GitHub Actions with Claude Code is just the beginning of AI automation. Learn to build complete autonomous workflows.
In our Module 6 — Autonomous Agents, you'll learn:
- →Designing reliable AI workflows
- →Error handling and recovery
- →Human-in-the-loop patterns
- →Scaling AI automation
Module 6 — AI Agents & ReAct
Create autonomous agents that reason and take actions.