check-pr について
check-pr は、GitHub の PR、GitLab の MR、Perforce の shelved changelist を確認するレビュー用スキルです。チェック結果、説明、コメントを調べ、Greptile の結果が現在のリビジョンに対応するか検証し、指摘への対応を支援します。
主な機能
- 01GitHub、GitLab、Perforce の識別
- 02チェック結果、説明、コメントの確認
- 03保留中のチェックの完了待ち
- 04Greptile の結果と現在のリビジョンの照合
- 05問題の分類と解決支援
活用シーン
- 01マージ前の PR または MR の課題整理
- 02Greptile が最新コミットをレビューしたか確認
- 03Perforce shelved changelist のレビュー指摘確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ paperclipai/ paperclip --skill check-prインストール後、Claude Code で/check-prを入力して読み込まれたか確認します。
同梱ファイルreferences/gitlab-api.mdreferences/graphql-queries.md
詳細
PR の確認
プルリクエスト(GitHub)、マージリクエスト(GitLab)、またはシェルブ済みチェンジリスト(Perforce)を分析し、レビューコメント、ステータスチェック、説明の完全性を確認して、見つかった問題への対処を支援します。
入力
- PR/MR/CL 番号(任意):指定されていない場合は、現在のブランチの PR/MR、または p4 のデフォルトの保留中チェンジリストを検出します。
手順
0. プラットフォームを検出する
まず、.p4config ファイル、または P4CLIENT/P4PORT 環境変数を確認して、ユーザーが Perforce のデポで作業しているかを調べます。
# Check for Perforce environment
if p4 info >/dev/null 2>&1; then
VCS="perforce"
else
# Fall back to git remote detection
REMOTE_URL=$(git remote get-url origin)
if echo "$REMOTE_URL" | grep -qi "gitlab"; then
VCS="gitlab"
else
VCS="github"
fi
fi
ホスト名に「gitlab」が含まれないセルフホスト型 GitLab インスタンスの場合、入力として --vcs gitlab を渡すことで上書きできます。Perforce の場合は、--vcs perforce を渡すことで上書きできます。
1. PR/MR/CL を特定する
番号が指定されている場合は、その番号を使用します。指定されていない場合は、次の方法で検出します。
GitHub:
gh pr view --json number,headRefName,headRefOid -q '{number: .number, branch: .headRefName, head: .headRefOid}'
GitLab:
glab mr view --output json | jq '.iid'
Perforce:
# List pending changelists for the current user/client
p4 changes -s pending -u $P4USER -c $P4CLIENT
プラットフォームごとの主なフィールドの違い:
- GitHub:
number、headRefName、headRefOid - GitLab:
iid、source_branch、sha - Perforce:チェンジリスト番号(CL)、レビュー中の CL の
shelvedファイル
2. PR/MR/CL の詳細を取得する
GitHub:
gh pr view <PR_NUMBER> --json title,body,state,reviews,comments,headRefName,headRefOid,statusCheckRollup
OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
gh api "repos/$OWNER_REPO/pulls/<PR_NUMBER>/comments"
gh api --paginate "repos/$OWNER_REPO/issues/<PR_NUMBER>/comments?per_page=100"
GitHub の PR はイシューでもあるため、一般的な PR コメントはイシューコメントのエンドポイントにあります。Greptile はレビューサイクルごとに新しいレビューやコメントを作成するのではなく、単一の一般的な PR コメントを編集する場合があります。PR に問題がないと判断する前に、updated_at に基づいて最新の Greptile 作成の一般コメントを必ず確認してください。「Prompt to fix all with AI」セクションも確認します。
GitLab:
glab mr view <MR_IID> --output json
# Fetch discussions (inline diff comments are type "DiffNote"; general comments have null type)
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions"
GitLab では、必要に応じてディスカッションをページネーションして取得します(?per_page=100&page=N を追加します)。
Perforce:
# Get changelist description, files, and status
p4 describe -s <CL_NUMBER>
# Get shelved files (for in-review CLs)
p4 describe -S <CL_NUMBER>
# Get the diff of the shelved changelist
p4 diff2 //...@=<CL_NUMBER> //...@=<CL_NUMBER>
# List review comments (if using p4 review workflow)
p4 review -c <CL_NUMBER>
Perforce CL の主なフィールド:
Change:チェンジリスト番号Status:pending、submitted、shelvedDescription:CL の説明/コミットメッセージFiles:CL 内のファイル一覧
3. 保留中のチェックが完了するまで待つ
分析する前に、すべてのステータスチェックが完了していることを確認します。チェックが PENDING または IN_PROGRESS(GitHub)、あるいは running または pending(GitLab)の場合は、すべてのチェックが終端状態になるまで30秒ごとにポーリングします。
GitHub: gh pr view から statusCheckRollup をポーリングします。
GitLab:
glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines"
パイプラインのステータス:running、pending、success、failed、canceled、skipped。running または pending のパイプラインがなくなるまでポーリングします。
Perforce: Perforce には組み込みの CI チェック機能はありません。チームがレビュー用ツール(Swarm など)や、シェルブイベントによって実行される外部 CI を利用している場合は、該当するシステムを確認します。それ以外の場合は、すぐに分析に進みます。
4. 現在の head に対する最新の Greptile レビューを必須にする
GitHub の PR では、既存の Greptile レビュー、コメント、または要約が、PR の現在の headRefOid と正確に一致していない限り、最新のものとして扱わないでください。これは、既存の PR に新しいコミットをプッシュした後に特に重要です。PR に Greptile のコメントや以前のレビューが残っていても、古いコミットに対する Greptile レビューは古いものです。
Greptile のチェックを行う直前に、現在の head SHA を取得してください。
HEAD_SHA=$(gh pr view <PR_NUMBER> --json headRefOid -q .headRefOid)
次に、そのコミットのチェック実行を調べ、完了済みの Greptile 実行があることを必須にしてください。
OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
GREPTILE_CHECKS=$(gh api "repos/$OWNER_REPO/commits/$HEAD_SHA/check-runs?per_page=100" \
--jq '[.check_runs[] | select(.name | test("greptile"; "i"))]')
# A run only counts as a valid fresh pass when it has completed AND concluded cleanly.
# GitHub check-run conclusions: success, neutral, skipped, failure, timed_out,
# cancelled, action_required, stale. Treat success/neutral as clean;
# everything else (especially failure and action_required) must block.
FRESH_GREPTILE_COMPLETED=$(echo "$GREPTILE_CHECKS" \
| jq '[.[] | select(.status == "completed")] | length')
FRESH_GREPTILE_CLEAN=$(echo "$GREPTILE_CHECKS" \
| jq '[.[] | select(.status == "completed" and (.conclusion | IN("success","neutral")))] | length')
FRESH_GREPTILE_BLOCKING=$(echo "$GREPTILE_CHECKS" \
| jq '[.[] | select(.status == "completed" and ((.conclusion | IN("success","neutral")) | not))] | length')
if [ "$FRESH_GREPTILE_COMPLETED" = "0" ]; then
echo "Blocked: no completed Greptile review/check is tied to current PR head $HEAD_SHA."
echo "Request a fresh Greptile review against this head before marking the PR check done."
echo "Suggested trigger: gh pr comment <PR_NUMBER> --body \"@greptile review\""
exit 1
fi
if [ "$FRESH_GREPTILE_BLOCKING" != "0" ] || [ "$FRESH_GREPTILE_CLEAN" = "0" ]; then
echo "Blocked: Greptile completed on head $HEAD_SHA but did not conclude clean"
echo "(conclusion was failure/action_required/timed_out/cancelled/stale, or no clean run exists)."
echo "Address the findings, push, and re-run Greptile until it concludes success/clean on the new head."
exit 1
fi
現在の head に対する Greptile チェックが存在するものの、まだ保留中または進行中の場合は、古いレビュー情報をもとに先へ進まず、greploop で使用されているのと同じポーリングパターンで待機してください。妥当な時間待っても現在の head に対する Greptile チェックが表示されない場合は、HEAD_SHA に対する最新の Greptile レビューがないため PR がブロックされていると報告し、停止してください。現在の head SHA と関連付けられない PR コメント、PR レビュー、または Greptile の要約をもとに、チェックを完了扱いにしないでください。
Greptile と連携している GitLab 環境では、MR の現在の head SHA に対して同じ最新性ルールを適用してください。
# 1. Get the MR's current head SHA
MR_SHA=$(glab mr view <MR_IID> --output json | jq -r '.sha // .diff_refs.head_sha')
# 2. Find the latest pipeline for that EXACT sha, then the Greptile job within it.
LATEST_PIPELINE_ID=$(glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines" \
| jq -r --arg sha "$MR_SHA" '[.[] | select(.sha == $sha)] | sort_by(.id) | last | .id // empty')
if [ -n "$LATEST_PIPELINE_ID" ]; then
GREPTILE_JOBS=$(glab api "projects/:fullpath/pipelines/$LATEST_PIPELINE_ID/jobs" \
| jq --arg sha "$MR_SHA" '[.[] | select(.name | test("greptile"; "i"))
| {name, status, pipeline_sha: $sha}]')
else
GREPTILE_JOBS='[]'
fi
GREPTILE_JOB_SUCCESS=$(echo "$GREPTILE_JOBS" \
| jq '[.[] | select(.status == "success")] | length')
GREPTILE_JOB_BLOCKING=$(echo "$GREPTILE_JOBS" \
| jq '[.[] | select(.status != "success")] | length')
# 3. If Greptile integrates via MR notes instead of a CI job, require the newest
# Greptile note to reference the current head sha and report a clean review.
GREPTILE_NOTES=$(glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100" \
| jq --arg sha "$MR_SHA" '[.[].notes[]
| select(.author.username | test("greptile"; "i"))]
| sort_by(.updated_at // .created_at)')
GREPTILE_NOTE_CLEAN=$(echo "$GREPTILE_NOTES" \
| jq --arg sha "$MR_SHA" 'if length == 0 then 0
elif ((last.body // "") | contains($sha) and test("Confidence Score:[[:space:]]*5/5|Confidence:[[:space:]]*5/5|\\b5/5\\b"; "i") and (test("Prompt To Fix|blocking issue|failed|action required"; "i") | not)) then 1
else 0 end')
if [ "$GREPTILE_JOB_SUCCESS" = "0" ] && [ "$GREPTILE_NOTE_CLEAN" = "0" ]; then
echo "Blocked: no successful Greptile job or completed-clean current-head Greptile note is tied to MR head $MR_SHA."
exit 1
fi
if [ "$GREPTILE_JOB_BLOCKING" != "0" ]; then
echo "Blocked: at least one Greptile job for MR head $MR_SHA did not succeed."
exit 1
fi
MR_SHA に対して、(a)Greptile のジョブまたはノートがまったくない(欠落)、(b)最新の Greptile ジョブ/ノートが別の sha に紐付いている(古い)、または(c)Greptile ジョブのステータスが success でない場合は、完了をブロックしてください。別の SHA に対する Greptile の完了済み結果は古いため、完了をブロックしなければなりません。
Greptile と連携している Perforce 環境では、CL の現在の保留リビジョン識別子と、それに紐付いた Greptile webhook/レビュー成果物を使って同じルールを適用してください。以前の保留リビジョンに対する Greptile の結果は古いため、完了をブロックしなければなりません。
5. PR/MR を分析する
すべてのチェックが完了したら、次の項目を評価してください。
A. ステータスチェック
- すべての CI チェックに合格していますか?
- 失敗しているものがある場合は、該当するチェックと失敗理由を特定してください。
B. PR/MR の説明
- 説明は十分で、チームの規約に従っていますか?
- 必須セクションはすべて記入されていますか?
- 更新が必要な TODO やプレースホルダーはありますか?
C. レビューコメント
- 対応が必要なインラインのコードレビューコメント
- ボットのレビューコメント(例:GitHub の
greptile-apps[bot]、GitLab の Greptile ボットユーザー、リンターなど)を確認してください。 - 人間のレビュアーによるコメント
- Perforce:
p4 reviewまたは外部レビュー ツールからのレビューコメント
D. 全般的なコメント
- PR/MR のディスカッションコメント
- GitHub では、issue のコメントエンドポイントを確認し、
updated_atを使って編集されたボットコメントも見つけてください。Greptile が最後に編集した要約には、新しいインラインコメントがなくても対応が必要な項目が含まれている場合があります。 - ボットのコメント(デプロイプレビューなど)。通常は参考情報です。
- Perforce: CL の説明には、明確な概要、対象ファイルの理由、テストに関するメモを含めてください。
6. 問題を分類する
見つかった問題ごとに、次のように分類してください。
| カテゴリー | 意味 |
|---|---|
| 対応が必要 | 必要なコード変更、テストの改善、または修正 |
| 参考情報 | 変更を必要としない確認メモ、質問、または FYI |
| 対応済み | 後続のコミットによって解決されたと思われる問題 |
7. 調査結果を報告する
概要表を提示してください。
| 項目 | 問題 | ステータス | 必要な対応 |
|---|---|---|---|
| ステータスチェック | CI ビルドが失敗 | 失敗 | src/api.ts の型エラーを修正 |
| レビュー | 「null チェックを追加」 - @reviewer | 対応が必要 | ガード節を追加 |
| 説明 | テスト計画に TODO のプレースホルダーがある | 対応が必要 | テスト計画を記入 |
| レビュー | 「問題ありません」 - @teammate | 参考情報 | なし |
8. 問題を修正する(依頼された場合)
対応が必要な項目がある場合:
- まだ切り替えていなければ、PR/MR のブランチ(git)に切り替えるか、正しい CL(Perforce)でファイルが開かれていることを確認します。
- 問題を修正するかどうか、ユーザーに確認します。
- 修正する場合は、修正した後、次の手順を実行します。
GitHub/GitLab: コミットしてプッシュします。
git add <files>
git commit -m "address review feedback"
git push
Perforce: ファイルを編集用に開き、変更を加えて、再度保留します。
p4 edit <file>
# make changes
p4 shelve -f -c <CL_NUMBER>
9. レビュースレッドを解決する
コメントに対応したら、該当するレビュースレッドを解決します。
Perforce - Perforce には「スレッドを解決する」というネイティブの概念はありません。代わりに、CL の説明を更新するか、使用中のレビューツール(Swarm など)で返信して、コメントに対応済みであることを示します。p4 review を使用する場合:
# Mark files as reviewed after addressing feedback
p4 review -c <CL_NUMBER>
GitHub - 未解決のスレッド ID を取得します(必要に応じてページネーションします。GraphQL リファレンスを参照):
gh api graphql -f query='
query($cursor: String) {
repository(owner: "OWNER", name: "REPO") {
pullRequest(number: PR_NUMBER) {
reviewThreads(first: 100, after: $cursor) {
pageInfo { hasNextPage endCursor }
nodes {
id
isResolved
comments(first: 1) {
nodes { body path }
}
}
}
}
}
}'
hasNextPage が true の場合は、-f cursor=ENDCURSOR を指定して残りのスレッドを取得します。
次に、対応済み、または情報提供のみのスレッドを解決します:
gh api graphql -f query='
mutation {
resolveReviewThread(input: {threadId: "THREAD_ID"}) {
thread { isResolved }
}
}'
エイリアス(t1、t2 など)を使って、複数の解決を 1 つのミューテーションにまとめます。
GitLab - 未解決のディスカッションを取得します(GitLab API リファレンスを参照):
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100"
"resolved": false のディスカッションを絞り込みます。各ディスカッションの id を収集します。
各ディスカッションを個別に解決します(GitLab には一括解決機能がありません):
glab api --method PUT \
"projects/:fullpath/merge_requests/<MR_IID>/discussions/<DISCUSSION_ID>" \
--field resolved=true
未解決のディスカッション ID ごとに繰り返します。
10. 複数の PR/MR/CL
一連の PR/MR/CL を確認する場合は、順番に処理します。
Perforce - 複数のチェンジリストを一度に確認するには:
p4 changes -s pending -u $P4USER -c $P4CLIENT -l
出力形式
次の内容を要約します:
- PR/MR/CL のタイトルまたは説明と現在の状態
- 検出されたプラットフォーム(GitHub / GitLab / Perforce)
- ステータスチェックの概要(成功/失敗/保留中)。Perforce の場合は N/A
- 見つかった問題の合計数
- 説明付きの対応が必要な項目
- 無視できる項目とその理由
- 推奨される次の手順