AIによるコードレビュー "PR-Agent" を導入した効果と課題について

サムネイル

AIによるコードレビューができるPR-Agentを導入した効果と課題について書いています。
導入結果としては、AIによるコードレビューが効果がある一方で、現時点では全てのレビューがAIに置き換えることはないことが分かりました。
この記事では、PR-Agentの具体的な効果、実際に感じた課題、課題に対する横断チームの対応策などを掘り下げています。

はじめに

こんにちは、DMM.comの松井建登です。
現在は、プラットフォーム開発本部 Developer Productivity Group 横断チームに所属しています。

所属している横断チームでは、社内の多様なサービスの開発生産性を上げるために、他チームにいくつかのプラットフォームを提供しています。
そのうちの1つに、複数のサービスのコードを、同一のGitHub Repositoryで管理するモノレポがあります。
モノレポは、複数のサービスのコードを同一のGitHub Repositoryで管理することで、CI/CDを共通化できたり、各種便利ツールを効率よく導入できたりします。
その便利ツールの1つとして、AIによるレビューができるPR-Agentを導入しました。

この記事では、主にPR-Agentの導入までのプロセスについてお話しします。

PR-Agentの概要

PR-Agentは、Codium AIにより、オープンソースで開発されているAIツールです。
裏側では、GPT-3.5やGPT-4を使い、GitHubのPull Requestに対して行える、以下の機能を提供しています。

  • Pull Requestで変更されたコードの、分析・要約・レビューを行う
  • Pull Requestのタイトルと説明を変更する
  • Pull Requestで変更されたコードの改善提案を行う
  • Pull Request内での、テキストベースの質問に回答する
    などなど

また、ぞれぞれの機能がreview, describe, improve,documentationなどのように種別で分かれており、必要な機能だけを呼び出せます。
モノレポではレビューに関係があり、PR-Agentの無料版で使えるreview, describe, improveの3つの機能を使っています。

そして、PR-Agentからは、GitHub ActionsのWorkflowを使って導入するためのActionsが提供されています。
そのため、Azure OpenAI API Keyさえあれば、GitHub ActionsのWorkflowで、導入自体は簡単にできます。

具体的な導入方法や詳細な機能に関しては、PR-AgentのGitHub Repositoryを参考にしてください。
https://github.com/Codium-ai/pr-agent

導入の目的

モノレポ環境にPR-Agentを導入した主な目的は、レビューコストの削減とコード品質の担保 です。
PR-Agentを利用して、初回のレビューを自動化することで、タイプミスやエラーの握りつぶしなどのよくあるミスを未然に防ぎます。
さらに、Pull Requestのタイトルと説明を分かりやすくすることで、レビュアーがPRの概要を把握しやすくなり、レビュー効率が向上します。

そして、AIが初歩的なミスを指摘することにより、人間のレビュアーはアーキテクチャやその他の重要なコードに集中できるようになります。
このように、レビューの速度と品質が向上し、結果としてコストの削減と品質の担保が実現されることを期待して導入しました。

導入までのプロセス

機能調査と費用の見積もり

機能調査

どのような機能があり、導入の目的が達成できそうかを調査しました。
結果、「PR-Agentの概要」にも書いた通り、Pull Requestに対する機能が揃っているため、問題なしと判断しました。

費用の見積もり

費用が許容範囲内であるかを確認するために、どのくらいの大きさのPRで、何円かかるかを調査しました。
調査方法は、PR-Agentを導入、複数サイズのPRを作成、Azuruから費用を確認するだけです。
あらかじめ、テックリードから「それ相応の利便性とメリットがあれば、費用はかかっても良い 」との話がありました。
そのため、「レビュアーの時給がxxxx円で、月yy時間が削減される」などの調査はしていません。

1チームへの試験導入

機能調査と見積もりが終われば、モノレポに導入する前に、1チームに試験導入を行いました。
試験導入の目的は、以下の通りです。

レビューコメントの精度確認

AIによるレビューコメントの精度を評価し、実際の環境での有効性を検証します。
これにより、AIが生成するフィードバックの質と実用性を確認しました。

必要 / 不要な機能の洗い出し

