PRレビューの品質と速度の改善をAIでなんとかしてみる
PRレビューの品質と速度の改善
- 開発時にPRを作成して複数人でレビューしてマージするというのが一般的な開発の進め方になっています。
- ただ、PRレビューには時間も手間もかかるためPRを作成してもなかなかレビューが終わらなかったり、レビューする人によって指摘の品質がまちまちだったりします。
- そこでAIにPRレビューをさせることで、自動でPRレビューをさせてPRレビューの品質と速度の改善を行います。
- AIがレビューすることによりLintチェックやフォーマッターのように人間がレビューする時点のコード品質を一定以上になるようにして人間のレビュアーの負担を軽減しつつ品質の均一化も狙っています。
GitHub Actions
GitHub ActionsとしてAIレビューのワークフローを組んで実装してみました。
また、今回はAIレビューだけでなくPRの修正量をチェックするワークフローを追加しています。
これはAIで入力できるデータ量には制限があるのと、要約などを行うのに量が多すぎるとレビューの精度が下がるためです。
人間がレビューする時にも大量の修正を含むPRレビューの効果は低いと言われているため、PRサイズの制限も導入しています。(Pull requestの理想的なサイズとその理由)
このワークフローを使用する際には、OpenAI APIのAPIKeyを取得してGithubのSecretsにOPENAI_API_KEYの変数として設定してください。
今回作成したGithubActionsのコードが下記です。
- .github/workflows/main.yml
name: On pull request
on:
pull_request:
types: [opened]
pull_request_review_comment:
types: [created]
issue_comment:
types: [created]
jobs:
limit-changes:
if: ${{ github.event_name == 'pull_request' }}
uses: ./.github/workflows/check-pr-changes-limit.yml
with:
limit: 400
extension: kt|java
code-review:
if: ${{ github.event_name == 'pull_request' || github.event_name == 'pull_request_review_comment' || github.event_name == 'issue_comment' }}
uses: ./.github/workflows/check-pr-ai-reviewer.yml
with:
openai_light_model: 'gpt-4'
openai_heavy_model: 'gpt-4'
language: 'ja-JP'
secrets:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- github/workflows/check-pr-ai-reviewer.yml
name: Code Review
permissions:
contents: read
pull-requests: write
on:
workflow_call:
inputs:
debug:
description: Debug mode
required: false
type: boolean
default: false
review_simple_changes:
description: Review simple changes
required: false
type: boolean
default: false
review_comment_lgtm:
description: Review comment LGTM
required: false
type: boolean
default: false
openai_light_model:
description: OpenAI light model to use
required: true
type: string
default: 'gpt-4'
openai_heavy_model:
description: OpenAI heavy model to use
required: true
type: string
default: 'gpt-4'
openai_timeout_ms:
description: OpenAI timeout in milliseconds
required: false
type: number
default: 900000
language:
description: Language of the review
required: true
type: string
default: 'ja-JP'
secrets:
GITHUB_TOKEN:
required: true
OPENAI_API_KEY:
required: true
concurrency:
group:
${{ github.repository }}-${{ github.event.number || github.head_ref ||
github.sha }}-${{ github.workflow }}-${{ github.event_name ==
'pull_request_review_comment' && 'pr_comment' || 'pr' }}
cancel-in-progress: ${{ github.event_name != 'pull_request_review_comment' }}
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: coderabbitai/ai-pr-reviewer@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
with:
debug: ${{ inputs.debug }}
review_simple_changes: ${{ inputs.review_simple_changes }}
review_comment_lgtm: ${{ inputs.review_comment_lgtm }}
openai_light_model: ${{ inputs.openai_light_model }}
openai_heavy_model: ${{ inputs.openai_heavy_model }}
openai_timeout_ms: ${{ inputs.openai_timeout_ms }}
language: ${{ inputs.language }}
system_message: |
あなたは @coderabbitai(別名 github-actions[bot])で、OpenAIによって訓練された言語モデルです。
些細なコードスタイルの問題や、コメント・ドキュメントの欠落についてはコメントしないでください。
summarize: |
次の内容でmarkdownフォーマットを使用して、最終的な回答を提供してください。
### 概要: 特定のファイルではなく、全体の変更に関する高レベルの要約を80語以内で。
### 詳細: ファイルとその要約のテーブル。スペースを節約するために、同様の変更を持つファイルを1行にまとめることが可能
summarize_release_notes: |
このプルリクエストのために、markdownフォーマットで簡潔なリリースノートを作成してください。
変更は以下のような分類で箇条書きにすること:
"New Feature", "Bug fix", "Documentation", "Refactor", "Style",
"Test", "Chore", "Revert"
例えば:
```
- New Feature: モーダルコンポーネントを追加
```
回答は50-100語以内にしてください。
- github/workflows/check-pr-changes-limit.yml
name: Limit number of changed lines
on:
workflow_call:
inputs:
limit:
description: Limit of changes
required: true
type: number
extension:
description: >
File extensions that you want to count changes.
Do not include "." before extensions.
Use regular expressions if you want to specify multiple extensions.
(example) kt|yml|gradle
required: true
type: string
exclude_dir:
description: >
Directories where you don't want to count changes.
Do not add "/" at the end of directory name.
type: string
required: false
env:
LIMIT: ${{ inputs.limit }}
EXT: ${{ inputs.extension }}
EXCLUDE: ${{ inputs.exclude_dir }}
jobs:
limit-changed-lines:
name: Limit changed lines in the pull request
runs-on: ubuntu-latest
steps:
name: Checkout base branch
uses: actions/checkout@v3
with:
ref: ${{ github.base_ref }}name: Setup base commit ID
run: echo "BASE=$(git rev-parse HEAD)" >> $GITHUB_ENVname: Checkout PR branch
uses: actions/checkout@v3name: Count number of changed lines and prepare comment
id: count_changes
run: |
changed=$(git diff $BASE –numstat \
| if [ -n "$EXCLUDE" ]; then grep -vE "^(\d+\s+)+\/?($EXCLUDE)\/"; else cat; fi \
| grep -E ".*.($EXT)$" \
| awk '{ additions+=$1; deletions+=$2 } END { print additions+deletions }')
echo "CHANGED=$changed" >> $GITHUB_ENVif [ $changed -gt $LIMIT ]; then message="**The number of changed lines exceeds the limit.**\n:hammer_and_wrench: LIMIT: $LIMIT, :fire: CHANGED: $changed" echo "MESSAGE=$message" >> $GITHUB_ENV echo "::error::Exceeds limit. (Limit: $LIMIT, Changed: $changed)" else message=":sparkles: Changes are within the limit :sparkles:" echo "MESSAGE=$message" >> $GITHUB_ENV fi
name: Post comment
uses: actions/github-script@v6
with:
script: |
const message = process.env.MESSAGE;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: message
});
Code Review Workflowの解説
このWorkflowは、プルリクエストの開始、プルリクエストレビューコメントの作成、およびイシューコメントの作成に反応します。
特に、GitHubのイベントに基づいて動作し、コードレビューのプロセスを自動化するために設計されています。
Githubの権限権限
このWorkflowには、コンテンツの読み取りとプルリクエストの書き込み権限が必要です。
トリガー
下記のイベントに反応して自動レビューが起動されます。
pull_request
: プルリクエストが開かれたときpull_request_review_comment
: プルリクエストのレビューコメントが作成されたときissue_comment
: イシューにコメントが作成されたとき
並行性
このWorkflowでは、concurrency
を設定しています。
これは、特定のグループ内で複数のジョブが同時に実行されるのを防ぎ、重複や競合を避けるためです。
また、プルリクエストレビューコメントイベントが発生した場合にのみ、進行中のジョブのキャンセルを避ける設定が施されています。
レビュー
このアクションは、AIによるコードレビューを提供し、以下の環境変数を使用します:
GITHUB_TOKEN
: GitHubから提供されるトークンを設定します。OPENAI_API_KEY
: OpenAIのAPIキーを設定します。
また、以下のオプションを設定しています:
: デバッグモードの無効化debug: false
: 単純な変更に対するレビューの無効化review_simple_changes: false
: LGTMのレビューコメントを無効化review_comment_lgtm: false
: 要約などに使用するOpenAIモデルの選択しています、コスト削減でgpt-3.5-turboを指定するのもありopenai_light_model: gpt-4
; コードレビューに使用するOpenAIモデルの選択していますopenai_heavy_model: gpt-4
:処理のタイムアウト時間openai_timeout_ms: 900000
: 生成する言語を設定していますlanguage: ja-JP
レビューの概要と詳細
AIは、レビューの概要と詳細なフィードバックを提供します。
これには、変更の高レベルの要約、ファイルごとの変更点の詳細、リリースノートの作成が含まれます。
このWorkflowは、開発プロセスを効率化し、より迅速かつ正確なフィードバックを提供することを目的としています。
実行結果
ワークフローをリポジトリに反映して、実際にPRを作成してAIコードレビューを試してみます。
AIレビューの設定で日本語指定していたのでレビューもしっかり日本語で生成されています。
コスト面
- コスト麺はだいたい1回レビューするのに100円程度かかりました。
- すべてをGPT4で処理するようにしているのと日本語で回答するようにしているので高めになっていると思います。
- この辺はチューニングの余地アリで、
としていたところをgpt-3-turboにするopenai_light_model: 'gpt-4'
- レビューを英語で生成する
- レビュー生成用のプロンプトを工夫してトークン数が減るようにする
- 上記の対応をすることでもう少しコスト削減はできると思います。
まとめ
AIによるコードレビューを導入して試してみました。
思ったより使えるなという印象で、フォーマッターやLintチェックではレビューし辛い内容のレビューが生成できていたかと思います。
GPT4を使用するので1回のレビューでもそれなりのコストがかかりますが、人間がレビューするよりは低いコストでレビューが行えました。
また、人間によるレビューではレビュアーによってレビューの品質はまちまちになりがちですが、フォーマッターやLintチェックのようにAIレビューであれば一定以上の品質を担保しやすくなります。
AIレビュー用にPRサイズ制限もしているので最終的に人間がレビューする際も見やすいサイズのPRになります。
gpt-4のコストがさらに安くなればもっと気軽にバンバン使いたいとこです。
参考
- githubのPR行数制限フローを作ってみた
- Pull requestの理想的なサイズとその理由
- GitHub Actionsでプルリクエストの変更行数を制限する #GitHubActions – Qiita
- githubのPR行数制限フローを作ってみた
- check-PR-update-rows/.github/workflows/check_update_rows.yml at main · eno-conan/check-PR-update-rows · GitHub
- PR-Agent を使って Pull Request をAIレビューしてみた。(日本語対応もしてみた) – LayerX エンジニアブログ
- ChatGPT CodeReviewでコードレビューを自動化してみた|LLMラボ
- ChatGPT APIとGitHub ActionsでPull RequestのAI Code Reviewをつくってみた
- ChatGPT にプルリクエストのタイトルをレビューしてもらう – TENTIALのテックブログ
- 【ChatGpt】CodeRabbitとGithubActionsを連携してプルリクエストのレビューと要約を自動生成する
- CodeRabbit: AI-powered Code Reviews
- もう初回コードレビューはAIに任せる時代になった – CodeRabbit –