mcpField
P
pr-resolver

pr-resolver

github.com/zenobi-usテスト・品質6835 回インストール今日更新
リポジトリ

pr-resolver について

GitHubのプルリクエストで、レビューコメントとチェック結果を取得し、対応後に解決を確認するスキルです。レビューごと、CIチェック種別ごとに個別コミットを作り、最後にまとめてプッシュする手順を定めています。

主な機能

  1. 01PRのレビューコメントとCI状態の取得
  2. 02すべてのレビューコメントへの対応と解決
  3. 03レビューコメントごとの個別コミット
  4. 04チェック種別ごとのCI修正とコミット
  5. 05GitHubから再取得して完了を確認

活用シーン

  1. 01GitHub PRのレビュー指摘への対応
  2. 02マージ前の失敗チェックの解消
  3. 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 スコープが必要です。

ワークフローの概要

  1. PR のコンテキストを取得する → すべてのレビュー スレッドとチェックのステータスを取得します(常に GitHub から最新の情報を取得します)
  2. 未解決のスレッドをすべて処理する → スレッドごとに、修正 → コミット → 解決を行い、次のスレッドに進みます
  3. 失敗したチェックをすべて修正する → すべての失敗に対応し、チェックの種類ごとにコミットします
  4. 変更をプッシュする → すべてのコミットの後に一度だけプッシュします
  5. 確認する → GitHub から再取得し、すべてのスレッドが解決済みで、すべてのチェックが成功していることを確認します

コミットのタイミング(必須):

  • 各レビュー スレッド = 1 コミット(修正 → git add → git commit → スレッドを解決 → 次のスレッド)
  • 各 CI チェックの種類 = 1 コミット(lint の修正、テストの修正、ビルドの修正はそれぞれ別のコミット)
  • 最後にすべての変更を1つのコミットにまとめてはなりません

重要な要件:

  • 常に GitHub から最新のデータを取得してください。 キャッシュ済み、または以前に取得したコンテキストを使用してはなりません。
  • 未解決のコメントをすべて処理してください。 スレッドをスキップしてはなりません。各コメントに対応し、解決する必要があります。
  • 未解決のスレッドがゼロであることが、許容される唯一の最終状態です。

コミット規約

変更ごとに、Conventional Commits 形式を使って個別のコミットを作成します。

<type>(<scope>): <description>

コメントからコミット種別を推定する:

コメントのパターンコミット種別
バグ修正、null チェック、エラー処理、検証fix
追加、含める、不足、実装feat
名前変更、リファクタリング、提案、X を Y に変更refactor
ドキュメント、コメント、READMEdocs
パフォーマンス、最適化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 修正する
  1. path のファイルを開きます
  2. line に移動します
  3. 必要な変更を適用します
  4. ファイルを保存します
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 fetchUser
  • fix(auth): add null check for token
  • feat(api): add retry logic per review
  • docs(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 から最新のデータを取得して確認してください。以前に取得したコンテキストに頼ってはいけません。

  1. すべてのスレッドが解決済みであること(未解決のスレッドが 0 件)
  2. CI チェックが再実行されていること
  3. 新たな失敗が発生していないこと
# 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 ワークフローのベストプラクティス

コメント