PR-Agentでは、GitHub Actions内でtrue/falseのフラグや数値を入れることで、機能をカスタマイズできます。
試験導入を通じて、開発チームにとって価値のある機能と、使用されない、または不要な機能を特定しました。

未発見の問題がないかの確認

新しいツールの導入には、予期せぬ問題が発生する可能性があります。
試験導入を通じて、隠れたバグや使用上の問題点がないかを調査しました。

モノレポへの導入

モノレポへの導入は、以下の2つを要件とします。

  1. PRの作成・更新時に、自動でPR-Agentを実行できること
  2. 各開発チームによって、PR-Agentの機能をカスタマイズできること

上記の要件を満たすために、以下の手順でモノレポへの導入を進めます。

PR-Agentの機能を選別する

各開発チームによって、PR-Agentで使いたい機能が異なるため、カスタマイズできるようにする必要があります。
しかし、全機能をカスタマイズできるようにすると、開発チームに負担がかかり、使ってもらえなくなります。
そのため、横断チームがON/OFFを決める機能と、各開発チームがカスタマイズできる機能に選別しました。

具体的には、以下の4つの機能に分けます。

  1. 強制的にONにする機能
  2. 強制的にOFFにする機能
  3. デフォルトはONにするが、各開発チームがカスタマイズできる機能
  4. デフォルトはOFFにするが、各開発チームがカスタマイズできる機能

以下は、選別した機能の例です。

オプション 説明 デフォルト値 開発チームがカスタマイズできるか
estimate_review_effort
labeling_review_effort
trueにすると、5段階でレビューにかかる労力を見積もります。
強制的にこの機能を使わせることで、後でラベルで絞り込み、各開発チームのレビュー負荷を算出できます。
レビュー負荷が高いチームには、「PRのサイズを小さくし、負荷を下げるように提案する」などの使い道があります。
true ×
require_score_review PRの点数を算出します。
何を根拠に算出しているか分からないため、この機能は使えないようにしました。
false ×
inline_code_comments trueにすると、インラインコメントとしてレビューコメントを残します。
falseにすると、通常のPRコメントとしてレビューコメントを残します。
好みが分かれる可能性があるため、デフォルトはtrueにしますが、各開発チームでカスタマイズできるようにします。
true
summarize trueにすると、コード改善提案のレビューコメントが1つのPRコメントにまとめて投稿されます。
falseにすると、レビューコメントが1つずつ投稿されます。
好みが分かれる可能性があるため、デフォルトはfalseにしますが、各開発チームでカスタマイズできるようにします。
false

モノレポの設定ファイルで、PR-Agentをカスタマイズできるようにする

モノレポには、各種ツールやCI/CDで使う設定を行うために、各サービス配下に設定ファイルが存在します。

モノレポのGitHub Repository
└── go/services
  ├── service-a
  │ └── setting.yaml
  └── service-b
    └── setting.yaml

今回は、PR-Agentの機能をカスタマイズできるようにするために、設定ファイルに以下のように記述します。
次のセクションで、GitHub ActionsのWorkflowから、この設定ファイルを読み取るようにします。

  • setting.yaml
# PR-AGENT自体のオン/オフ
pr-agent: true

# PR Agentの設定
pr-agent-setting:
  review:
    pr_opened_pushed: true
    focused_one_thing: true
    test_review: true
    security_review: false
    num_code_suggestions: 4
    inline_code_comments: true
    extra: ""
  describe:
    pr_opened_pushed: true
    extra: ""
  improve:
    pr_opened_pushed: true
    num_code_suggestions: 4
    summarize_suggestions: false
    extra: ""

PR-Agentを実行するGitHub ActionsのWorkflowを作成する

  • PR-Agentが提供しているActionの機能

1. 特定の環境変数を設定することで、PRの作成時にPR-Agentを実行できる
PRの作成時がトリガーになっているWorkflowで、以下の環境変数をtrueに設定します。
そして、同じWorkflow内でPR-Agentが提供しているActionを実行すると、PRの作成時にPR-Agentが実行できます。

GITHUB_ACTION.AUTO_REVIEW
GITHUB_ACTION.AUTO_DESCRIBE
GITHUB_ACTION.AUTO_IMPROVE

