Claude CodeでCI/CDを自動生成する
GitHub Actionsのワークフローファイルは覚えることが多い。
Claude CodeにCLAUDE.mdでルールを渡すと、プロジェクトの制約に従ったCI/CDを自動生成してくれる。
CLAUDE.mdにCI/CDルールを定義する
# CI/CD Rules
## ブランチ戦略
- mainへの直接pushは禁止。必ずPR経由
- 全PRにCIパスが必須(ci-required status check)
## パイプラインステージ(順序厳守)
1. lint — ESLint + Prettier check
2. test — Jest(カバレッジ80%以上必須)
3. build — tsc + vite build
4. deploy — mainマージ時のみ、Blue-Green本番反映
## シークレット管理
- APIキーは全てGitHub Secretsに格納
- .env は .gitignore 必須
CIワークフロー生成プロンプト
Node.js 20のCIワークフローをCLAUDE.mdのルールに従って生成してください。
ステージ: lint → test(カバレッジ80%以上)→ build
npm依存のキャッシュ、テスト結果のGitHub Actions Summary表示を含める。
生成される.github/workflows/ci.ymlの主要部分:
name: CI
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npm run lint
- run: npm run format:check
test:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- name: Run tests with coverage
run: npm test -- --coverage --coverageReporters=json-summary
- name: Coverage gate (80%)
run: |
COVERAGE=$(node -e "
const s = require('./coverage/coverage-summary.json');
console.log(s.total.lines.pct);
")
node -e "if (${COVERAGE} < 80) process.exit(1)"
echo "Coverage: ${COVERAGE}%" >> $GITHUB_STEP_SUMMARY
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci && npm run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
PRへの自動カバレッジコメント
PRオープン・更新時にカバレッジ差分をPRコメントとして投稿するジョブを追加してください。
既存コメントがある場合は更新する。カバレッジが下がった場合は警告アイコンを表示。
生成コード抜粋:
coverage-comment:
needs: test
permissions:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const base = parseFloat(process.env.BASE_COVERAGE) || 0;
const pr = parseFloat(process.env.PR_COVERAGE) || 0;
const diff = (pr - base).toFixed(1);
const icon = pr < base ? '⚠️' : '✅';
const body = `## ${icon} Test Coverage
| Branch | Coverage |
|--------|----------|
| Base | ${base}% |
| PR | ${pr}% |
| Diff | ${diff > 0 ? '+' : ''}${diff}% |`;
// 既存コメントを検索して更新
const comments = await github.rest.issues.listComments({
...context.repo, issue_number: context.issue.number
});
const existing = comments.data.find(c => c.body.includes('Test Coverage'));
if (existing) {
await github.rest.issues.updateComment({
...context.repo, comment_id: existing.id, body
});
} else {
await github.rest.issues.createComment({
...context.repo, issue_number: context.issue.number, body
});
}
本番デプロイ(Blue-Green方式)
mainブランチへのマージで本番デプロイするワークフローを生成してください。
Blue-Green方式でゼロダウンタイムデプロイ。ヘルスチェック失敗時は自動ロールバック。
デプロイ結果をSlackに通知。
生成される.github/workflows/deploy.ymlの主要部分:
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Build and push Docker image
run: |
docker build -t myapp:${{ github.sha }} .
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker push ghcr.io/${{ github.repository }}/myapp:${{ github.sha }}
- name: Deploy to Green
run: |
ssh ubuntu@${{ secrets.DEPLOY_HOST }} "
docker pull ghcr.io/${{ github.repository }}/myapp:${{ github.sha }}
docker run -d --name myapp-green -p 3001:3000 \
ghcr.io/${{ github.repository }}/myapp:${{ github.sha }}
"
- name: Health check
run: |
for i in {1..10}; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://${{ secrets.DEPLOY_HOST }}:3001/health)
[ "$STATUS" = "200" ] && exit 0
sleep 5
done
exit 1
- name: Switch traffic
if: success()
run: |
ssh ubuntu@${{ secrets.DEPLOY_HOST }} "
sed -i 's/3000/3001/' /etc/nginx/conf.d/app.conf
nginx -s reload
docker stop myapp-blue 2>/dev/null || true
docker rename myapp-green myapp-blue
"
- name: Rollback on failure
if: failure()
run: |
ssh ubuntu@${{ secrets.DEPLOY_HOST }} "
docker stop myapp-green 2>/dev/null || true
docker rm myapp-green 2>/dev/null || true
"
- name: Notify Slack
if: always()
run: |
STATUS="${{ job.status }}"
ICON=$([ "$STATUS" = "success" ] && echo ":rocket:" || echo ":x:")
curl -s -X POST "${{ secrets.SLACK_WEBHOOK }}" \
-H "Content-Type: application/json" \
-d "{\"text\": \"${ICON} Deploy ${STATUS}: \`${{ github.sha }}\`\"}"
まとめ
| ステップ | 内容 |
|---|---|
| CLAUDE.md定義 | ブランチ戦略・ステージ順序・シークレット管理ルールを明文化 |
| CIワークフロー | lint→test(カバレッジ80%)→build。キャッシュで高速化 |
| PR自動コメント | カバレッジ差分を表示。既存コメントを更新 |
| デプロイ | Blue-Greenで安全なゼロダウンタイムデプロイ |
CLAUDE.mdにルールを書いてからプロンプトを実行すると、汎用テンプレートではなくプロジェクト固有のCI/CDが生成される。
Code Review Pack(¥980)の /code-review スキルで、生成したCI設定ファイルの漏れ・セキュリティリスクを自動検出できます。