1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code × Gemini CLIでIssue自動実装&デュアルAIレビューを実現するGitHub Actions

1
Posted at

当記事は生成AIによって執筆しています。内容の正確性には十分注意を払っていますが、誤った情報が含まれている可能性があります。実際にご利用の際は、公式ドキュメント等もあわせてご確認ください。

はじめに

GitHub上での開発フローを効率化したいと考え、AIを活用した自動化ワークフローを構築しました。

具体的には以下を実現します。

  1. Issue自動実装: ラベルを付けるだけでClaude Codeが自動でコードを実装
  2. デュアルAIレビュー: Claude CodeとGemini CLIの2つのAIで多角的なコードレビュー
  3. 自動修正ループ: レビューで問題があれば自動で修正を試行

「AIに任せられる部分は任せて、人間は本質的な判断に集中する」という思想で設計しています。

対象読者

  • GitHub Actionsの基本を理解している方
  • AIを開発フローに取り入れたい方
  • コードレビューの効率化を図りたい方

この記事でわかること

  • Claude Code GitHub Actionsの活用方法
  • Gemini CLIをGitHub Actionsで使う方法
  • 複数AIによるレビューの実装パターン
  • 自動修正ループの設計

環境

項目 バージョン/内容
GitHub Actions ubuntu-latest
Claude Code Action v1
Gemini CLI 最新版
Node.js 20.x

前提条件

  • GitHubリポジトリが作成済みであること
  • Anthropic APIキーを取得済みであること
  • Google APIキー(Gemini用)を取得済みであること

今回のゴール

以下のような自動化フローを構築します。

┌─────────────┐     ┌──────────────────┐     ┌─────────────────────┐
│   Issue     │────▶│  Claude Code     │────▶│   Pull Request      │
│   作成      │     │  自動実装        │     │   作成              │
└─────────────┘     └──────────────────┘     └──────────┬──────────┘
                                                        │
                    ┌───────────────────────────────────┴───────────┐
                    ▼                                               ▼
          ┌─────────────────┐                           ┌─────────────────┐
          │  Claude Code    │                           │  Gemini CLI     │
          │  レビュー       │                           │  レビュー       │
          └────────┬────────┘                           └────────┬────────┘
                   │                                             │
                   └─────────────────┬───────────────────────────┘
                                     ▼
                           ┌─────────────────┐
                           │ 両方OK? ────────┼──▶ マージ可能
                           └────────┬────────┘
                                    │NG
                                    ▼
                           ┌─────────────────┐
                           │  Claude Code    │
                           │  自動修正       │
                           └─────────────────┘

実装手順

1. シークレットの設定

GitHubリポジトリの Settings → Secrets and variables → Actions で以下を設定します。

シークレット名 説明
ANTHROPIC_API_KEY Anthropic Consoleで取得
GOOGLE_API_KEY Google AI Studioで取得

2. ラベルの作成

ワークフローのトリガーとなるラベルを作成します。

# GitHub CLIを使用
gh label create "claude-auto" --color "7C3AED" --description "Claude Codeで自動実装"
gh label create "auto-generated" --color "0EA5E9" --description "自動生成されたPR"
gh label create "needs-review" --color "F59E0B" --description "レビュー待ち"
gh label create "review-passed" --color "10B981" --description "レビュー通過"
gh label create "needs-fix" --color "EF4444" --description "修正が必要"
gh label create "auto-fix" --color "8B5CF6" --description "自動修正を実行"
gh label create "needs-manual-fix" --color "DC2626" --description "手動修正が必要"

3. Issue自動実装ワークフロー

.github/workflows/01-issue-to-implementation.yml を作成します。

name: Issue Auto Implementation

on:
  issues:
    types: [labeled]