2. 特定の環境変数を設定することで、PRの作成時にPR-Agentを実行できる
PR-Agentが提供しているActionは、トリガーになったコメントの内容によって、呼び出すPR-Agentの機能を変えます。
これが「PR-Agentの概要」で書いた「必要な機能だけを呼び出せる 」ということです。
例えば、/review というコメントの投稿がトリガーで、PR-Agentが提供しているActionを含んだWokrflowが実行された場合、PR-Agentのreview機能 が実行できます。

つまり、以下の2つのWorkflowを作成することで、PRの作成・更新時にPR-Agentを実行するという要件を満たせます。

  1. PRの作成とコメントの投稿がトリガーでかつ、PR-Agentが提供しているActionを使ったWorkflow
  2. PRの更新がトリガーでかつ、PR-Agentの機能を呼び出すコメントを実行するWorkfklow


  • PRの作成とコメントの投稿がトリガーでかつ、PR-Agentが提供しているActionを使ったWorkflow
name: "Exec PR Agent"

on:
  pull_request:
    types: [opened]
  issue_comment:
    types: [created]

jobs:
  # 1. PRで変更されているサービス名を取得するjobが入ります(extract-changed-services)。
  # 2. 設定ファイルからPR-Agent自体がONになっているか確認するjobが入ります(check-run-pr-agent)。

  # 3. PR-Agentの機能をカスタマイズする環境変数を設定します。
  set-pr-agent-env:
    needs: [check-run-pr-agent]
    if: ${{ needs.check-run-pr-agent.outputs.pr_agent == 'true' }}
    runs-on: ubuntu-latest
    name: Set PR Agent Env
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: "Install yq command"
        run: |
          wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq
          chmod +x /usr/local/bin/yq

      - name: Set ENV
        run: |
          SETTING_FILE_PATH="go/services/service-a/setting.yaml"
          echo "SETTING_FILE_PATH=$SETTING_FILE_PATH" >> $GITHUB_ENV

          # ここでtrue / falseを切り替えることで、PR作成時にどの機能を実行するかを決められます。
          echo "GITHUB_ACTION.AUTO_REVIEW=$(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.review.pr_opened_pushed')" >> $GITHUB_ENV
          echo "GITHUB_ACTION.AUTO_DESCRIBE=$(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.describe.pr_opened_pushed')" >> $GITHUB_ENV
          echo "GITHUB_ACTION.AUTO_IMPROVE=$(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.improve.pr_opened_pushed')" >> $GITHUB_ENV

          # 特定のファイルは、PR-Agentのレビュー対象外にできます。
          echo "IGNORE.GLOB=$(cat $SETTING_FILE_PATH | yq -o=json -I=0 '.pr-agent-setting.ignore')" >> $GITHUB_ENV

          # /review で指定する設定(PR_REVIEWER)
          # 設定ファイルでカスタマイズする設定
          echo "PR_REVIEWER.INLINE_CODE_COMMENTS=$(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.review.inline_code_comments')" >> $GITHUB_ENV
          echo "PR_REVIEWER.EXTRA_INSTRUCTIONS=Please use Japanese. $(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.review.extra')" >> $GITHUB_ENV
          (省略)
          # 横断チームが強制でON / OFFを決める設定
          echo "PR_REVIEWER.REQUIRE_ESTIMATE_EFFORT_TO_REVIEW=true" >> $GITHUB_ENV
          echo "PR_REVIEWER.ENABLE_REVIEW_LABELS_EFFORT=true" >> $GITHUB_ENV

          # /describe で指定する設定(PR_DESCRIPTION)
          echo "PR_DESCRIPTION.EXTRA_INSTRUCTIONS=Please use Japanese. $(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.describe.extra')" >> $GITHUB_ENV
          (省略)

          # /improve で指定する設定(PR_CODE_SUGGESTIONS)
          echo "PR_CODE_SUGGESTIONS.NUM_CODE_SUGGESTIONS=$(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.improve.num_code_suggestions')" >> $GITHUB_ENV
          (省略)

      # 4. PR-Agentを実行する
      - name: Exec PR Agent
        id: exec-pr-agent
        uses: Codium-ai/pr-agent@main
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OPENAI.KEY: ${{ secrets.OPENAI_KEY }}
          OPENAI.API_TYPE: "azure"
          OPENAI.API_VERSION: "2023-05-15"
          OPENAI.API_BASE: "xxxxxxxxx"
          OPENAI.DEPLOYMENT_ID: "pr-agent"
  • PRの更新がトリガーでかつ、PR-Agentの機能を呼び出すコメントを実行するWorkfklow

