|
| 1 | +--- |
| 2 | +title: "GitLabのレビューにPR-Agentを組み込んでみた" |
| 3 | +date: 2025/04/17 00:00:00 |
| 4 | +postid: a |
| 5 | +tag: |
| 6 | + - pr-agent |
| 7 | + - GitLab |
| 8 | + - 生成AI |
| 9 | + - GitLab |
| 10 | +category: |
| 11 | + - DevOps |
| 12 | +thumbnail: /images/20250417a/thumbnail.png |
| 13 | +author: 髙橋遼 |
| 14 | +lede: "フューチャーでは、Gitホスティング環境として、SaaSとしてのGitHubだけでなく、社内開発基盤運用チームが構築・運用している、オンプレミス版のGitLabも利用可能となっています。" |
| 15 | +--- |
| 16 | +# はじめに |
| 17 | + |
| 18 | +こんにちは。フューチャーの社内セキュリティ部門、SATの髙橋です。 |
| 19 | + |
| 20 | +フューチャーでは、Gitホスティング環境として、SaaSとしてのGitHubだけでなく、社内開発基盤運用チームが構築・運用している、オンプレミス版のGitLabも利用可能となっています。 |
| 21 | + |
| 22 | +私が所属するSATでは、後者のGitLabを用いて開発を行っています。 |
| 23 | + |
| 24 | +近頃の社内では、「[Gemini、社内利用スタート!](/articles/20250311a/)」といった記事に代表されるように、AI業務利活用の動きが本格化しています。 |
| 25 | + |
| 26 | +SATでも、主にセキュリティの観点から、次々に出てくるAIサービスについて継続的に検証を進めています。そうした日々の中、開発も並行して行っていると、**GitLabでも、GitHub Copilotのように、AIによるコードレビューの自動化を実現したい!** というモチベーションが湧くようになりました。 |
| 27 | + |
| 28 | +いろいろと探していたところ、[PR-Agent](https://github.com/qodo-ai/pr-agent)というOSSに出会いました。 |
| 29 | + |
| 30 | +この記事では、GitLabに組み込んでみた実例を元に、PR-Agentでできることを紹介したいと思います。 |
| 31 | + |
| 32 | +<div class="note info" style="background: #e5f8e2; padding:16px; margin:24px 12px; border-radius:8px;"><span class="fa fa-fw fa-check-circle"></span> |
| 33 | + |
| 34 | +GitLabの公式AIソリューションとしては、[GitLab Duo](https://about.gitlab.com/ja-jp/gitlab-duo/)が既にエンタープライズ向けに提供されています。 |
| 35 | + |
| 36 | +[参考:GitLab Duoエンタープライズを提供開始](https://about.gitlab.com/ja-jp/blog/2024/09/03/gitlab-duo-enterprise-is-now-available/) |
| 37 | + |
| 38 | +**本記事執筆時点(2025年4月)** においては、前述の社内環境内ではまだ利用できません。 |
| 39 | + |
| 40 | +</div> |
| 41 | + |
| 42 | +# PR-Agentとは |
| 43 | + |
| 44 | +PR-Agentは、大規模言語モデル(LLM)を活用してPull Requestに関連する様々なタスクを自動化・強化するために設計されたオープンソース**ツール**です。 |
| 45 | + |
| 46 | +Qodo(旧CodiumAI)によって開発が進められており、Apache 2.0ライセンスの下で公開されています。OSSの信頼性を判断する指標の一つであるGitHubでのスター数は`7.6k`(本記事執筆時点)と、一定の評価を得ていると言えるでしょう。 |
| 47 | + |
| 48 | +なお、PR-Agentをベースにより機能が豊富な[Qodo Merge](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/)というマネージドサービスもありますが、本記事での紹介は割愛します。 |
| 49 | + |
| 50 | +最大の特徴は、**Pull Requestを基にしたレビュー関連機能の提供に特化している**点にあります。LLMへの対応状況は、[こちら](https://github.com/qodo-ai/pr-agent/blob/main/pr_agent/algo/__init__.py)で確認できますが、Geminiを始め、代表的なLLMは利用可能となっています。最近公開されたモデルも随時リストアップされていることから、新型モデルへの対応が迅速に行われていることが伺えます。 |
| 51 | + |
| 52 | +## PR-Agentとのやり取り |
| 53 | + |
| 54 | +PR-Agentとのやり取りは、Pythonで実装されたCLIツール(後述)、またはPull Request上のコメントから以下のようなスラッシュコマンドを経由して行います。 |
| 55 | + |
| 56 | +<div class="note info" style="background: #e5f8e2; padding:16px; margin:24px 12px; border-radius:8px;"><span class="fa fa-fw fa-check-circle"></span> |
| 57 | + |
| 58 | +**以下の情報は、本記事執筆時点(2025年4月)のものです。** |
| 59 | + |
| 60 | +</div> |
| 61 | + |
| 62 | +- Describe |
| 63 | + - slash_command: `/describe` |
| 64 | + - cli: `python -m pr_agent.cli --pr_url=<pr_url> describe` |
| 65 | + - AIがPRの内容を解析し、概要欄などを自動生成・更新します |
| 66 | +- Review |
| 67 | + - slash_command: `/review` |
| 68 | + - cli: `python -m pr_agent.cli --pr_url=<pr_url> review` |
| 69 | + - PR内の修正について、AIによるレビューを実施し、フィードバックしてくれます |
| 70 | +- Improve |
| 71 | + - slash_command: `/improve` |
| 72 | + - cli: `python -m pr_agent.cli --pr_url=<pr_url> improve` |
| 73 | + - PR内の実装について、改善案の提案を受けることができます |
| 74 | + - 設定によっては、Push毎の自動起動も可能です |
| 75 | +- Ask |
| 76 | + - slash_command: `/ask` |
| 77 | + - cli: `python -m pr_agent.cli --pr_url=<pr_url> ask "your question"` |
| 78 | + - PRの内容について、質問を投げることができます |
| 79 | + - コード差分へのコメント経由で、該当行についてコンテキストを絞って質問することも可能です |
| 80 | +- UpdateChangelog |
| 81 | + - slash_command: `/update_changelog` |
| 82 | + - cli: `python -m pr_agent.cli --pr_url=<pr_url> update_changelog` |
| 83 | + - PRの内容に基づいて、`CHANGELOG.md`を生成または更新します |
| 84 | +- Help Docs |
| 85 | + - slash_command: `/help_docs "Your Question on docs"` |
| 86 | + - cli: `python -m pr_agent.cli --pr_url=<pr_url> help_docs` |
| 87 | + - リポジトリ内のドキュメント(デフォルトは`/docs`フォルダ、カスタマイズ可能)の内容について質問すると、AIが回答を生成します |
| 88 | +- Help |
| 89 | + - slash_command: `/help` |
| 90 | + - cli: `N/A` |
| 91 | + - PR-Agentで利用可能な機能についての一覧を取得できます |
| 92 | + |
| 93 | +# PR-Agent導入 |
| 94 | + |
| 95 | +PR-Agentの導入について紹介します。 |
| 96 | + |
| 97 | +基本的には[公式のドキュメント](https://qodo-merge-docs.qodo.ai/installation/)を見ながら進めればすぐに使い始められます。 |
| 98 | + |
| 99 | +GitLabへの導入の場合、大きく分けて次の2パターンでの構築が可能となっています。 |
| 100 | + |
| 101 | +- GitLab CI Pipelineへの導入 |
| 102 | +- GitLab webhook serverの構築 |
| 103 | + |
| 104 | +今回の検証では、GitLab webhook serverを構築し、Webhookを経由してPR-Agentを動作させる方法を選択しました。 |
| 105 | + |
| 106 | +こちらの手法を選ぶメリットは以下の通りです。 |
| 107 | + |
| 108 | +- 1つのWebhook Serverを、複数プロジェクトから呼び出すことが可能 |
| 109 | +- プロジェクトごとのCI Pipeline定義への修正を行わずに済む |
| 110 | + - PR-Agentの挙動は、後述する設定ファイルによってリポジトリごとにカスタマイズ可能です |
| 111 | + |
| 112 | +## GitLab Webhook Serverの構築 |
| 113 | + |
| 114 | +1. まずは、GitLab上で、操作対象のグループ、プロジェクトに対して「`Reporter`」ロールをもったユーザーを用意してください |
| 115 | +2. 1.で用意したユーザーにおいて、`api`操作権限を与えた`Personal Access Token`を生成します |
| 116 | +3. 任意のPython環境で、共有鍵を生成します (後の手順で使うため、メモしておいてください) |
| 117 | + |
| 118 | + ```sh |
| 119 | + SHARED_SECRET=$(python -c "import secrets; print(secrets.token_hex(10))") |
| 120 | + ``` |
| 121 | + |
| 122 | +4. [PR-Agentのリポジトリ](https://github.com/qodo-ai/pr-agent.git)をクローンします |
| 123 | + |
| 124 | + ```sh |
| 125 | + git clone https://github.com/qodo-ai/pr-agent.git |
| 126 | + ``` |
| 127 | + |
| 128 | +5. クローンしたリポジトリのルート直下に、以下のような`.env`ファイルを用意します |
| 129 | + |
| 130 | + ```toml |
| 131 | + # Config for gitlab |
| 132 | + CONFIG.GIT_PROVIDER=gitlab |
| 133 | + GITLAB.PERSONAL_ACCESS_TOKEN=<2.で生成したPAT> |
| 134 | + GITLAB.SHARED_SECRET=<3.で生成した共有鍵> |
| 135 | +
|
| 136 | + # セルフホスト版GitLabを利用している場合、そのURLを記載します。 |
| 137 | + # 初期値は "[https://gitlab.com](https://gitlab.com)" のため、SaaS版 (GitLab.com) を利用する場合は不要です。 |
| 138 | + GITLAB.URL=<your_gitlab_url> |
| 139 | +
|
| 140 | + # LLM API Key |
| 141 | + # モデル選択については、公式ドキュメント ( [https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/](https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/) ) を参照してください。 |
| 142 | + # 以下はGeminiを利用する場合の例です。 |
| 143 | + GOOGLE_AI_STUDIO.GEMINI_API_KEY=<your_token_here> |
| 144 | + ``` |
| 145 | + |
| 146 | +6. 以下のコマンドで、PR-AgentのWebhook用コンテナをビルドします |
| 147 | + |
| 148 | + ```sh |
| 149 | + docker build . -t gitlab_pr_agent --target gitlab_webhook -f docker/Dockerfile |
| 150 | + ``` |
| 151 | + |
| 152 | +7. ビルドしたコンテナは、任意のホスティング先で、GitLabからアクセス可能な状態にしておきます |
| 153 | + |
| 154 | +これで GitLab Webhook Server側のセットアップは完了です。 |
| 155 | + |
| 156 | +次に、GitLab側のプロジェクトでWebhook設定を行います。 |
| 157 | + |
| 158 | +以下のイベントが発生した際にWebhookをトリガーし、先ほど公開したWebhookサーバーが受け取れるように設定します。 |
| 159 | + |
| 160 | +- push |
| 161 | +- comment |
| 162 | +- merge request events |
| 163 | + |
| 164 | +## `.pr-agent.toml`(Configuration File)について |
| 165 | + |
| 166 | +OSS版のPR-Agentの各種挙動は、対象リポジトリのデフォルトブランチのルートに`.pr-agent.toml`という設定ファイルをアップロードすることで制御が可能です。 |
| 167 | + |
| 168 | +マネージドサービスの`Qodo Merge`では、Gitリポジトリ内のWikiページを利用したり、組織全体で設定を一元管理したりすることも可能なようです。詳しくは公式ドキュメントを参照してください。 |
| 169 | +[Configuration File - Qodo Merge (and open-source PR-Agent)](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/) |
| 170 | + |
| 171 | +実際に利用中の設定例を紹介します。 |
| 172 | + |
| 173 | +```toml |
| 174 | +# --*-- pr_agent configuration --*-- |
| 175 | +# see also: https://github.com/qodo-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml |
| 176 | +[config] |
| 177 | +git_provider = "gitlab" |
| 178 | +
|
| 179 | +#ref: See Available Model list https://github.com/qodo-ai/pr-agent/blob/main/pr_agent/algo/__init__.py |
| 180 | +model="gemini/gemini-2.0-flash" |
| 181 | +fallback_models=["gemini/gemini-1.5-flash"] |
| 182 | +
|
| 183 | +[pr_reviewer] # /review # |
| 184 | +extra_instructions = "Please use Japanese." |
| 185 | +
|
| 186 | +[pr_description] # /describe # |
| 187 | +generate_ai_title=true |
| 188 | +extra_instructions = "Please use Japanese." |
| 189 | +
|
| 190 | +[pr_code_suggestions] # /improve # |
| 191 | +extra_instructions = "Please use Japanese." |
| 192 | +
|
| 193 | +[pr_add_docs] # /add_docs # |
| 194 | +extra_instructions = "Please use Japanese." |
| 195 | +
|
| 196 | +[pr_update_changelog] # /update_changelog # |
| 197 | +extra_instructions = "Please use Japanese." |
| 198 | +``` |
| 199 | + |
| 200 | +以下、抜粋して説明します |
| 201 | + |
| 202 | +- `git_provider`は、`gitlab`を使うことを明示しています |
| 203 | +- `model`,`fallback_model`で利用するLLMを指定しています |
| 204 | + プライマリとセカンダリといった感じで使うモデルを記載します |
| 205 | + - 基本は`"gemini/gemini-2.0-flash"`を用いる |
| 206 | + - フォールバック先として`""gemini/gemini-1.5-flash"`を呼び出す |
| 207 | +- `generative_ai_title` |
| 208 | + - 有効にしていると、プルリクエストのタイトルを、AIによって自動生成してくれます |
| 209 | +- `extra_instructions` |
| 210 | + - LLMに対して、追加のプロンプトを入れることができます |
| 211 | + ここでは、各種操作について日本語で回答をしてほしいという意味を込めたプロンプトを入れています |
| 212 | +
|
| 213 | +# 実際の動作イメージ |
| 214 | +
|
| 215 | +PR-Agentとのやり取りのイメージの実例をご紹介します。 |
| 216 | +
|
| 217 | +今回は、以下のようなPythonの実装が含まれたブランチをPull Requestしたというストーリーを仮定します。 |
| 218 | +
|
| 219 | +一見、何の変哲もない、パラメータの値を結合してprintするだけのものに見えますが、**文字列の結合の部分に、改善できる隙をわざと残しています。** |
| 220 | +
|
| 221 | +そこをPR-Agentが、レビューできるかを検証してみます。 |
| 222 | +
|
| 223 | +```py main.py |
| 224 | +def greeting(word): |
| 225 | + #指摘してほしいポイント: 文字列結合には f-string や .format() の方が推奨されること |
| 226 | + print("Hello," + word) |
| 227 | +if __name__ == "__main__": |
| 228 | + greeting("World") |
| 229 | +``` |
| 230 | +
|
| 231 | +早速Pull Requestを出した直後が以下のイメージです。 |
| 232 | +
|
| 233 | +<img src="/images/20250417a/image.png" alt="" width="864" height="541" loading="lazy"> |
| 234 | +
|
| 235 | +<img src="/images/20250417a/image_2.png" alt="png" width="809" height="756" loading="lazy"> |
| 236 | +
|
| 237 | +早速PR-Agentによるレビューがされていることがわかりますね。 |
| 238 | +
|
| 239 | +これは、`.pr-agent.toml` 内の `pr_commands` で定義されたアクションが、新しいプルリクエストが開かれたことをトリガーとして自動実行されたためです。 |
| 240 | +
|
| 241 | +[GitLabに対してのpr_commandsのデフォルトの挙動](https://github.com/qodo-ai/pr-agent/blob/bc3ef4763dd77c180094dd38b90fa0352f6e62b0/pr_agent/settings/configuration.toml#L273C1-L276C2)は、Pull Requestの説明(`/describe`)と、レビューサマリ(`/review`)、コード改善案(`/improve`)の3つが処理されていることがわかります。 |
| 242 | +
|
| 243 | +**改善案では、見事、残しておいた隙を指摘してくれていますね!** |
| 244 | +
|
| 245 | +```ini configration.toml |
| 246 | +pr_commands = [ |
| 247 | + "/describe --pr_description.final_update_message=false", |
| 248 | + "/review", |
| 249 | + "/improve", |
| 250 | +] |
| 251 | +``` |
| 252 | +
|
| 253 | +続いて、コメントから`/ask`で、今回のコードの概要を聞いてみました。 |
| 254 | +
|
| 255 | +<img src="/images/20250417a/image_3.png" alt="" width="340" height="57" loading="lazy"> |
| 256 | +
|
| 257 | +回答がこちら。 |
| 258 | +
|
| 259 | +<img src="/images/20250417a/image_4.png" alt="" width="676" height="440" loading="lazy"> |
| 260 | +
|
| 261 | +コード規模が大きくなってくるとまた結果が変わってくるとは思いますが、小さいコンテキストでは完璧ですね。 |
| 262 | +
|
| 263 | +最後に、`/update_changelog`を実行した時のイメージを紹介します。 |
| 264 | +
|
| 265 | +<img src="/images/20250417a/image_5.png" alt="" width="627" height="230" loading="lazy"> |
| 266 | +
|
| 267 | +オプション次第ではpushまで行ってくれるようなので、履歴管理が捗りそうです。 |
| 268 | +
|
| 269 | +# さいごに |
| 270 | +
|
| 271 | +導入してみての所感は、Pull Request駆動のレビューに特化したOSSとして見れば、必要十分な機能が提供されているなという印象です。 |
| 272 | +
|
| 273 | +より多機能なAIサービスは世の中にたくさんあると思いますが、実業務での導入には依然としてセキュリティ要件や費用面など課題がつきまといます。 |
| 274 | +
|
| 275 | +その点、多様なLLMモデルに対応しつつ、オンプレミス環境にも比較的容易に構築できるPR-Agentは、有償サービスのような利便性とセキュリティ要件の両立を目指す場合に、有力な選択肢の一つになるでしょう。 |
| 276 | +
|
| 277 | +今後は、プロジェクト固有のコーディングルールなどをPR-Agentに反映させ、より実務に即したレビューが出力されるよう、さらに活用を模索していきたいと思います。 |
0 commit comments