GoogleのLLM「Gemini」でコードレビューをするGitHub Actionsを自力で構築してみた

ビジネスdアプリ開発チームの立木です。現在、私たちのチームでは生成AIによる開発効率の向上を検討しています。その一環として、コードレビューの自動化を検討しています。
そこで、本記事では検証の一環として勉強も兼ねて、GoogleのLLM「Gemini」でコードレビューをするGitHub Actionsを自力で構築してみたのでその方法を紹介します。

Geminiとは

Geminiとは、Googleが提供しているLLMです。つい先日も、Gemini 2.5 proがリリースされ、コーディング能力を含め、その能力向上が話題となりました。
APIも提供しており、個人向けではGoogle AI Studio、企業・エンタープライズ向けではGoogle CloudのVertex AI経由で利用できます。

Google AI Studio

Google AI Studioとは、個人向けのGeminiが試せるWebサービスです。Googleアカウントがあれば誰でも利用でき、Gemini 2.5 proを含めたGeminiのさまざまなモデルとのチャットやAPIキーの発行が可能です。

Vertex AI

Vertex AIとは、主にエンタープライズ向けの、Google Cloudが提供している機械学習関連のサービスです。
Geminiに限らず機械学習開発全般に使用できますが、今回はその機能の中の1つのGemini APIを使用します。

Google Gen AI SDK

Google Gen AI SDKとは、Geminiを使用したアプリケーションを開発するためのソフトウェア開発キットです。
Google AI Studio・Vertex AIで発行したAPIキーを使用した開発に対応しています。

対応言語としては、現時点(2025年3月現在)で以下の言語に対応しています。

  • Python
  • Go
  • Java
  • JavaScript/TypeScript(プレビュー版)

Pythonの場合、以下のように実装できます。

・Google AI Studioを使用する場合

from google import genai

# クライアント作成
client = genai.Client(api_key='GEMINI_API_KEY')

# レスポンス取得
response = client.models.generate_content(
    model='gemini-2.0-flash', contents='こんにちは'
)
print(response.text)

・Vertex AIを使用する場合

from google import genai

# クライアント作成
client = genai.Client(
    vertexai=True, project='your-project-id', location='us-central1'
)

# レスポンス取得
response = client.models.generate_content(
    model='gemini-2.0-flash', contents='こんにちは'
)
print(response.text)

着想の背景

Geminiによるコードレビューの自動化の着想に至った背景としては、コードレビューの時間短縮とコードの品質向上のためです。

AIでコードレビューを自動化する方法はすでに公式からも多く提供されており、Geminiの場合はGemini Code Assist for GitHubというGitHub Appをインストールすることで簡単に組み込むことができます。 ですが、内部でどのように動いているかが見えにくいといった課題があり、勉強も兼ねて自身で構築してみることにしたというのが経緯です。

コードレビューの観点

コードレビューを自動化するにあたって、コードレビューの観点を整理しておく必要があります。

すでにチームや全社で決められている場合も多いかと思いますが、今回は例としてGoogleがGemini Code Assistで用いている以下の観点をそのまま使用します。

・正確性: コードが意図したとおりに機能し、エッジケースを処理し、論理エラー、競合状態、API の誤った使用をチェックします。
・効率性: パフォーマンスのボトルネックや最適化の対象となる領域(ループの過剰、メモリリーク、非効率なデータ構造、冗長な計算、過剰なロギング、非効率な文字列操作など)を特定します。
・保守性: コードの読みやすさ、モジュール性、言語の慣用句とベスト プラクティスへの準拠を評価します。変数、関数、クラスの不適切な命名、コメントやドキュメントの欠如、複雑なコード、コードの重複、不整合な形式、マジックナンバーを対象としています。
・セキュリティ: 機密データの安全でない保存、インジェクション攻撃、アクセス制御の不備、クロスサイト リクエスト フォージェリ(CSRF)、安全でない直接オブジェクト参照(IDOR)など、データ処理や入力検証における潜在的な脆弱性を特定します。
・その他: プル リクエストの審査では、テスト、パフォーマンス、スケーラビリティ、モジュール性と再利用性、エラー ロギングとモニタリングなど、その他のトピックも考慮されます。

もちろん、プロンプトの修正によって個々に合わせたカスタマイズが可能です。

完成したもの