jobs:
  implement:
    # 'claude-auto' ラベルが付いた場合のみ実行
    if: github.event.label.name == 'claude-auto'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      issues: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Create feature branch
        run: |
          BRANCH_NAME="feature/issue-${{ github.event.issue.number }}"
          git checkout -b "$BRANCH_NAME"
          echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV

      - name: Run Claude Code for implementation
        uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            以下のIssueを実装してください。

            ## Issue #${{ github.event.issue.number }}: ${{ github.event.issue.title }}

            ${{ github.event.issue.body }}

            ## 実装要件
            - 既存のコードスタイルに従ってください
            - 適切なテストを追加してください
            - コミットメッセージは日本語で、Issue番号を含めてください

      - name: Push changes
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git push origin "${{ env.BRANCH_NAME }}"

      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v6
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          branch: ${{ env.BRANCH_NAME }}
          title: "feat: Issue #${{ github.event.issue.number }} の実装"
          body: |
            ## 概要
            Issue #${{ github.event.issue.number }} を自動実装しました。

            ## 関連Issue
            Closes #${{ github.event.issue.number }}
          labels: |
            auto-generated
            needs-review

ポイント: fetch-depth: 0で全履歴を取得することで、Claude Codeがリポジトリ全体のコンテキストを理解できます。

4. デュアルAIレビューワークフロー

.github/workflows/02-dual-ai-review.yml を作成します。

name: Dual AI Code Review

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  # ===== Claude Code レビュー =====
  claude-review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    outputs:
      has_issues: ${{ steps.parse_result.outputs.has_issues }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Claude Code Review
        id: claude_review
        uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            このPull Requestのコードレビューを行ってください。

            ## PR情報
            - タイトル: ${{ github.event.pull_request.title }}
            - 説明: ${{ github.event.pull_request.body }}

            ## レビュー観点
            1. コード品質: 可読性、保守性、命名規則
            2. バグ・セキュリティ: 潜在的なバグ、脆弱性
            3. パフォーマンス: 非効率なコード
            4. テスト: テストの網羅性

            ## 出力形式
            JSON形式で結果を出力:
            {
              "overall_status": "APPROVED" または "CHANGES_REQUESTED",
              "summary": "評価サマリー",
              "issues": [...]
            }

      - name: Parse Claude review result
        id: parse_result
        run: |
          if echo '${{ steps.claude_review.outputs.result }}' | grep -q '"overall_status": "CHANGES_REQUESTED"'; then
            echo "has_issues=true" >> $GITHUB_OUTPUT
          else
            echo "has_issues=false" >> $GITHUB_OUTPUT
          fi

      - name: Post Claude review comment
        uses: actions/github-script@v7
        with:
          script: |
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: ${{ github.event.pull_request.number }},
              body: `## 🤖 Claude Code Review\n\n${{ steps.claude_review.outputs.result }}`
            });

  # ===== Gemini CLI レビュー =====
  gemini-review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    outputs:
      has_issues: ${{ steps.parse_result.outputs.has_issues }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install Gemini CLI
        run: npm install -g @google/gemini-cli

      - name: Get PR diff
        run: |
          gh pr diff ${{ github.event.pull_request.number }} > pr_diff.txt
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Run Gemini Review
        id: gemini_review
        env:
          GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
        run: |
          cat << 'EOF' > review_prompt.txt
          以下のコード差分をレビューしてください。
          レビュー観点: コード品質、バグ、セキュリティ、パフォーマンス

          $(cat pr_diff.txt)

          JSON形式で出力:
          {"overall_status": "APPROVED"/"CHANGES_REQUESTED", "summary": "...", "issues": [...]}
          EOF

          gemini -p "$(cat review_prompt.txt)" > gemini_result.txt 2>&1 || true
          echo "result<<EOF" >> $GITHUB_OUTPUT
          cat gemini_result.txt >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Parse Gemini review result
        id: parse_result
        run: |
          if grep -q '"overall_status": "CHANGES_REQUESTED"' gemini_result.txt; then
            echo "has_issues=true" >> $GITHUB_OUTPUT
          else
            echo "has_issues=false" >> $GITHUB_OUTPUT
          fi

      - name: Post Gemini review comment
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const result = fs.readFileSync('gemini_result.txt', 'utf8');
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: ${{ github.event.pull_request.number }},
              body: `## 💎 Gemini CLI Review\n\n${result}`
            });

  # ===== レビュー結果の統合判定 =====
  review-summary:
    needs: [claude-review, gemini-review]
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      issues: write

    steps:
      - name: Evaluate review results
        id: evaluate
        run: |
          CLAUDE_ISSUES="${{ needs.claude-review.outputs.has_issues }}"
          GEMINI_ISSUES="${{ needs.gemini-review.outputs.has_issues }}"

          if [ "$CLAUDE_ISSUES" = "true" ] || [ "$GEMINI_ISSUES" = "true" ]; then
            echo "needs_fix=true" >> $GITHUB_OUTPUT
          else
            echo "needs_fix=false" >> $GITHUB_OUTPUT
          fi

      - name: Update PR labels
        uses: actions/github-script@v7
        with:
          script: |
            const needsFix = '${{ steps.evaluate.outputs.needs_fix }}' === 'true';
            const newLabel = needsFix ? 'needs-fix' : 'review-passed';
            
            // 既存ラベルを削除して新しいラベルを追加
            const labelsToRemove = ['review-passed', 'needs-fix', 'needs-review'];
            for (const label of labelsToRemove) {
              try {
                await github.rest.issues.removeLabel({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: ${{ github.event.pull_request.number }},
                  name: label
                });
              } catch (e) { /* ラベルが存在しない場合は無視 */ }
            }
            
            await github.rest.issues.addLabels({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: ${{ github.event.pull_request.number }},
              labels: [newLabel]
            });