自動的にコメントを打つようにする目的は、開発チームがPR-Agentを実行するコメントを覚えなくてもいい、かつ更新のたびに投稿する必要をなくすためです。
また、開発チームがコメントを覚えなくていいようにすることで、開発チームの負担を減らします。

name: "Post Comment For PR Agent"

on:
  pull_request:
    types: [synchronize]

env:
  REVIEW_COMMAND: /review
  DESCRIBE_COMMAND: /describe
  IMPROVE_COMMAND: /improve

jobs:
  # 1. PRで変更されているサービス名を取得するjobが入ります(extract-changed-services)。
  # 2. 前回の更新によって、投稿されたコメントを削除するjobが入ります(cleanup-previous-comments)。
  # ここで削除しないと、ずっとコメントが残り続け、ノイズになるため削除するjobを入れています。
  # 3. 設定ファイルからPR-Agent自体がONになっているか確認するjobが入ります(check-run-pr-agent)。

  # 4. ①で作成したWorkflowを実行するためのコメントを投稿します。
  post-comment:
    needs: [extract-changed-services, check-run-pr-agent, cleanup-previous-comments]
    if: ${{ needs.check-run-pr-agent.outputs.pr_agent == 'true' }}
    runs-on: ubuntu-latest
    name: Post Comment
    env:
      GH_TOKEN: ${{ secrets.GH_TOKEN }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: "Install yq command"
        run: |
          wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq
          chmod +x /usr/local/bin/yq

      - name: Check Run PR Agent Command
        id: check-run-pr-agent-command
        run: |
          SETTING_FILE_PATH="go/services/service-a/pf-code-universe_setting/setting.yaml"
          IS_REVIEW=$(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.review.pr_opened_pushed')
          IS_DESCRIBE=$(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.describe.pr_opened_pushed')
          IS_IMPROVE=$(cat $SETTING_FILE_PATH | yq '.pr-agent-setting.improve.pr_opened_pushed')
          echo "is_review=$IS_REVIEW" >> $GITHUB_OUTPUT
          echo "is_describe=$IS_DESCRIBE" >> $GITHUB_OUTPUT
          echo "is_improve=$IS_IMPROVE" >> $GITHUB_OUTPUT

      - name: Post Review Start Message
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN }}
        run: |
          if [ "${{ steps.check-run-pr-agent-command.outputs.is_review }}" == "true" ]; then
            BODY=$(echo -e "${{ env.REVIEW_COMMAND }}")
            gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "$BODY"
          fi

          if [ "${{ steps.check-run-pr-agent-command.outputs.is_describe }}" == "true" ]; then
            BODY=$(echo -e "${{ env.DESCRIBE_COMMAND }}")
            gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "$BODY"
          fi

          if [ "${{ steps.check-run-pr-agent-command.outputs.is_improve }}" == "true" ]; then
            BODY=$(echo -e "${{ env.IMPROVE_COMMAND }}")
            gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "$BODY"
          fi

PR-Agentの出力例

PR-Agentのバージョンによって、表示されるコメントのフォーマットが変わるため、最新バージョンを確認したい場合はPR-Agentのmdファイルを参考にしてください。

review機能(PRの要約と提案)

review機能の出力例

describe機能(PRの説明とタイトルを変更・追記する)

describe機能の出力例

improve機能(コードの改善提案)

improve機能の出力例

現時点でのPR-Agentの評価

良い点: よくあるミスの指摘は精度が高い

PR-Agentは、1つのファイルでのよくあるミスの指摘は精度が高いです。
具体的には、クリーンアップ処理の忘れや、エラーの握りつぶしなどです。
そのため、レビュアーは以下画像のようなミスを指摘する必要がなくなります。

  • deferでのクリーンアップ処理をしていない(golang)

  • エラーハンドリングを忘れている(golang)

  • suspendがtrueになっている(k8s manifest)

良い点: PRの変更点を要約できる

以下画像のように、PR-AgentではPull Requestの変更点を要約できます。
具体的には、DescriptionセクションにはPull Request全体の変更点が列挙されており、Changes walkthroughセクションにはファイル単位での変更点が列挙されています。
そのため、Pull Requestの作成者はdescriptionを書く量を減らせ、レビュアーは変更点が明確になることで、レビューしやすくなります。

物足りない点: PR-Agentのレビューには限界がある

PR-Agentが生成したレビューコメントや、PRのタイトルと説明の正確さを保証するためには、人間による判断が必要です。
つまり、PR-Agentは、初心者向けのサポート機能というよりは、一定の開発スキルやリテラシーを持つ開発者のサポート機能であり、高機能なLinterのイメージです。
横断チームとしては、PR-Agentを上記の理解のもと運用しており、人間によるレビューはなくならないと考えています。
そのため、人間によるレビューを行うためのレビューシステム の構築を行っています。

レビューシステムについての詳細は、以下のURLを参考にしてください。

結論

横断チームでは、AIレビューによる効果はあるが、人間によるレビューが不要になるような期待しているほど効果はない と結論づけています。

得られた教訓やプラクティス

コメントによるノイズは少なくする

PR-Agentは、コメントベースの機能が多いです。
モノレポのデフォルト設定で、PR-Agentを実行すると、1回あたり10個ほどコメントが投稿されます。
そのため、PR-Agentを実行するたびに、前回の実行で投稿されたコメントを削除するような対応をしないと、ノイズになります。
ノイズが増えると、開発チームがPR-Agentを使わなくなります。

レビュー対象外のファイルを設定できるようにする

PR-Agentは、デフォルトではPRで変更されたコードを全て対象とします。
ただ、READMEのようなドキュメントをレビューしてほしい開発チームは少ないです。
そのため、レビュー対象外のファイルを設定できるようにしておくことで、レビュー費用を削減できます。
また、レビューファイルが少なくなることで、PR-Agentの実行時間が短くなり、開発者体験が良くなります。

開発チームへの負担を減らす

ツールを導入する際に、開発チームの負担が大きくなると、そのツールを使わなくなります。
例えば、上記でも説明した通り、カスタマイズできる機能を提供するチーム側で絞ったり、
自動的にコメントが投稿されるようにしたりすることで、ツールを導入することによる開発チームの負担を減らします。

AIによるコードレビュー"PR-Agent"についてのまとめ

この記事では、DMM.comのモノレポ環境におけるAIベースのレビューツール、PR-Agentの導入プロセスについてお話ししました。
PR-Agentの導入の主な目的は、レビューコストの削減とコード品質の担保であり、初回のレビューを自動化し、レビュープロセスの効率化を図ることです。
また今後は、さらなるコストの削減やコード品質の担保を行うために、以下のことに取り組んでいく予定です。

今後取り組むこと

開発チームからのフィードバックを受け、PR-Agentの設定を改善する

僕が所属している横断チームには、GitHub Issuesの機能を利用して、横断チームが提供しているプラットフォームに対する問い合わせを行える仕組みがあります。
そこから開発チームのフィードバックを受け、カスタマイズできる機能の増減、デフォルト設定の変更を行い、PR-Agentの設定を改善し続けています。

モノレポ以外のGitHub Repositoryに横展開する

モノレポへの導入を知見を踏まえて、PR-Agentを他のGitHub Repositoryに横展開します。
現在では、k8sのマニフェストファイルを管理するGitHub Repositoryにも、PR-Agentを導入しています。

GitHub Repositoryにあるコード全体をAIレビューできる仕組みを構築する

PR-Agentは、PRで変更されたファイルでかつ、変更されたファイルを1つずつレビューし、ファイル内でのミスを指摘することが多いです。
しかし、Repositoryにあるコード全体をレビューできるようになると、アーキテクチャのような複数ファイルを跨いだレビューを行える可能性があります。
そのため、PR-Agent含むAIツールを使うことで、Repositoryにあるコード全体をAIレビューにかける仕組みを構築できないか模索しています。