pr-resolver について
GitHubのプルリクエストで、レビューコメントとチェック結果を取得し、対応後に解決を確認するスキルです。レビューごと、CIチェック種別ごとに個別コミットを作り、最後にまとめてプッシュする手順を定めています。
主な機能
- 01PRのレビューコメントとCI状態の取得
- 02すべてのレビューコメントへの対応と解決
- 03レビューコメントごとの個別コミット
- 04チェック種別ごとのCI修正とコミット
- 05GitHubから再取得して完了を確認
活用シーン
- 01GitHub PRのレビュー指摘への対応
- 02マージ前の失敗チェックの解消
- 03プッシュ後にレビューコメントの解決を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ zenobi-us/ dotfiles --skill pr-resolverインストール後、Claude Code で/pr-resolverを入力して読み込まれたか確認します。
同梱ファイルreferences/github_api_reference.md
詳細
GitHub PR リゾルバー
すべてのコメントを処理し、コードを修正し、すべての会話スレッドを解決し、すべての失敗した CI チェックを修正することで、プルリクエストのレビュー指摘への対応を自動化します。
このスキルでは、コメントを一切スキップしません。未解決のスレッドはすべて対応して解決する必要があります。
前提条件
# Verify gh CLI is installed and authenticated
gh auth status
# If not authenticated, run:
gh auth login
トークンには、リポジトリに完全にアクセスするための repo スコープが必要です。
ワークフローの概要
- PR のコンテキストを取得する → すべてのレビュー スレッドとチェックのステータスを取得します(常に GitHub から最新の情報を取得します)
- 未解決のスレッドをすべて処理する → スレッドごとに、修正 → コミット → 解決を行い、次のスレッドに進みます
- 失敗したチェックをすべて修正する → すべての失敗に対応し、チェックの種類ごとにコミットします
- 変更をプッシュする → すべてのコミットの後に一度だけプッシュします
- 確認する → GitHub から再取得し、すべてのスレッドが解決済みで、すべてのチェックが成功していることを確認します
コミットのタイミング(必須):
- 各レビュー スレッド = 1 コミット(修正 →
git add→git commit→ スレッドを解決 → 次のスレッド) - 各 CI チェックの種類 = 1 コミット(lint の修正、テストの修正、ビルドの修正はそれぞれ別のコミット)
- 最後にすべての変更を1つのコミットにまとめてはなりません
重要な要件:
- 常に GitHub から最新のデータを取得してください。 キャッシュ済み、または以前に取得したコンテキストを使用してはなりません。
- 未解決のコメントをすべて処理してください。 スレッドをスキップしてはなりません。各コメントに対応し、解決する必要があります。
- 未解決のスレッドがゼロであることが、許容される唯一の最終状態です。
コミット規約
変更ごとに、Conventional Commits 形式を使って個別のコミットを作成します。
<type>(<scope>): <description>
コメントからコミット種別を推定する:
| コメントのパターン | コミット種別 |
|---|---|
| バグ修正、null チェック、エラー処理、検証 | fix |
| 追加、含める、不足、実装 | feat |
| 名前変更、リファクタリング、提案、X を Y に変更 | refactor |
| ドキュメント、コメント、README | docs |
| パフォーマンス、最適化 | perf |
| スタイル、インデント、空白 | style |
ファイルパスからスコープを決める:
- ディレクトリ名またはモジュール名を抽出します:
src/services/UserService.ts→services - 一般的なプレフィックスは除外します:
src、lib、app - ルートにあるファイルではファイル名を使います:
index.ts→index
CI チェックのコミット:
- lint の修正 →
fix(lint): resolve linting errors - テストの修正 →
fix(tests): update failing assertions - ビルド/型エラー →
fix(build): resolve build errors - フォーマット →
style(format): apply formatting
ステップ 1:PR のコンテキストを取得する(常に最新の情報を取得)
重要:常に GitHub から最新のデータを取得してください。以前に取得したコンテキストデータを再利用してはなりません。
1.1 PR の詳細を取得する
# Get PR metadata
gh pr view <PR_NUMBER> --json number,title,state,headRefName,baseRefName,author,url
1.2 レビュー スレッドを取得する(ページネーションを使った GraphQL)
GraphQL を使って、解決ステータスを含むレビュー スレッドを取得します。API が1回のリクエストで返す項目は最大100件のため、スレッドが多い PR ではページネーションが必要です。
# First page (no cursor)
gh api graphql -f query='
query($owner: String!, $repo: String!, $prNumber: Int!, $cursor: String) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $prNumber) {
reviewThreads(first: 100, after: $cursor) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
isResolved
isOutdated
path
line
comments(first: 100) {
nodes {
id
databaseId
body
author { login }
createdAt
path
line
diffHunk
}
}
}
}
}
}
}' -f owner=OWNER -f repo=REPO -F prNumber=PR_NUMBER
ページネーションの処理:
# Check if more pages exist
HAS_NEXT=$(echo "$RESULT" | jq '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')
END_CURSOR=$(echo "$RESULT" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor')
# If hasNextPage is true, fetch next page with cursor
if [ "$HAS_NEXT" = "true" ]; then
gh api graphql -f query='...' -f owner=OWNER -f repo=REPO -F prNumber=PR_NUMBER -f cursor="$END_CURSOR"
fi
重要:hasNextPage が false になるまでページを取得し続けてください。処理を始める前に、すべてのスレッドを収集してください。
1.3 チェックのステータスを取得する
# Get all checks for the PR
gh pr checks <PR_NUMBER>
# For detailed check information
gh pr checks <PR_NUMBER> --json name,state,conclusion,description
1.4 コンテキストを解析する
取得後、次の項目を特定します。
- 未解決のスレッド:
isResolved: falseのスレッド - 失敗したチェック:
conclusionがfailure、cancelled、timed_out、またはaction_requiredのチェック
# Count unresolved threads
echo "Unresolved threads: $(echo "$THREADS_JSON" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length')"
# List failing checks
gh pr checks <PR_NUMBER> --json name,conclusion | jq '.[] | select(.conclusion == "failure")'
ステップ 2:すべてのレビュー スレッドを処理する
必須:未解決のスレッドをすべて処理してください。コメントをスキップしてはなりません。
未解決のスレッドを1つずつ処理します(すべてのスレッドを確認してください)。
2.1 コメントを理解する
最初のコメント(スレッドの起点となったコメント)を抽出し、求められている内容を把握します。
# For each unresolved thread, extract:
# - path: file path
# - line: line number
# - body: comment text
# - thread_id: GraphQL ID for resolution
2.2 修正の種類を特定する
すべてのコメントに対応が必要です。適切な修正方法を判断してください。
| コメントのパターン | 必要な対応 |
|---|---|
```suggestion を含む | 提案されたコードをそのまま適用します |
| 「Typo」「rename」「change X to Y」 | 指定されたテキストの変更を行います |
| 「Add...」「Include...」「Missing...」 | 要求されたコードや内容を追加します |
| 「Remove...」「Delete...」 | 指定されたコードを削除します |
| 「Consider...」「Maybe...」「Nit:」 | 改善を適用します(これらも依頼事項です) |
| 質問または議論 | コードを修正するか返信して対応し、その後スレッドを解決します |
任意のコメントはありません。すべてのスレッドに対応し、解決する必要があります。
2.3 コードの提案を適用する
明示的な提案があるコメントについては、内容を抽出して適用します。
# Suggestion blocks look like:
# ```suggestion
# replacement code here
# ```
# Extract suggestion content and apply to the file at the specified line
2.4 修正する
pathのファイルを開きますlineに移動します- 必要な変更を適用します
- ファイルを保存します
2.5 修正をコミットする(直ちに — まとめてコミットしない)
重要:修正のたびに直ちにコミットしてください。最後まで待たないでください。コミットをまとめないでください。
修正を行ったら、その都度、Conventional Commits 形式のメッセージを付けて直ちにコミットします。
# Stage only the affected file
git add <path>
# Commit with conventional message
git commit -m "<type>(<scope>): <description>"
コミットの例:
refactor(services): rename getUser to fetchUserfix(auth): add null check for tokenfeat(api): add retry logic per reviewdocs(utils): add JSDoc for helper function
2.6 スレッドを解決する
コミット後、GraphQL を使ってスレッドを解決します。
gh api graphql -f query='
mutation($threadId: ID!) {
resolveReviewThread(input: {threadId: $threadId}) {
thread {
id
isResolved
}
}
}' -f threadId="<THREAD_ID>"
未解決のスレッドごとに、手順 2.1〜2.6 を繰り返します。スレッドごとにコミットを 1 つ作成してください。すべてのスレッドを個別にコミットして処理するまで、手順 3 に進まないでください。
手順 3:失敗したチェックを修正する
3.1 失敗を分析する
# List all failing checks
gh pr checks <PR_NUMBER> --json name,state,conclusion,description | jq '.[] | select(.conclusion == "failure")'
# View workflow run logs for details
gh run view <RUN_ID> --log-failed
3.2 よくあるチェックの修正
Lint(eslint、pylint、ruff):
# JavaScript/TypeScript
npm run lint -- --fix
npx eslint . --fix
# Python
ruff check --fix .
black .
型チェック(tsc、mypy、pyright):
- チェック出力に表示された型エラーを修正します
- 不足している型注釈を追加します
- 誤った型を更新します
テスト(jest、pytest、vitest):
- テスト出力を読んで失敗を特定します
- 失敗したテストまたは実装を修正します
- 必要に応じてスナップショットを更新します:
npm test -- -u
フォーマット(prettier、black):
npx prettier --write .
black .
ビルド(webpack、vite、tsc):
- 構文エラーを修正します
- インポートの問題を解決します
- 依存関係がインストールされていることを確認します
3.3 チェックの修正を個別にコミットする
各チェックの種類を修正した後、それぞれ個別にコミットします。
# After fixing lint errors
git add .
git commit -m "fix(lint): resolve linting errors"
# After fixing test failures
git add .
git commit -m "fix(tests): update failing assertions"
# After fixing build/type errors
git add .
git commit -m "fix(build): resolve build errors"
# After fixing formatting
git add .
git commit -m "style(format): apply formatting"
3.4 ローカルでチェックを再実行する
プッシュする前に、ローカルで修正を確認します。
# Run the same commands CI runs
npm run lint
npm run test
npm run build
手順 4:すべてのコミットをプッシュする
すべてのレビュー スレッドと CI チェックに個別のコミットで対応した後、1 回だけプッシュします。
# Get the branch name
BRANCH=$(gh pr view <PR_NUMBER> --json headRefName -q '.headRefName')
# Push all commits to PR branch
git push origin $BRANCH
これにより、コミットごとに複数回ではなく、すべての変更に対して CI が 1 回実行されます。
手順 5:解決を確認する(必ず再取得する)
プッシュ後、必ず GitHub から最新のデータを取得して確認してください。以前に取得したコンテキストに頼ってはいけません。
- すべてのスレッドが解決済みであること(未解決のスレッドが 0 件)
- CI チェックが再実行されていること
- 新たな失敗が発生していないこと
# Re-fetch threads (fresh API call with pagination support)
gh api graphql -f query='
query($owner: String!, $repo: String!, $prNumber: Int!, $cursor: String) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $prNumber) {
reviewThreads(first: 100, after: $cursor) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
isResolved
}
}
}
}
}' -f owner=OWNER -f repo=REPO -F prNumber=PR_NUMBER
# Count remaining unresolved (remember to paginate if hasNextPage is true)
UNRESOLVED=$(echo "$RESULT" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length')
echo "Remaining unresolved: $UNRESOLVED"
# Check CI status
gh pr checks <PR_NUMBER>
重要:
- GitHub 上の実際の最新状態を確認するため、検証には必ず新しい API 呼び出しを使用してください。
- **未解決のスレッドが 1 件でも残っている場合、タスクは完了していません。**戻って対応してください。
- 許容される最終状態は、未解決のスレッドが 0 件の場合のみです。
完全な例
#!/bin/bash
# Complete workflow to resolve ALL PR feedback
PR_NUMBER=$1
REPO="owner/repo" # Or extract from current git remote
OWNER=${REPO%/*}
REPO_NAME=${REPO#*/}
# 1. Fetch fresh context from GitHub
echo "Fetching PR #$PR_NUMBER..."
PR_INFO=$(gh pr view $PR_NUMBER --json number,title,headRefName,baseRefName)
BRANCH=$(echo $PR_INFO | jq -r '.headRefName')
echo "PR: $(echo $PR_INFO | jq -r '.title')"
echo "Branch: $BRANCH"
# Fetch ALL review threads with pagination
ALL_THREADS="[]"
CURSOR=""
while true; do
if [ -z "$CURSOR" ]; then
CURSOR_ARG=""
else
CURSOR_ARG="-f cursor=$CURSOR"
fi
RESULT=$(gh api graphql -f query='
query($owner: String!, $repo: String!, $prNumber: Int!, $cursor: String) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $prNumber) {
reviewThreads(first: 100, after: $cursor) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
isResolved
path
line
comments(first: 100) {
nodes {
body
author { login }
}
}
}
}
}
}
}' -f owner=$OWNER -f repo=$REPO_NAME -F prNumber=$PR_NUMBER $CURSOR_ARG)
# Append threads from this page
PAGE_THREADS=$(echo $RESULT | jq '.data.repository.pullRequest.reviewThreads.nodes')
ALL_THREADS=$(echo "$ALL_THREADS $PAGE_THREADS" | jq -s 'add')
# Check for next page
HAS_NEXT=$(echo $RESULT | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')
if [ "$HAS_NEXT" != "true" ]; then
break
fi
CURSOR=$(echo $RESULT | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor')
done
UNRESOLVED_COUNT=$(echo $ALL_THREADS | jq '[.[] | select(.isResolved == false)] | length')
TOTAL_COUNT=$(echo $ALL_THREADS | jq 'length')
echo "Total threads: $TOTAL_COUNT"
echo "Unresolved threads: $UNRESOLVED_COUNT"
# 2. Checkout PR branch
git fetch origin $BRANCH
git checkout $BRANCH
# 3. Process EACH unresolved thread (Claude does this interactively)
# For each thread:
# - Read the comment
# - Make the fix
# - git add <file>
# - git commit -m "<type>(<scope>): <description>"
# - gh api graphql ... resolve mutation
# - Move to next thread
# 4. Fix failing checks (one commit per check type)
gh pr checks $PR_NUMBER --json name,conclusion | jq '.[] | select(.conclusion == "failure")'
# Fix each failing check type and commit separately
# 5. Push all commits
git push origin $BRANCH
# 6. Verify - re-fetch ALL pages and confirm zero unresolved
# (Use same pagination loop as above)
if [ "$REMAINING" -gt 0 ]; then
echo "⚠️ WARNING: $REMAINING threads still unresolved!"
echo "Must go back and process remaining threads."
else
echo "✅ All threads resolved!"
fi
参考資料
以下について詳しくは references/github_api_reference.md を参照してください。
- コメントの意図を示すパターン
- CI チェックの種類とよくある修正
- API のレート制限とエラー処理
- Git ワークフローのベストプラクティス