Running AI in Your CI/CD Pipeline with MonoRouter
Use Claude in GitHub Actions, GitLab CI, or any CI system by routing through MonoRouter. No API credits, no usage surprises.
CI/CD pipelines are one of the best places to use AI — automated code review, test generation, documentation updates. They're also one of the most expensive places to use the Anthropic API, because pipeline runs add up fast. MonoRouter makes this practical.
GitHub Actions: Complete Workflow
Here's a full workflow that runs an AI-powered code review on every pull request:
# .github/workflows/ai-review.yml
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: read
pull-requests: write
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history for diff
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: pip install anthropic
- name: Get PR diff
id: diff
run: |
git diff origin/${{ github.base_ref }}...HEAD > /tmp/pr.diff
echo "lines=$(wc -l < /tmp/pr.diff)" >> $GITHUB_OUTPUT
- name: AI Review
if: steps.diff.outputs.lines > 0
env:
ANTHROPIC_API_KEY: ${{ secrets.MONOROUTER_KEY }}
ANTHROPIC_BASE_URL: https://api.monorouter.dev/v1
run: python scripts/ai-review.py /tmp/pr.diff
- name: Post review comment
if: steps.diff.outputs.lines > 0
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('/tmp/review.md', 'utf8');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: review
});
The Review Script
Here's the Python script that powers the review:
#!/usr/bin/env python3
"""AI-powered code review using Claude through MonoRouter."""
import anthropic
import sys
def review_diff(diff_path: str) -> str:
client = anthropic.Anthropic() # reads env vars
with open(diff_path) as f:
diff = f.read()
# Truncate very large diffs to stay within context limits
if len(diff) > 100_000:
diff = diff[:100_000] + "\n... (truncated)"
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
system="""You are a senior code reviewer. Review the following git diff.
Focus on:
- Bugs and logic errors
- Security vulnerabilities (injection, auth bypass, data exposure)
- Performance issues (N+1 queries, unnecessary allocations)
- Missing error handling
Format your response as markdown. Use ✅ for approvals and ⚠️ for issues.
Start with a one-line summary. Skip style nitpicks.""",
messages=[{"role": "user", "content": f"```diff\n{diff}\n```"}],
)
return response.content[0].text
if __name__ == "__main__":
review = review_diff(sys.argv[1])
# Write to file for the GitHub Action to pick up
with open("/tmp/review.md", "w") as f:
f.write("## AI Code Review\n\n")
f.write(review)
f.write("\n\n---\n*Powered by Claude via MonoRouter*")
print(review)
GitLab CI Configuration
The same approach works with GitLab CI:
# .gitlab-ci.yml
ai-review:
stage: review
image: python:3.12-slim
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
variables:
ANTHROPIC_API_KEY: $MONOROUTER_KEY
ANTHROPIC_BASE_URL: "https://api.monorouter.dev/v1"
before_script:
- pip install anthropic
script:
- git diff $CI_MERGE_REQUEST_DIFF_BASE_SHA...$CI_COMMIT_SHA > /tmp/pr.diff
- python scripts/ai-review.py /tmp/pr.diff
artifacts:
paths:
- /tmp/review.md
expire_in: 1 week
AI Test Generation
Beyond code review, you can use Claude to generate test cases for changed code. Here's a script that generates tests for new functions:
#!/usr/bin/env python3
"""Generate test stubs for new functions in a PR diff."""
import anthropic
import re
def generate_tests(diff_path: str) -> str:
client = anthropic.Anthropic()
with open(diff_path) as f:
diff = f.read()
# Extract only added lines (new code)
added_lines = [
line[1:] for line in diff.split("\n")
if line.startswith("+") and not line.startswith("+++")
]
if not added_lines:
return "No new code to test."
new_code = "\n".join(added_lines)
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
system="""Generate pytest test cases for the following new code.
Include edge cases and error conditions.
Use descriptive test names.
Add brief comments explaining what each test verifies.""",
messages=[{"role": "user", "content": f"```python\n{new_code}\n```"}],
)
return response.content[0].text
if __name__ == "__main__":
import sys
tests = generate_tests(sys.argv[1])
print(tests)
Why CI is Expensive on the API
A code review bot that runs on every PR might analyze 50–100 files per review. That's a lot of input tokens. Here's a real cost projection:
| Metric | Daily | Monthly |
|---|---|---|
| PRs per day | 15 | ~300 |
| Avg diff size | 5,000 tokens | — |
| Review output | 800 tokens | — |
| Input tokens (Sonnet) | 75K | 1.5M |
| Output tokens (Sonnet) | 12K | 240K |
| API cost | $0.40 | $8.10 |
That's just for code review. Add test generation ($15/mo), documentation updates ($10/mo), and commit message suggestions ($5/mo), and CI-driven AI costs hit $40+/month. Through MonoRouter, all of it is covered by your existing subscriptions.
Concurrency and Caching
CI pipelines can trigger multiple jobs simultaneously. MonoRouter's request queuing handles this — jobs wait in the queue rather than failing with 429 errors.
For efficiency, cache your Python dependencies so each CI run doesn't reinstall anthropic:
# GitHub Actions caching
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-anthropic
restore-keys: ${{ runner.os }}-pip-
- run: pip install anthropic
Set generous timeouts in your CI configuration. A review that normally takes 15 seconds might take 60 seconds during peak hours:
- name: AI Review
timeout-minutes: 5 # generous timeout for queued requests
env:
ANTHROPIC_API_KEY: ${{ secrets.MONOROUTER_KEY }}
ANTHROPIC_BASE_URL: https://api.monorouter.dev/v1
run: python scripts/ai-review.py /tmp/pr.diff
Other CI Systems
The same approach works with CircleCI, Jenkins, Buildkite, or any CI system that supports environment variables. The pattern is always the same:
- Store
MONOROUTER_KEYas an encrypted secret - Set
ANTHROPIC_API_KEYandANTHROPIC_BASE_URLin the job environment - Run your Python/TypeScript script as a build step
- Use the output however you need (PR comments, artifacts, Slack notifications)