解説

  • claude-reviewgemini-review並列実行されるため、レビュー時間を短縮できます
  • 各ジョブのoutputsを使って、review-summaryジョブで結果を統合判定します
  • 一方でも問題を検出した場合はneeds-fixラベルが付与されます

5. 自動修正ワークフロー

.github/workflows/03-auto-fix-on-review.yml を作成します。

name: Auto Fix on Review Failure

on:
  pull_request:
    types: [labeled]

jobs:
  auto-fix:
    if: github.event.label.name == 'auto-fix'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      issues: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          ref: ${{ github.event.pull_request.head.ref }}
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Get review comments
        id: get_reviews
        uses: actions/github-script@v7
        with:
          script: |
            const comments = await github.rest.issues.listComments({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: ${{ github.event.pull_request.number }}
            });

            const reviewComments = comments.data.filter(c =>
              c.body.includes('Claude Code Review') ||
              c.body.includes('Gemini CLI Review')
            );

            const reviewContent = reviewComments
              .slice(-2)
              .map(c => c.body)
              .join('\n\n---\n\n');

            core.setOutput('review_content', reviewContent);

      - name: Count fix attempts
        id: count_attempts
        uses: actions/github-script@v7
        with:
          script: |
            const commits = await github.rest.pulls.listCommits({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: ${{ github.event.pull_request.number }}
            });

            const fixAttempts = commits.data.filter(c =>
              c.commit.message.includes('[auto-fix]')
            ).length;

            core.setOutput('attempts', fixAttempts);

            if (fixAttempts >= 3) {
              core.setFailed('自動修正の上限(3回)に達しました');
            }

      - name: Run Claude Code for auto-fix
        uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            以下のレビューコメントに基づいてコードを修正してください。

            ## 修正試行回数: ${{ steps.count_attempts.outputs.attempts }} / 3

            ## レビューコメント
            ${{ steps.get_reviews.outputs.review_content }}

            ## 修正要件
            1. 指摘された全ての問題を修正
            2. 新たな問題を発生させない
            3. テストも必要に応じて更新

      - name: Commit and push fixes
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"

          if [ -n "$(git status --porcelain)" ]; then
            git add -A
            git commit -m "[auto-fix] レビュー指摘事項の修正 (#${{ steps.count_attempts.outputs.attempts }})"
            git push
          fi

      - name: Remove auto-fix label
        uses: actions/github-script@v7
        with:
          script: |
            try {
              await github.rest.issues.removeLabel({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: ${{ github.event.pull_request.number }},
                name: 'auto-fix'
              });
            } catch (e) { }

