🦔
PRの状態管理とGitHub Actionsによるレビュー催促の自動化を導入
背景
開発チームでは、次のような課題が発生していました。
-
PR の状態が分かりにくい
→ 「作業中なのか」「レビュー可能なのか」「修正対応中なのか」が見えない -
レビュー依頼が通知に埋もれる
→ 気づくまでに時間がかかり、レビューが後回しになる
このため、まず PR の状態管理ラベル を整備し、誰が見ても状況を把握できるようにしました。
その上で、レビュー待ちのPRをGitHub Actionsで定時に Slack へ通知する仕組みを導入しました。
1. PR の状態管理ラベル
PR の状態を正確に把握するために、次のラベルを運用しています。
ラベル | 使いどころ |
---|---|
WIP | 作業中。まだレビュー不要 |
レビュー待ち | 作業完了。レビュー依頼済み。このラベルが付いた PR が通知対象 |
修正中 | レビュー指摘の修正対応中 |
保留 | 外部要因や依存関係で一時停止(例: 上流マージ待ち) |
DO NOT MERGE | 検証用や一時的な PR。マージ禁止 |
効果
- 状態が明確になり、PR が「放置されているのか」「対応中なのか」がすぐ分かる
- レビュアーが優先して確認すべき PR を迷わず判断できる
2. GitHub Actionsでレビュー催促を自動化
ラベル運用を整備した後、「レビュー待ち」ラベルが付いた PR を対象に定時リマインダーを実行するようにしました。
特徴
-
平日 09:00 / 11:00 / 13:00 / 15:00(JST) に実行
-
祝日は自動スキップ(holidays-jp API 利用)
-
要リベース判定を自動化
- コンフリクトが発生している場合は ❌ (:no_entry_sign:)
- ベースブランチより遅れている場合は ⚠️ (:warning:)
-
レビュアーを Slack メンションに変換
- GitHub login → Slack ユーザー ID を JSON マッピングで対応
-
Slack へ分かりやすいリストを投稿
こんな感じです↓
実装例(サンプル)
.github/workflows/review-reminder.yml
name: PR Review Reminder
on:
schedule:
- cron: '0 0 * * 1-5' # JST 09:00
- cron: '0 2 * * 1-5' # JST 11:00
- cron: '0 4 * * 1-5' # JST 13:00
- cron: '0 6 * * 1-5' # JST 15:00
workflow_dispatch:
env:
LABEL_NAME: 'レビュー待ち'
jobs:
remind:
runs-on: ubuntu-latest
steps:
- name: Skip on Japan public holidays
id: holiday
run: |
TODAY=$(TZ=Asia/Tokyo date +%Y-%m-%d)
HOLIDAYS=$(curl -fsSL https://holidays-jp.github.io/api/v1/date.json)
if echo "$HOLIDAYS" | jq -e --arg d "$TODAY" 'has($d)' >/dev/null; then
echo "skip=true" >> $GITHUB_OUTPUT
else
echo "skip=false" >> $GITHUB_OUTPUT
fi
- name: Query PRs with label
id: prs
if: steps.holiday.outputs.skip != 'true'
uses: actions/github-script@v7
with:
script: |
const label = process.env.LABEL_NAME;
const mapping = JSON.parse(process.env.SLACK_USER_MAP || '{}');
const prs = await github.request('GET /repos/{owner}/{repo}/pulls', {
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
per_page: 100
});
const filtered = prs.data.filter(pr =>
(pr.labels || []).some(l => l.name === label)
);
const header = `👀 レビュー待ちのPR(${filtered.length}件)`;
if (filtered.length === 0) {
core.setOutput('body', '• 該当なし :tada:');
core.setOutput('header', header);
return;
}
const lines = await Promise.all(filtered.map(async (pr) => {
const prDetail = await github.request('GET /repos/{owner}/{repo}/pulls/{number}', {
owner: context.repo.owner,
repo: context.repo.repo,
number: pr.number
});
let rebaseMark = '';
const state = prDetail.data.mergeable_state;
if (state === 'dirty') {
rebaseMark = ' — :no_entry_sign: *要リベース*';
} else if (state === 'behind') {
rebaseMark = ' — :warning: *要リベース*';
}
const reviewers = (pr.requested_reviewers || []).map(r => {
return mapping[r.login] ? `<@${mapping[r.login]}>` : `@${r.login}`;
});
const firstLine = `• <${pr.html_url}|#${pr.number} ${pr.title}> (by @${pr.user.login}, base: ${pr.base.ref})${rebaseMark}`;
return reviewers.length > 0
? `${firstLine}\n> *レビュアー:* ${reviewers.join(' ')}`
: firstLine;
}));
core.setOutput('header', header);
core.setOutput('body', lines.join('\n'));
env:
SLACK_USER_MAP: ${{ secrets.SLACK_USER_MAP }}
- name: Post to Slack
if: steps.holiday.outputs.skip != 'true'
env:
SLACK_WEBHOOK_URL: ${{ secrets.PR_REVIEW_SLACK_WEBHOOK_URL }}
run: |
payload=$(jq -n \
--arg header "${{ steps.prs.outputs.header }}" \
--arg body "${{ steps.prs.outputs.body }}" \
'{
text: $header,
blocks: [
{ "type": "header", "text": { "type": "plain_text", "text": $header, "emoji": true } },
{ "type": "section", "text": { "type": "mrkdwn", "text": $body } }
]
}')
curl -s -X POST -H 'Content-Type: application/json' \
--data "$payload" \
"$SLACK_WEBHOOK_URL"
導入手順
-
ラベル運用をチームで合意
- 「レビュー待ち」ラベルが付いた PR が通知対象
- WIP / 修正中 / 保留 / DO NOT MERGE も合わせて導入
-
Slack Webhook を作成し、GitHub Secretsに保存
PR_REVIEW_SLACK_WEBHOOK_URL
-
GitHub login ⇔ Slack ユーザー ID マッピングを Secrets に保存
- Secrets 名:
SLACK_USER_MAP
{ "shimadama": "U0123456AA", "madamada": "U0123456BB" }
- Secrets 名:
-
上記 YAML を配置
- 以降は「レビュー待ち」ラベル付き PR が定時に通知される
効果
- レビュー開始までの時間が短縮
- PR が「放置」か「修正中」かがすぐ分かる
- 定時通知でチーム全体がレビュー対象を意識できる
まとめ
- ステップ 1: PR 状態管理ラベルを導入 → 状態が明確になり、認識のズレを防ぐ
- ステップ 2: GitHub Actions でレビュー催促を自動化 → レビュー遅延を防ぎ、開発をスムーズに進められる
おまけ:社内向け運用ドキュメント(テンプレ)
# PR運用
## 運用ルール
このチャンネルは GitHub 通知を集約し、進捗とレビュー依頼の見逃しを防ぎます。
/github subscribe <org>/<repo> issues pulls commits:* reviews comments
レビュー/コメント時は必ずメンション(@ユーザー名)。
SlackメンバーIDとGitHubアカウントは紐付け変換(漏れは随時補完)。
## PRリマインダー
通知時刻: 09:00 / 11:00 / 13:00 / 15:00(JST)
## PRのステータス管理ラベル
- WIP: まだレビュー不要
- レビュー待ち: レビュー依頼済み(リマインダー対象)
- 修正中: レビュー指摘への対応中
- 保留: 依存や外部要因で一時停止
- DO NOT MERGE: 検証用。絶対にマージしない
おまけ:なぜリベースが必要か
-
最新のベースブランチと差分が大きいPR
- コンフリクトやbehind状態を放置すると、マージ時に大規模な修正が必要になる
- レビュアーが見ている差分が古い状態のままになり、レビューの質が下がる
-
コミット履歴の汚染
-
git merge
を繰り返すと「マージコミット」が増加し、履歴がノイズで読みにくくなる -
git rebase
によって履歴をフラットに保つことで、誰がどの変更を入れたのかが明確になり、後からのトラブルシューティングが容易になる
-
-
チーム開発におけるメリット
- レビュアーが安心してレビューできる(最新のコードベースに対して確認できるため)
- CIの実行結果が正しく保証される(古いブランチ状態ではテストが通っていても、最新では落ちる可能性がある)
- 最終的に「マージ作業で詰まるリスク」を下げ、開発フローを滑らかに保てる
Discussion