完成したもののスクリーンショットです。 以下は、今回実装したGeminiによるコードレビューのプルリクエストを作成し、コードレビューをさせた結果です。
コードレビューの対象としては、ビジネスdアプリのコードではなく、テスト用に私が作成したサンプルプログラムを使用しています。

プルリクエストが開くと、変更の概要と変更されたファイルパスの一覧が表示され、レビューでの指摘事項にそれぞれ、ボットがコメントしていく挙動になっています。 各レビューコメントはMUST, WANTなどのラベルが付けられるようになっています。
(※生成AIは出力に誤りのある可能性があるため、使用の際は注意が必要です)

ファイルの構成

ファイルの構成は以下の通りです。 .github/workflows内にci/cdのyamlファイルを置き、そこからGeminiでコードレビューをするPythonスクリプトのscripts/gemini_review_code.pyを呼び出します。

.github/
  └ workflows/
     ├ scripts/
     |  └ gemini_review_code.py
     └ gemini-code-review.yml

GitHub Actionsを使用したことがない方で、その使用方法について詳しく知りたい場合は、以下の公式ページが参考になるかと思います。
https://docs.github.com/ja/actions/writing-workflows/quickstart

処理の流れ

続いて、処理の流れを説明していきます。

gemini_review_code.pyとgemini-code-review.ymlを先ほどのファイル構成で示した場所にそれぞれ配置します。
プルリクエストを作成すると今回作成したGitHub Actionsが走り、Geminiでコードレビューが該当のプルリクエストで更新のあったファイルのみに対して実行され、結果が表示されます。

ここからは、今回作成したファイルの中身について説明していきます。

gemini-code-review.yml

GitHub Actionsのワークフローファイルである、gemini-code-review.ymlの処理の流れについて説明します。 処理は以下の流れになっています。

  1. コードのチェックアウト
  2. Pythonのセットアップ
  3. 必要なライブラリのインストール
  4. Geminiによるコードレビュー(scripts/gemini_review_code.pyの実行)

ファイルの詳細な中身は以下のようになっています。 事前に環境変数としてGEMINI_API_KEYの設定が必要です。

GITHUB_TOKENはGitHub Appsトークンのことで、GitHub Actionsのワークフロー開始時に自動生成されるトークンです。なので、環境変数として設定することは不要です。
これを使い、事前にpermissionsの部分で必要な権限を与えておくと、GitHub内の情報(プルリクエスト番号やタイトル・本文の情報など)にアクセスできます。

name: Code Review with Gemini

on:
  pull_request:
    branches:
      - develop

permissions:
  pull-requests: write
  contents: read

jobs:
  code_review:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          ref: ${{ github.head_ref }}
          fetch-depth: 0

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.x'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install PyGithub google-genai

      - name: Run Gemini Code Review
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
        run: |
          python .github/workflows/scripts/gemini_review_code.py

gemini_review_code.py

Geminiでのコードレビューをするスクリプトである、gemini_review_code.pyの処理の流れについて説明します。 処理は以下の流れになっています。

  1. PyGitHub (GitHub API)を用いて、該当のリポジトリとプルリクエストの情報を取得
  2. 1で取得したプルリクエストの情報をもとに、変更のあったファイル一覧を取得
  3. プルリクエストの変更差分から変更の概要と変更されたファイル一覧をボットがコメント
  4. 変更のあった各ファイルに対して、Geminiによるコードレビューをし、その内容をボットがコメント

ファイルの中身については長くなってしまうので省略しますが、Google Gen AI SDKとPyGitHubを用いて上記の処理を実装しています。

プロンプト

最後に、プロンプトの中身について説明します。 プルリクエストの変更の概要取得と、コードレビュー時のプロンプトはそれぞれ以下を用いています。

・変更の概要取得プロンプト

変更の概要取得プロンプトは以下の通りです。 出力形式や出力例を与えています。

    あなたはプロフェッショナルなソフトウェアエンジニアです。
    以下はこのプルリクエストで変更されたファイル名と変更されたコードの組み合わせです。
    
    {diff_string}
    
    この内容から与えられた出力形式で、変更の概要と変更されたファイルの一覧を出力してください。
    
    出力形式(markdown形式):
    ## 概要
    (ここに変更の概要を書く)
    
    ## 変更されたファイル
    (変更されたファイルをリスト形式で書く)
    
    出力例:
    ## 概要
    このプルリクエストは、加算処理において引数が負の値の場合に正しい答えを返さないバグの修正を行っています。
    
    ## 変更されたファイル
    - src/add.ts
    - package.json