ポイント

  • 無限ループを防ぐため、最大3回までの修正試行に制限しています
  • コミットメッセージに[auto-fix]を含めることで、修正回数をカウントできます
  • pushすると再度レビューワークフローがトリガーされ、自動的に再レビューが実行されます

実装のポイント

ポイント1: プロンプト設計

AIの出力品質はプロンプトに大きく依存します。以下を意識しました。

prompt: |
  ## コンテキスト
  (何をレビューするのか明確に)

  ## レビュー観点
  (具体的なチェックポイントを列挙)

  ## 出力形式
  (JSON等の構造化フォーマットを指定)

構造化された出力を要求することで、後続処理でのパース処理が容易になります。

ポイント2: 並列実行による高速化

jobs:
  claude-review:
    # ...
  gemini-review:
    # ...
  review-summary:
    needs: [claude-review, gemini-review]  # 両方完了後に実行

Claude CodeとGemini CLIのレビューを並列実行することで、直列実行と比べて約半分の時間でレビューが完了します。

ポイント3: 自動修正の上限設定

if (fixAttempts >= 3) {
  core.setFailed('自動修正の上限に達しました');
}

AIによる自動修正は万能ではありません。3回修正しても解決しない場合は人間の判断が必要と判断し、needs-manual-fixラベルを付与して通知します。

応用: さらに発展させるには

基本の実装ができたら、以下のような拡張も可能です。

マージ自動化

- name: Auto merge if approved
  if: steps.evaluate.outputs.needs_fix == 'false'
  run: gh pr merge ${{ github.event.pull_request.number }} --squash
  env:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Slack通知

- name: Notify Slack
  uses: slackapi/slack-github-action@v1
  with:
    payload: |
      {
        "text": "PR #${{ github.event.pull_request.number }} のレビューが完了しました"
      }

特定ファイルの除外

- name: Get changed files (exclude tests)
  run: |
    FILES=$(gh pr diff ${{ github.event.pull_request.number }} --name-only | grep -v '_test\.' | tr '\n' ' ')

トラブルシューティング

Q. レビューが実行されない

A. シークレットの設定を確認してください。

# リポジトリのシークレット一覧を確認
gh secret list

また、ワークフローファイルのpermissionsセクションが適切に設定されているか確認してください。

Q. 自動修正がループする

A. 以下を確認してください。

  1. needs-manual-fixラベルが付いていないか
  2. レビューコメントにAIでは対応困難な問題がないか
  3. 修正回数が上限(3回)に達していないか

Q. APIエラーが発生する

A. APIキーの有効性と利用制限を確認してください。

# Anthropic APIのテスト
curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-4-20250514","max_tokens":10,"messages":[{"role":"user","content":"test"}]}'

まとめ

この記事ではClaude CodeとGemini CLIを活用したGitHub Actions自動開発ワークフローを紹介しました。

  • Issue自動実装: ラベル付与だけでPRまで自動作成
  • デュアルAIレビュー: 2つのAIによる多角的なコードレビュー
  • 自動修正ループ: 問題検出時の自動修正(最大3回)
  • 人間へのエスカレーション: 自動で解決できない場合は適切に通知

AIによる自動化は完璧ではありませんが、定型的な作業を削減し、人間がより本質的な判断に集中できる環境を作れます。ぜひプロジェクトに合わせてカスタマイズしてみてください。

参考

サンプルコード

今回のワークフローファイル一式は以下で公開しています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?