はじめに
GitHub ActionsにKiro CLIを組み込み、Pull Requestに対するコードレビューを自動化してみました。
今回やったことは、develop ブランチにPRが作成・更新されたらKiro CLIでレビューし、その結果をPRコメントに投稿するというものです。
ただ、PRの変更量が大きいとAIに渡す情報量も増えるため、レビュー前に変更量をチェックして、一定サイズを超えたPRはレビューをスキップするようにしました。
今回の構成はこんな感じです。
Pull Request
│
│ developへのPR
▼
GitHub Actions
│
▼
Self-hosted Runner
│
├── PR変更量をチェック
│
├── 上限以内
│ │
│ ▼
│ Kiro CLI
│ │
│ ▼
│ レビュー結果
│ │
│ ▼
│ PRコメント
│
└── 上限超過
│
▼
レビューSkip
│
▼
Authorへ通知
Kiro CLIをSelf-hosted Runnerで利用する
今回はGitHub-hosted Runnerではなく、Self-hosted Runnerを利用しました。
Kiro CLIはSelf-hosted Runner側であらかじめログインしておきます。
kiro-cli login --use-device-flow
ログイン後、以下で認証状態を確認できます。
kiro-cli whoami
GitHub Actionsからは、Runner上にインストールしてあるKiro CLIをそのまま実行します。
今回の構成ではKiroのAPI Keyは使用していません。
GitHub ActionsのSecretsにAPI Keyを登録してWorkflowから渡すのではなく、Self-hosted Runner側でKiro CLIにログインした状態を利用しています。
そのため、Workflow自体にKiroのAPI Keyを記述する必要がありません。
ただし、この方式ではRunner上に認証状態を保持することになるため、Self-hosted Runner自体のアクセス制御や管理は必要になります。
GitHub Actionsのトリガー
まず、develop ブランチに対するPull Requestをトリガーにします。
name: Kiro Code Review
on:
pull_request:
types:
- opened
- synchronize
- reopened
branches:
- develop
permissions:
contents: read
pull-requests: write
jobs:
review:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
opened だけではなく synchronize も指定しています。
これでPRに追加コミットがpushされた場合も再度レビューが実行されます。
PRの変更量に上限を設定する
AIレビューを入れるにあたって、気になったのがコストです。
PRの変更量が大きくなるほどAIに渡すコンテキストも増えるため、レビューにかかるコストや時間も増えていきます。
そこで、Kiro CLIを実行する前にPRの変更量をチェックすることにしました。
上限値はGitHub Actions Variablesで管理します。
例えば、
KIRO_REVIEW_MAX_LINES=1000
としておきます。
Workflowからは、
${{ vars.KIRO_REVIEW_MAX_LINES }}
で取得できます。
上限値をWorkflowに直接書かないことで、レビュー対象のサイズを変更したい場合もActions Variablesの値を変更するだけで済みます。
PRの変更行数を取得する
今回は git diff --numstat を利用して、追加行数と削除行数を取得します。
- name: Get diff statistics
run: |
git fetch origin \
${{ github.event.pull_request.base.ref }} \
${{ github.event.pull_request.head.ref }}
git diff \
--numstat \
origin/${{ github.event.pull_request.base.ref }}...HEAD \
> /tmp/numstat
numstat にはファイルごとの追加行数と削除行数が出てくるので、それを集計します。
ADDED_LINES=$(awk '{ added += $1 } END { print added+0 }' /tmp/numstat)
DELETED_LINES=$(awk '{ deleted += $2 } END { print deleted+0 }' /tmp/numstat)
TOTAL_CHANGED_LINES=$((ADDED_LINES + DELETED_LINES))
echo "Added lines : ${ADDED_LINES}"
echo "Deleted lines : ${DELETED_LINES}"
echo "Changed lines : ${TOTAL_CHANGED_LINES}"
今回は、
追加行数 + 削除行数
を変更量として扱っています。
変更量が上限を超えたらレビューをSkipする
取得した変更量とActions Variablesに設定した上限値を比較します。
- name: Check review size
id: size-check
env:
MAX_LINES: ${{ vars.KIRO_REVIEW_MAX_LINES }}
run: |
ADDED_LINES=$(awk '{ added += $1 } END { print added+0 }' /tmp/numstat)
DELETED_LINES=$(awk '{ deleted += $2 } END { print deleted+0 }' /tmp/numstat)
TOTAL_CHANGED_LINES=$((ADDED_LINES + DELETED_LINES))
echo "added=${ADDED_LINES}" >> "$GITHUB_OUTPUT"
echo "deleted=${DELETED_LINES}" >> "$GITHUB_OUTPUT"
echo "total=${TOTAL_CHANGED_LINES}" >> "$GITHUB_OUTPUT"
if [ "$TOTAL_CHANGED_LINES" -gt "$MAX_LINES" ]; then
echo "review=false" >> "$GITHUB_OUTPUT"
else
echo "review=true" >> "$GITHUB_OUTPUT"
fi
例えば上限を1000行にしている場合、
500行
↓
Kiro CLIでレビュー
1000行
↓
Kiro CLIでレビュー
1500行
↓
レビューSkip
となります。
サイズオーバー時はAuthorへ通知する
レビューをSkipするだけだと、PRを作成した側からすると「なぜレビューされなかったのか」が分かりません。
そこで、サイズ上限を超えた場合はPRコメントを投稿するようにしました。
- name: Notify review skipped
if: steps.size-check.outputs.review == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr comment \
${{ github.event.pull_request.number }} \
--body "## 🤖 Kiro AI Review
レビュー対象の変更量が設定された上限値を超えたため、AIコードレビューをスキップしました。
- 変更行数: ${{ steps.size-check.outputs.total }}
- 上限値: ${{ vars.KIRO_REVIEW_MAX_LINES }}
PRを分割して再度Pull Requestを作成してください。"
これで、レビューされなかった理由をPR上で確認できます。
Kiro CLIでレビューする
変更量が上限以内の場合だけKiro CLIを実行します。
- name: Run Kiro Code Review
if: steps.size-check.outputs.review == 'true'
run: |
kiro-cli chat \
--no-interactive \
--agent code-reviewer \
"このPull Requestの変更内容をレビューしてください。
以下の観点でレビューしてください。
- セキュリティ
- バグ・ロジックエラー
- パフォーマンス
- 可読性・保守性
- テスト
重要度の低い指摘や単なる好みの問題は指摘しないでください。
" \
> /tmp/kiro-review.md
レビュー結果は一度ファイルに保存しています。
こうしておくことで、後続のステップでそのままGitHubのPRコメントとして利用できます。
レビュー内容
レビューでは、単純に「コードレビューしてください」とするのではなく、レビュー観点をある程度固定しました。
セキュリティ
- 認証・認可の不備
- SQL Injectionなどのインジェクション
- XSS
- CSRF
- SSRF
- 入力値検証
- 秘密情報のハードコード
- ログへの機密情報出力
- 不適切な権限設定
バグ・ロジック
- 明らかなロジックエラー
- null / undefinedの考慮漏れ
- 境界値の考慮漏れ
- 例外処理の不足
- エラー時に不正な状態になる可能性
- 非同期処理や競合状態
パフォーマンス
- 不要なDBアクセス
- N+1
- 不要なAPIリクエスト
- 大量データ処理
- 不要なループ
- メモリ使用量
- 明らかに改善可能な処理
可読性・保守性
- 複雑すぎる処理
- 重複コード
- 責務の過剰な集中
- 命名
- SOLID
- DRY
- KISS
- YAGNI
ただし、単なる個人の好みやスタイルの違いは指摘しないようにしています。
テスト
- 新しく追加されたロジックのテスト不足
- エッジケース
- 異常系
- 既存機能への影響
また、すべての変更に対して細かく指摘させるのではなく、「実際に修正する価値があるもの」を中心にレビューさせるようにしています。
Kiroのカスタムエージェント
レビュー用のプロンプトはWorkflowに直接書き込むのではなく、Kiroのカスタムエージェントとして管理しています。
例えば、
.kiro/
└── agents/
├── code-reviewer.json
└── prompts/
└── code-review.md
という構成です。
レビューのルールをWorkflowから切り離しておくことで、レビュー内容を変更したい場合にもActionsのWorkflowを修正する必要がありません。
また、プロジェクトの開発ルールなどを追加したくなった場合も、レビュー用のプロンプト側で管理できます。
レビュー結果をPRコメントへ投稿する
Kiro CLIの実行が終わったら、結果をPRコメントに投稿します。
- name: Post Kiro Review
if: steps.size-check.outputs.review == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
{
echo "## 🤖 Kiro AI Review"
echo ""
cat /tmp/kiro-review.md
} > /tmp/pr-comment.md
gh pr comment \
${{ github.event.pull_request.number }} \
--body-file /tmp/pr-comment.md
これでPR上にKiro CLIによるレビュー結果が表示されます。
イメージとしては、
## 🤖 Kiro AI Review
### Security
問題なし
### Bug
[High]
xxx.phpのxxx処理について...
### Performance
問題なし
### Maintainability
[Low]
...
のような形になります。
GitHub Actionsの全体
ここまでの内容をまとめると、Workflowは以下のようになります。
name: Kiro Code Review
on:
pull_request:
types:
- opened
- synchronize
- reopened
branches:
- develop
permissions:
contents: read
pull-requests: write
jobs:
review:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get diff statistics
run: |
git fetch origin \
${{ github.event.pull_request.base.ref }} \
${{ github.event.pull_request.head.ref }}
git diff \
--numstat \
origin/${{ github.event.pull_request.base.ref }}...HEAD \
> /tmp/numstat
- name: Check review size
id: size-check
env:
MAX_LINES: ${{ vars.KIRO_REVIEW_MAX_LINES }}
run: |
ADDED_LINES=$(awk '{ added += $1 } END { print added+0 }' /tmp/numstat)
DELETED_LINES=$(awk '{ deleted += $2 } END { print deleted+0 }' /tmp/numstat)
TOTAL_CHANGED_LINES=$((ADDED_LINES + DELETED_LINES))
echo "added=${ADDED_LINES}" >> "$GITHUB_OUTPUT"
echo "deleted=${DELETED_LINES}" >> "$GITHUB_OUTPUT"
echo "total=${TOTAL_CHANGED_LINES}" >> "$GITHUB_OUTPUT"
if [ "$TOTAL_CHANGED_LINES" -gt "$MAX_LINES" ]; then
echo "review=false" >> "$GITHUB_OUTPUT"
else
echo "review=true" >> "$GITHUB_OUTPUT"
fi
- name: Notify review skipped
if: steps.size-check.outputs.review == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr comment \
${{ github.event.pull_request.number }} \
--body "## 🤖 Kiro AI Review
レビュー対象の変更量が設定された上限値を超えたため、AIコードレビューをスキップしました。
- 変更行数: ${{ steps.size-check.outputs.total }}
- 上限値: ${{ vars.KIRO_REVIEW_MAX_LINES }}
PRを分割して再度Pull Requestを作成してください。"
- name: Run Kiro Code Review
if: steps.size-check.outputs.review == 'true'
run: |
kiro-cli chat \
--no-interactive \
--agent code-reviewer \
"このPull Requestの変更内容をレビューしてください。
以下の観点でレビューしてください。
- セキュリティ
- バグ・ロジックエラー
- パフォーマンス
- 可読性・保守性
- テスト
重要度の低い指摘や単なる好みの問題は指摘しないでください。
" \
> /tmp/kiro-review.md
- name: Post Kiro Review
if: steps.size-check.outputs.review == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
{
echo "## 🤖 Kiro AI Review"
echo ""
cat /tmp/kiro-review.md
} > /tmp/pr-comment.md
gh pr comment \
${{ github.event.pull_request.number }} \
--body-file /tmp/pr-comment.md
変更量に上限を設けた理由
今回、サイズ上限を入れたのは、単純に「大きなPRをレビューしたくない」という理由ではありません。
PRが大きくなるほどAIに渡すコンテキストも増えるため、レビューにかかるコストや時間も増えます。
また、AIレビュー以前に、人間がレビューする場合でも大きなPRはレビューしづらくなります。
そのため、
小さなPR
↓
Kiro CLIでレビュー
大きなPR
↓
PRを分割
という運用にしました。
AIのコストを抑えながら、PR自体も小さく保ちやすくなります。
API Keyを使わない構成にした理由
今回はKiro CLIのAPI KeyをGitHub Actionsへ渡す方式ではなく、Self-hosted Runnerでログイン済みのKiro CLIを利用しました。
そのため、Workflow内にKiroのAPI Keyを設定する必要がありません。
構成としては、
Self-hosted Runner
│
├── Kiro CLI
│
└── ログイン済み
│
▼
GitHub Actionsから実行
となります。
一方で、Self-hosted Runnerを使う以上、Runnerの管理は必要です。
特に、
- Runnerへのアクセス権限
- 認証状態の管理
- Runnerのディスク
- ログ
- GitHub Actionsから実行される処理
などは考慮する必要があります。
やってみて
実際にPRレビューへ組み込んでみると、毎回人間がゼロから変更内容を確認する前に、ある程度の問題を拾ってくれるのは便利でした。
特に、
- 明らかな実装ミス
- エラーハンドリング漏れ
- テスト不足
- セキュリティ上の問題
- パフォーマンス上の気になる実装
あたりを先に確認してもらえるので、人間のレビューでは設計や仕様など、より重要な部分に時間を使いやすくなります。
一方で、AIの指摘が常に正しいわけではないので、最終的な判断は人間が行う前提です。
今回の仕組みでは「AIにレビューを任せる」というより、
PR作成
↓
Kiroで一次レビュー
↓
指摘を確認
↓
人間によるレビュー
という使い方をしています。
今後やりたいこと
現状でも基本的なレビューはできますが、もう少し改善できそうなところがあります。
- 変更ファイル数にも上限を設定する
- 自動生成ファイルをレビュー対象から除外する
- 特定ディレクトリだけレビューする
- 同じPRへのコメント重複を防ぐ
- GitHubのReview Commentとして行単位で指摘する
- Severityごとに指摘を分類する
- プロジェクト固有のルールをレビューへ反映する
- レビュー結果をメトリクスとして記録する
特にGitHubのReview Commentとして、該当コードの行に直接コメントできるようにすると、もう少し使いやすくなりそうです。
まとめ
今回はKiro CLIをGitHub Actionsに組み込み、Pull Requestのコードレビューを自動化しました。
最終的な流れは、
Pull Request
↓
GitHub Actions
↓
Self-hosted Runner
↓
変更量チェック
│
├── 上限超過
│ ↓
│ レビューSkip
│ ↓
│ Authorへ通知
│
└── 上限以内
↓
Kiro CLI
↓
コードレビュー
↓
PRコメント
という形です。
今回の実装では、
- Kiro CLI
- GitHub Actions
- Self-hosted Runner
- PR変更量によるコスト制御
- GitHub Actions Variables
- PRコメントへの自動投稿
を組み合わせています。
AIレビューを人間のレビューの代わりにするのではなく、一次レビューとして組み込むことで、レビューの負担を少し減らすことができました。
Kiro CLIを普段の開発フローに組み込みたい場合は、こういった形も一つの選択肢になると思います。