GitHub Actions × AI:CI/CDパイプラインにAIを組み込む実践ガイド
PRを出すたびに手動でレビューし、テストを書き、READMEを更新する。個人開発ではこの繰り返しが地味にきつい。GitHub ActionsにAIを組み込めば、この三つを自動化できる。本記事では実際に動くワークフローYAMLを示しながら、導入手順を解説する。
なぜCI/CDにAIを入れるのか
コードレビュー、テスト生成、ドキュメント更新はどれも「コードを読んで判断・生成する」タスクだ。LLMが最も得意とする領域と一致する。
GitHub Actionsに組み込む利点は三つある。
- PR単位で自動実行: 人間がトリガーを意識しなくていい
- 既存パイプラインに追加するだけ: インフラを新たに立てる必要がない
- コスト管理がしやすい: APIコールはPRイベント発生時のみなので青天井にならない
使うAPIはAnthropicのClaude APIだが、OpenAI APIでもロジックはほぼ同じだ。
ユースケース1:PRへのAIコードレビュー
何をやるか
PRがオープン・更新されたとき、差分をAIに送り、改善点・バグリスク・セキュリティ懸念をコメントとして返す。
ワークフローYAML
# .github/workflows/ai-code-review.yml
name: AI 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
- name: Get diff
id: diff
run: |
git diff origin/${{ github.base_ref }}...HEAD > /tmp/diff.txt
echo "diff_size=$(wc -c < /tmp/diff.txt)" >> $GITHUB_OUTPUT
- name: Run AI review
if: steps.diff.outputs.diff_size != '0'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
DIFF=$(cat /tmp/diff.txt | head -c 12000)
# 注意: DIFFに含まれるダブルクォートや改行等の特殊文字がJSONを破壊する可能性がある。
# 本番運用ではjqやpython等でJSONを安全に組み立てること。
# 例: jq -n --arg diff "$DIFF" '{model:"claude-3-5-haiku-20241022",...}'
RESPONSE=$(curl -s https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d "{
\"model\": \"claude-3-5-haiku-20241022\",
\"max_tokens\": 1024,
\"messages\": [{
\"role\": \"user\",
\"content\": \"以下のgit diffをレビューしてください。バグリスク、セキュリティ懸念、改善点を箇条書きで日本語で返してください。問題がなければ '特に問題なし' とだけ返してください。\n\n${DIFF}\"
}]
}")
COMMENT=$(echo "$RESPONSE" | python3 -c "
import json, sys
data = json.load(sys.stdin)
print(data['content'][0]['text'])
")
gh pr comment $PR_NUMBER --repo $REPO --body "## AI コードレビュー
${COMMENT}
*このコメントはAIによって自動生成されました*"
AIレビューの精度とコストを両立させる設計
差分サイズの制限: head -c 12000 で入力トークンを抑える。大きなPRは自動でスキップされるが、それで十分だ。小さなPRほどAIレビューが刺さる。
モデル選択: レビューには claude-3-5-haiku-20241022 を使っている。速くて安い。OpusやSonnetは精度は高いが、毎PRで呼ぶには高コストすぎる。
permissions: pull-requests: write: PRへのコメント書き込みに必要。忘れると403エラーになる。
プロンプト設計: 「問題がなければ ‘特に問題なし’ とだけ返す」と明示しておくことで、過剰なコメントを防げる。
ユースケース2:AIによるテスト自動生成
何をやるか
PRで変更されたソースファイルを検出し、そのファイルに対するテストコードのドラフトをPRコメントとして出力する。そのままペーストして使えるレベルを目標にする。
ワークフローYAML
# .github/workflows/ai-test-gen.yml
name: AI Test Generation
on:
pull_request:
types: [opened]
paths:
- 'src/**/*.ts'
- 'src/**/*.js'
- 'lib/**/*.py'
jobs:
generate-tests:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed source files
id: files
run: |
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD \
| grep -E '\.(ts|js|py)$' \
| grep -v '\.test\.' \
| grep -v '\.spec\.' \
| head -3)
echo "files<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGED" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Generate tests
if: steps.files.outputs.files != ''
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
COMMENT_BODY="## AI テスト生成ドラフト\n\n"
while IFS= read -r FILE; do
[ -z "$FILE" ] && continue
[ ! -f "$FILE" ] && continue
CONTENT=$(cat "$FILE" | head -c 8000)
LANG=$(echo "$FILE" | sed 's/.*\.//')
RESPONSE=$(curl -s https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d "{
\"model\": \"claude-3-5-haiku-20241022\",
\"max_tokens\": 2048,
\"messages\": [{
\"role\": \"user\",
\"content\": \"以下の${LANG}コードに対するユニットテストを生成してください。正常系・異常系・境界値を含めてください。テストコードのみ返してください。\n\n\`\`\`${LANG}\n${CONTENT}\n\`\`\`\"
}]
}")
TEST_CODE=$(echo "$RESPONSE" | python3 -c "
import json, sys
data = json.load(sys.stdin)
print(data['content'][0]['text'])
")
COMMENT_BODY="${COMMENT_BODY}### \`${FILE}\`\n\n${TEST_CODE}\n\n---\n\n"
done <<< "${{ steps.files.outputs.files }}"
printf "%b" "$COMMENT_BODY" > /tmp/comment.txt
gh pr comment $PR_NUMBER --repo $REPO --body-file /tmp/comment.txt
テスト生成の対象選定とコスト制御
対象ファイルの絞り込み: .test. や .spec. を含むファイルを除外している。テストファイル自体のテストを生成しても意味がない。head -3 で最大3ファイルに限定してコストを抑える。
paths フィルタ: ソースファイルが変更されていないPR(ドキュメントのみの変更など)ではジョブ自体を起動しない。無駄なAPI呼び出しを防ぐ。
生成物の扱い: あくまでドラフトとしてコメントに出力し、自動コミットはしない。AIが生成したテストをレビューなしでリポジトリに入れるのはリスクが高い。確認してから手動でペーストする運用が現実的だ。
言語検出: 拡張子から言語を判定してプロンプトに渡す。TypeScriptとPythonでは慣習的なテストの書き方が異なるため、これだけで生成品質が上がる。
ユースケース3:AIによるドキュメント自動更新
何をやるか
mainブランチへのマージ後、変更されたソースファイルを元にREADMEの該当セクションを更新するPRを自動作成する。
ワークフローYAML
# .github/workflows/ai-doc-update.yml
name: AI Doc Update
on:
push:
branches: [main]
paths:
- 'src/**'
- 'lib/**'
jobs:
update-docs:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Get changed files
id: changed
run: |
CHANGED=$(git diff HEAD~1 --name-only | grep -E '\.(ts|js|py)$' | head -5)
echo "files<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGED" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Generate doc update
if: steps.changed.outputs.files != ''
id: docgen
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
CHANGED_FILES="${{ steps.changed.outputs.files }}"
README=$(cat README.md | head -c 4000)
DIFF=$(git diff HEAD~1 HEAD -- $CHANGED_FILES | head -c 8000)
RESPONSE=$(curl -s https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d "{
\"model\": \"claude-3-5-haiku-20241022\",
\"max_tokens\": 2048,
\"messages\": [{
\"role\": \"user\",
\"content\": \"以下のREADMEとコード変更差分を見て、READMEで更新が必要な箇所を特定し、更新後のMarkdownテキストを返してください。README全体を返す必要はなく、変更が必要なセクションのみ返してください。変更が不要なら '更新不要' とだけ返してください。\n\n## 現在のREADME\n${README}\n\n## コード変更差分\n${DIFF}\"
}]
}")
DOC_UPDATE=$(echo "$RESPONSE" | python3 -c "
import json, sys
data = json.load(sys.stdin)
print(data['content'][0]['text'])
")
echo "$DOC_UPDATE" > /tmp/doc_update.txt
echo "update_needed=$([ "$DOC_UPDATE" != '更新不要' ] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
- name: Create PR with doc update
if: steps.docgen.outputs.update_needed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
BRANCH="ai-doc-update-$(date +%Y%m%d-%H%M%S)"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b $BRANCH
# AIが提案した更新内容をREADMEに追記(末尾に提案として追加)
echo "" >> README.md
echo "<!-- AI Doc Update Suggestion -->" >> README.md
cat /tmp/doc_update.txt >> README.md
git add README.md
git commit -m "docs: AI suggested README update"
git push origin $BRANCH
gh pr create \
--title "docs: AI によるREADME更新提案" \
--body "$(cat <<'PRBODY'
mainへのマージ後にAIが生成したドキュメント更新提案です。
内容を確認・編集してからマージしてください。不要なら閉じて構いません。
*このPRはAIによって自動生成されました*
PRBODY
)" \
--base main \
--head $BRANCH
ドキュメント更新PRの安全な運用設計
更新をPRとして出す: ドキュメントを直接mainに書き込まない。AIの提案は必ず人間がレビューするフローを維持する。
fetch-depth: 2: HEAD~1 との差分を取るために必要。デフォルトの fetch-depth: 1 では直前のコミットが取得できずエラーになる。
コスト管理のための入力制限: READMEは4000文字、差分は8000文字に絞っている。それ以上は無視するが、実用上は十分だ。大規模なモノレポには向かないが、個人プロジェクト規模なら問題ない。
コスト試算
個人開発での実際のコストを示す。モデルは claude-3-5-haiku-20241022 を前提とする。
| ユースケース | 入力トークン目安 | 出力トークン目安 | 1回あたりコスト |
|---|---|---|---|
| AIコードレビュー | ~3,000 | ~500 | ~$0.003 |
| テスト生成(3ファイル) | ~6,000 | ~1,500 | ~$0.008 |
| ドキュメント更新 | ~4,000 | ~1,000 | ~$0.005 |
月30PRを出すプロジェクトで全機能を使ったとしても、月$0.5未満に収まる計算だ。
コストを抑える主なコントロールポイントは二つだ。
モデルの使い分け: Haikuで十分な精度が出ることがほとんどだ。コードが複雑で精度を上げたい場合だけSonnetに切り替える。
paths フィルタの活用: 関係ないファイルが変更されたときにジョブを起動しない。設定ファイルやドキュメントのみの変更でAI系ジョブを走らせる必要はない。
Secrets管理
ANTHROPIC_API_KEY はリポジトリのSettings > Secrets and variables > ActionsにRepository secretsとして登録する。
プライベートリポジトリなら問題ないが、パブリックリポジトリでは注意が必要だ。forkされたリポジトリからのPRでは、デフォルトでSecretsが渡されない(pull_request_target を使えば渡せるが、セキュリティリスクを伴う)。パブリックリポジトリでAIレビューを使いたい場合は、pull_request_target の挙動を十分理解した上で設定すること。
まとめと導入順序
三つのユースケースを紹介したが、いきなり全部入れる必要はない。導入の難易度と効果を考えると、以下の順序が現実的だ。
- まずAIコードレビュー: 最もシンプルで効果がわかりやすい。差分を渡してコメントを返すだけで、すぐ動く。
- 次にテスト生成: テストが薄いプロジェクトで即効性がある。出力はドラフトとして使い、品質は自分で判断する。
- 最後にドキュメント更新: PRを自動作成するため、設定が少し複雑になる。リポジトリの運用が安定してから導入する。
CI/CDパイプラインにAIを組み込むことで、レビュー・テスト・ドキュメントの三点セットが自動化できる。ただし、AIの出力を無条件に信頼しないことが前提だ。コメントやPRとして提案し、人間が最終判断する設計を維持することで、品質とスピードを両立できる。
関連記事
Agentive 編集部
AIエージェントを実際に使い倒す個人開発者。サイト制作の自動化を実践しながら、その知見を発信しています。