差分のdiff_stringには、以下のようなファイル名とUnified Diff形式の文字列の組み合わせを与えています。

{
  ".github/workflows/gemini-code-review.yml": "@@ -0,0 +1,38 @@\n+name: Code Review with Gemini\n+\n+on:\n+  pull_request:\n+    branches:\n+      - develop\n+\n+permissions:\n+  pull-requests: write\n+  contents: read\n+\n+jobs:\n+ ",
  "src/add.ts": "@@ -1,2 +1,2 @@\n+function"
}

・コードレビューのプロンプト

コードレビューのプロンプトは以下の通りです。 こちらもdiffとしてUnified Diff形式を与えています。 先ほどのプロンプトの違いは、こちらはJSON形式で返すように指示している点です。

    あなたはプロフェッショナルなソフトウェアエンジニアです。
    以下のコードレビューのルールに従って差分の内容をレビューしてください。
    褒めるコメントは不要です。変更が必要な箇所のみを淡々と指摘してください。

    # 差分(Unified Diff形式)
    以下はUnified Diff形式の差分です。
    @@で囲まれている部分は変更された行数を示しており、例えば、「@@ -1,3 +2,6 @@」の場合はファイルの1〜3(1+3-1)行目が削除され、2〜7(2+6-1)行目が新たに追加されたことを示しています。
    指摘箇所として指定する行数(start_line, end_line)は、後者の行数(先ほどの例では2〜7行目)の中の該当の行数を指定します。
    
    ```diff
    {diff}
    ```

    # コードレビュールール
    コードレビューをする際には、次の点を確認する必要があります。

    ・正確性: コードが意図したとおりに機能し、エッジケースを処理し、論理エラー、競合状態、API の誤った使用をチェックします。
    ・効率性: パフォーマンスのボトルネックや最適化の対象となる領域(ループの過剰、メモリリーク、非効率なデータ構造、冗長な計算、過剰なロギング、非効率な文字列操作など)を特定します。
    ・保守性: コードの読みやすさ、モジュール性、言語の慣用句とベスト プラクティスへの準拠を評価します。変数、関数、クラスの不適切な命名、コメントやドキュメントの欠如、複雑なコード、コードの重複、不整合な形式、マジックナンバーを対象としています。
    ・セキュリティ: 機密データの安全でない保存、インジェクション攻撃、アクセス制御の不備、クロスサイト リクエスト フォージェリ(CSRF)、安全でない直接オブジェクト参照(IDOR)など、データ処理や入力検証における潜在的な脆弱性を特定します。
    ・その他: プル リクエストの審査では、テスト、パフォーマンス、スケーラビリティ、モジュール性と再利用性、エラー ロギングとモニタリングなど、その他のトピックも考慮されます。

    レビューを依頼されたコードの各行を必ず確認し、コンテキストを確認し、コードの健全性を改善していることを確認してください。

    # 参考情報
    severityは指摘事項の重大度を表します。
    以下の値の中から適切なものを選び選択してください。
    Q: 質問
    FYI: 参考までに
    NITS:重箱の隅をつつくような指摘
    IMO:私の意見では
    MUST:必須
    WANT:できれば

    # 出力形式
    指摘事項1つにつき以下のJSON形式で各データを格納し、すべての指摘事項のJSON形式の配列を出力してください。
    もし指摘事項がなければ、空の配列を返してください。

    ```json
    {{
        "start_line": (変更箇所の変更後の開始行数),
        "end_line": (変更箇所の変更後の終了行数),
        "severity": "指摘事項の重大度",
        "comment": "指摘事項"
    }}
    ```

    # 出力例
    [
        {{
            "start_line": 1,
            "end_line": 1,
            "severity": "MUST",
            "comment": "typoがあるので直してください"
        }},
        {{
            "start_line": 13,
            "end_line": 28,
            "severity": "WANT",
            "comment": "関数名はupdateCommentとした方が良いと思います"
        }}
    ]

終わりに

今回は、GeminiでコードレビューをするGitHub Actionsを自力で構築してみました。

精度や挙動の安定度という点ではまだ改善が必要なので、今後も修正を進めていきたいと思います。 また、チーム内で運用することになれば、その評価についても今後行っていきたいと思います。

© NTT Communications Corporation 2014