各リポジトリに workflow を撒かずに Claude Code Action で PR レビューする Hub 型基盤
メグリでは会社全体で数百規模のリポジトリを運用しています。2025 年 10 月に GitHub Copilot のコードレビューを会社全体で標準化したのですが、当時は外部委託などの Copilot ライセンスを持たない方の PR には自動でレビューが付きませんでした。そのため、PR を出す人によって AI レビューの有無が変わる状態になっていました。
そこで、Claude Code Action を使って、対象リポジトリの PR を Hub リポジトリ側からレビューする仕組みを作りました。社内では mgre-ai-reviewer と呼んでいますが、この記事では一般化して Hub 型 AI レビュー基盤 と呼びます。
Claude Code Actions 自体の概要や、社内で Devin から Claude Code Actions へ移行した背景については、以前の記事「DevinからClaude Code Actionsへ移行するための検証」で書いています。本記事では、その上で外部リポジトリの PR を Hub からレビューする構成について記載します。
当初の動機は「Copilot ライセンスを持たないメンバーの PR にも AI レビューを付けたい」でした。ただ、2026 年 5 月時点では Organization 側の設定により、ライセンス未保有メンバーにも Copilot code review を適用できます。また、2026 年 6 月 1 日以降、GitHub-hosted runner 上で実行される Copilot code review runs は GitHub Actions minutes を消費する予定です。
そのため、Copilot の代替というよりも、レビュー観点・モデル選択・投稿形式・観測を自分たちで制御するための補完基盤という位置づけです。
1. 何を作ったか
作ったものは「PRのURLを渡すと、GitHub Actions で Claude Code Action を起動し、対象 PR にレビューを投稿する仕組み」です。
入口は 2 つあります。
- 手動: Hub Issue に PR URL と
@claudeを書く - 自動: GitHub Org Webhook を GAS Webhook で受け、対象 PR の Hub Issue を作る
Hub Issue は起動トリガーというだけでなく、レビュー依頼のキューや、使用モデルや判定理由を残すものとなっています。GitHub 上で検索でき、@claude メンションで Claude Code Action を起動できるため、初期版では外部 DB を持たずに Issue を実行単位として使っています。対象 PR が close や merge されたら、定期的に cron で Hub Issue も close します。
2. なぜ各リポジトリに workflow を撒かず Hub 型にしたか
最初に考えたのは、各リポジトリに AI レビュー用の workflow を置く案でした。数個のリポジトリならそれで十分ですが、数百規模になると次のような課題があります。
- レビュー観点を変えるたびに各リポジトリへの展開が必要になる
- トークンや権限の設定が散らばる
- モデル選択の条件を更新しづらい
- workflow の微妙な差分が増えて、あとから追えなくなる
Hub 型にすると、対象リポジトリ側に workflow を増やさず、レビュー観点・モデル選択・投稿形式・観測メタデータを 1 箇所に寄せられます。
コスト面でも Hub 型にした意味がありました。実運用では、PR のサイズや変更パスに応じて Haiku / Sonnet / Opus を切り替える 3 段モデルルーティングを入れています。軽微な変更には軽いモデル、通常の実装変更には標準モデル、認証周りの変更、大規模な変更、設定ファイルの変更などの慎重に見たい変更には強いモデルを使う、という考え方です。各リポジトリに workflow を撒いていると、この条件変更を横展開するだけで手間が増えます。Hub に寄せることで、コストとレビュー品質のバランスを中央で調整できます。
もちろん、Hub リポジトリの Actions から別リポジトリの PR を読むため、認証経路を別に用意する必要があります。
3. 全体構成
全体像は次のような構成となっています。
手動経路では、Hub Issue に対象 PR の URL と @claude を書きます。これで Claude Code Action が起動し、Issue 本文から PR URL を取り出してレビュー対象を決めます。
自動経路では、GitHub Org Webhook を GAS Webhook で受け、対象リポジトリ・対象ブランチ・作成者などを見て Hub Issue を作ります。初期版では Webhook 受信と Issue 作成だけに GAS を使いました。
Actions 側の処理は、大きく分けると次の流れです。
1. Hub Issue から対象 PR URL を取得する
2. 対象 PR の owner / repo / number を取り出す
3. 外部リポジトリ用トークンで PR metadata と diff を読む
4. Claude Code Action でレビュー内容を生成する
5. review body と inline comments を JSON に整形する
6. gh api で対象 PR に review として投稿する
この構成では、Claude Code Action にすべてを任せているわけではありません。責務は次のように分けています。
| 責務 | 担当 |
|---|---|
| Hub Issue から PR URL を取り出す | GitHub Actions / shell |
| 対象 PR の metadata / diff を取得する |
gh + EXTERNAL_GH_TOKEN
|
| レビュー観点に沿って指摘を生成する | Claude Code Action |
| review body / inline comments の JSON を作る | Claude Code Action + 後続 script |
| JSON の最低限の検証 | 後続 script |
| 対象 PR へ review 投稿 |
gh api + EXTERNAL_GH_TOKEN
|
対象リポジトリ側には AI レビュー用 workflow を置かず、Hub 側で「どの PR を読めるか」「誰が起動できるか」「どの形式で投稿するか」を制御します。
4. 実装で詰まったところ
外部リポジトリへアクセスする認証
Hub 型で最初に詰まったのは認証です。
GitHub Actions の GITHUB_TOKEN は、基本的に workflow が実行されているリポジトリ向けのトークンです。Hub リポジトリで Actions を動かしても、そのままでは対象リポジトリの PR diff を読んだり、対象 PR に review を投稿したりできません。
そこで、外部リポジトリ用の fine-grained PAT を EXTERNAL_GH_TOKEN として Actions secrets に登録しました。標準の GITHUB_TOKEN は上書きせず、外部リポジトリへ触るコマンドだけ明示的にトークンを切り替えます。
env:
EXTERNAL_GH_TOKEN: ${{ secrets.EXTERNAL_GH_TOKEN }}
GH_TOKEN="$EXTERNAL_GH_TOKEN" gh pr view "$PR_URL" --json title,author,files
GH_TOKEN="$EXTERNAL_GH_TOKEN" gh pr diff "$PR_URL"
CLAUDE.md にも、外部リポジトリへアクセスする場合は GH_TOKEN=$EXTERNAL_GH_TOKEN を前置する、と明記しました。AI に任せる処理ほど、暗黙の前提を減らしておいた方が事故りにくいです。
PAT を AI 実行環境で使う以上、被害範囲を絞ることは前提です。実運用では、少なくとも次の制約を入れています。
- fine-grained PAT を使い、対象 Organization / repository を限定する
- repository permissions は
Metadata: read、Pull requests: read/writeを基本にし、checkout やファイル取得が必要な場合だけContents: readを付ける - 有効期限を設定し、定期的にローテーションする
- Hub Issue を作成できるユーザー、または
@claudeで起動できるユーザーを制限する -
pull_request_targetのように外部入力と強い権限が混ざる構成にはしない - Actions log にトークン、diff 全文、API 応答を不用意に出さない
PAT は初期実装としては手軽ですが、権限集中のリスクがあります。長期運用では GitHub App 化して、対象リポジトリごとの短命な installation token を発行する構成に寄せたいと考えています。
gh api で PR review として投稿する
レビュー投稿は、通常の Issue comment ではなく PR review として出したかったので、GitHub REST API の Create a review for a pull request を使いました。
イメージは次のような JSON を作り、gh api で POST します。
{
"event": "COMMENT",
"body": "全体のレビューコメントです。",
"comments": [
{
"path": "app/src/main/java/example/Foo.kt",
"line": 42,
"side": "RIGHT",
"body": "この nullable 値は明示的に扱った方が安全です。"
}
]
}
GH_TOKEN="$EXTERNAL_GH_TOKEN" gh api \
"repos/$OWNER/$REPO/pulls/$PULL_NUMBER/reviews" \
--method POST \
--input review.json
この形にすると、総評と複数のインラインコメントが 1 つの review としてまとまります。人間のレビュアーが見る画面でも、単発コメントの羅列より追いやすくなります。
event は COMMENT にしています。AI による review で APPROVE や REQUEST_CHANGES まで出すと、人間のレビュー判断と混ざりやすいためです。
また、AI が生成した JSON をそのまま gh api に渡すのは危険です。実際には、path / line / side の組み合わせを差分情報と照合し、存在しないファイル、diff hunk 外の行、空の body、長すぎるコメントは投稿対象から外すか review body 側に逃がしています。差分上にない行へインラインコメントを付けようとすると、API 側で validation error になります。
差分外の指摘は review body に逃がす
GitHub の PR review comment は unified diff 上の位置に紐づきます。つまり、インラインコメントとして投稿できるのは基本的に差分上の行です。
AI にレビューさせると、差分外のファイルや既存実装との整合性を指摘したくなることがあります。例えば「兄弟クラスでも同じ override が必要」「別ファイルの同じ分岐にも修正が必要」のような指摘です。
ここを無理にインラインコメント化しようとすると、API 制約との戦いになります。初期版では、差分外の指摘は review body に書くルールにしました。
差分外の確認事項:
- `FooRepository.kt:128` に同じ null handling の分岐があります。
今回の修正と同じ方針に揃える必要がないか確認してください。
これは CLAUDE.md 側の出力ルールとして明示しています。実装で GitHub の制約を隠すより、AI の出力形式を制約に合わせる方がシンプルでした。
自己レビューのループを防ぐ
Hub 型にすると、Hub リポジトリ自身の PR をどう扱うかも考える必要があります。Hub 自身の PR を対象にすると、AI レビュー基盤の変更 PR が AI レビューを起動するループを作れてしまいます。
そこで、GAS Webhook 側で Hub リポジトリを除外し、Actions 側でも対象 PR URL を見て Hub 自身なら処理を止める二段構えにしました。
if [ "$OWNER/$REPO" = "$HUB_REPOSITORY" ]; then
echo "Skip self review: $OWNER/$REPO"
exit 0
fi
5. 最初から入れた小さな観測の仕組み
詳しいモデルルーティングの話は省きますが、どの PR でどのモデルを使ったか」は Hub Issue に残すようにしました。
例えば、次のような model marker コメントを Hub Issue に投稿します。
<!-- ai-review-model-marker -->
🤖 **使用モデル**: `sonnet`
- 対象 PR: https://github.com/example/mobile-app/pull/123
- additions+deletions: 87 (+62 / -25)
- changedFiles: 4
- 判定: 小さめの通常 PR、クリティカルパス検出なし
- run: https://github.com/example/hub/actions/runs/123456789
これだけでも、あとから Hub Issue を検索して「どのモデルがどのくらい使われているか」「強いモデルに上げすぎていないか」を確認できます。
最初から大きなダッシュボードを作る必要はありませんでした。まずは検索・集計できる粒度で実行結果を残すことを優先しています。
レビュー観点は CLAUDE.md に集約しています。例えば、Kotlin の !!、差分外指摘の書き方、セキュリティや認証まわりの確認方針などです。Hub に寄せたことで、このファイルを更新するだけで横断的に反映できます。
6. まとめ
Claude Code Action を使って外部リポジトリの PR をレビューする場合、単に workflow を書くだけでは終わりません。Hub リポジトリから対象 PR を読むための認証、PR review として投稿するための JSON 整形、差分外コメントの扱い、自己レビュー防止など、実装上の細かい論点があります。
今回の Hub 型 AI レビュー基盤では、対象リポジトリに workflow を撒かず、Hub 側にレビュー観点・モデル選択・投稿形式・観測メタデータを集約しました。その代わり、外部リポジトリ用の EXTERNAL_GH_TOKEN を明示的に使い分け、gh api で PR review を組み立てる実装にしています。
現時点では、これは完成形というより初期版です。Copilot code review を主軸にしつつ、細かく制御したいレビュー観点やモデル選択を Hub 側で補う位置付けで運用しています。実運用では 3 段モデルルーティングも入れていますが、GitHub App 化による PAT 依存解消など、まだ置き換えたい部分も残っています。
