github-pr-review-comments

📁 straub/agent-skills 📅 9 days ago
1
总安装量
1
周安装量
#50376
全站排名
安装命令
npx skills add https://github.com/straub/agent-skills --skill github-pr-review-comments

Agent 安装分布

opencode 1
github-copilot 1
claude-code 1

Skill 文档

GitHub PR Review Comments

This skill provides a comprehensive workflow for managing PR review comments using the gh CLI and GitHub’s GraphQL API.

When to Use This Skill

Use this skill when:

  • Asked to address PR review comments
  • Finding unreplied or unresolved review threads
  • Replying to review comments
  • Resolving or unresolving review threads
  • Working with review threads programmatically (coding agents, automation)

Finding All Review Comments (Reliable Method)

CRITICAL: PR review comments are paginated and span multiple review rounds. Simple queries will miss comments. Use this comparison approach:

Step 1: Get ALL Original Comment IDs

gh api repos/{owner}/{repo}/pulls/{pr}/comments --paginate \
  --jq '[.[] | select(.in_reply_to_id == null)] | .[].id' \
  | sort -n > /tmp/all_original_comments.txt

This finds all “top-level” review comments (not replies).

Step 2: Check Your Username

gh api user -q .login

Step 3: Get ALL Comment IDs That Have Your Replies

gh api repos/{owner}/{repo}/pulls/{pr}/comments --paginate \
  --jq '[.[] | select(.user.login == "{your_username}" and .in_reply_to_id != null)] | .[].in_reply_to_id' \
  | sort -n > /tmp/replied_comments.txt

Step 4: Find Unreplied Comments (Set Difference)

comm -23 /tmp/all_original_comments.txt /tmp/replied_comments.txt

This shows comment IDs that don’t have your reply yet.

Why Simple Approaches Fail

  • Time-based filtering misses comments from earlier review rounds added to the same PR
  • Non-paginated queries miss comments beyond the first page (typically 30-100 per page)
  • Counting reviews vs comments is misleading – a single review can have many comments
  • The PR “comments” field only shows issue-style comments, not review comments

Getting Comment Details

Once you have unreplied comment IDs, get full details:

gh api repos/{owner}/{repo}/pulls/{pr}/comments --paginate \
  --jq '[.[] | select(.id == {id1} or .id == {id2})] | .[] | {id, path, line, body}'

Replace {id1}, {id2} with actual comment IDs.

Replying to Review Comments

Basic Reply to a Comment

gh api repos/{owner}/{repo}/pulls/{pr}/comments/{comment_id}/replies \
  -X POST -f body='Your response here'

Response Format Best Practices

  • Start with status emoji:
    • ✅ for addressed/fixed
    • 🔄 for acknowledged/will fix
    • 💭 for discussion/clarification needed
  • Reference specific commits when fixes are made: **FIXED** in commit abc1234
  • Be concise but clear about what action was taken
  • Group related fixes into single commits with descriptive messages

Example Responses

# Fixed issue
gh api repos/owner/repo/pulls/123/comments/456/replies \
  -X POST -f body='✅ **FIXED** in commit abc1234 - Refactored to use async/await pattern'

# Acknowledged
gh api repos/owner/repo/pulls/123/comments/789/replies \
  -X POST -f body='🔄 Good catch! Will fix in next commit'

Working with Review Threads (GraphQL API)

The GitHub GraphQL API provides powerful capabilities for managing review threads.

Fetch Unresolved Review Threads

gh api graphql -f query='
{
  repository(owner: "OWNER", name: "REPO") {
    pullRequest(number: PR_NUMBER) {
      reviewThreads(first: 100) {
        nodes {
          id
          isResolved
          comments(first: 100) {
            nodes {
              id
              body
              author { login }
              path
              line
            }
          }
        }
      }
    }
  }
}'

Reply to a Review Thread

Use the thread ID from reviewThreads.nodes[].id (format: PRRT_kwDO...), NOT the comment ID:

gh api graphql -f query='
mutation {
  addPullRequestReviewThreadReply(input: {
    pullRequestReviewThreadId: "PRRT_kwDO..."
    body: "Your reply here"
  }) {
    comment { id }
  }
}'

Resolve a Review Thread

gh api graphql -f query='
mutation {
  resolveReviewThread(input: {threadId: "PRRT_kwDO..."}) {
    thread { id isResolved }
  }
}'

Thread IDs are in the id field of each thread node (format: PRRT_kwDO...).

Unresolve a Review Thread

gh api graphql -f query='
mutation {
  unresolveReviewThread(input: {threadId: "PRRT_kwDO..."}) {
    thread { id isResolved }
  }
}'

Workflow: Addressing All Review Comments

  1. Find unreplied comments using the comparison method above
  2. Get comment details for each unreplied comment
  3. Make necessary code changes to address the feedback
  4. Commit changes with descriptive messages
  5. Reply to each comment with status and commit reference
  6. Resolve threads when appropriate (only after fix is confirmed and pushed)

Examples

Example 1: Find and List All Unreplied Comments for PR #42

# Set variables
OWNER="myorg"
REPO="myrepo"
PR="42"

# Step 1: Get all original comment IDs
gh api repos/$OWNER/$REPO/pulls/$PR/comments --paginate \
  --jq '[.[] | select(.in_reply_to_id == null)] | .[].id' \
  | sort -n > /tmp/all_original_comments.txt

# Step 2: Get your username
USERNAME=$(gh api user -q .login)

# Step 3: Get comment IDs you've replied to
gh api repos/$OWNER/$REPO/pulls/$PR/comments --paginate \
  --jq "[.[] | select(.user.login == \"$USERNAME\" and .in_reply_to_id != null)] | .[].in_reply_to_id" \
  | sort -n > /tmp/replied_comments.txt

# Step 4: Find unreplied comment IDs
UNREPLIED=$(comm -23 /tmp/all_original_comments.txt /tmp/replied_comments.txt)

# Step 5: Get details for unreplied comments
for id in $UNREPLIED; do
  gh api repos/$OWNER/$REPO/pulls/$PR/comments --paginate \
    --jq "[.[] | select(.id == $id)] | .[] | {id, path, line, body, author: .user.login}"
done

Example 2: Reply to Multiple Comments After Fix

OWNER="myorg"
REPO="myrepo"
PR="42"
COMMIT="abc1234"

# Reply to comment about async refactoring
gh api repos/$OWNER/$REPO/pulls/$PR/comments/111/replies \
  -X POST -f body="✅ **FIXED** in commit $COMMIT - Refactored to use async/await"

# Reply to comment about error handling
gh api repos/$OWNER/$REPO/pulls/$PR/comments/222/replies \
  -X POST -f body="✅ **FIXED** in commit $COMMIT - Added try/catch with proper error logging"

Example 3: Get All Unresolved Threads and Reply

OWNER="myorg"
REPO="myrepo"
PR="42"

# Fetch unresolved threads
THREADS=$(gh api graphql -f query="
{
  repository(owner: \"$OWNER\", name: \"$REPO\") {
    pullRequest(number: $PR) {
      reviewThreads(first: 100) {
        nodes {
          id
          isResolved
          comments(first: 1) {
            nodes { body path }
          }
        }
      }
    }
  }
}")

echo "$THREADS" | jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)'

# Reply to a specific thread and resolve it
THREAD_ID="PRRT_kwDOAbc123"

gh api graphql -f query="
mutation {
  addPullRequestReviewThreadReply(input: {
    pullRequestReviewThreadId: \"$THREAD_ID\"
    body: \"✅ Fixed in latest commit\"
  }) {
    comment { id }
  }
}"

gh api graphql -f query="
mutation {
  resolveReviewThread(input: {threadId: \"$THREAD_ID\"}) {
    thread { id isResolved }
  }
}"

Guidelines

  • Always paginate when fetching PR comments – use --paginate flag
  • Use set comparison (comm command) to reliably find unreplied comments
  • Reply before resolving – add a comment explaining the fix before marking as resolved
  • Reference commits in replies so reviewers can verify the fix
  • Group related changes into single commits with clear messages
  • Test your fixes before replying to ensure the issue is actually addressed
  • Be specific in replies about what changed and why
  • Keep replies concise but informative
  • Use emojis consistently for status (✅ fixed, 🔄 in progress, 💭 discussion)

Notes

REST API vs GraphQL API

  • REST API (gh api repos/.../pulls/.../comments):

    • Better for listing and filtering comments
    • Simpler for replies
    • Requires pagination for complete results
  • GraphQL API (gh api graphql):

    • Better for fetching threads with nested structure
    • Required for resolving/unresolving threads
    • More efficient for complex queries (fewer API calls)
    • Thread IDs have format PRRT_kwDO...

Comment ID vs Thread ID

  • Comment IDs are numeric (e.g., 123456789)
  • Thread IDs are GraphQL node IDs (e.g., PRRT_kwDOAbc123...)
  • Use comment IDs for REST API replies
  • Use thread IDs for GraphQL thread operations

Automation Considerations

For coding agents and automation:

  • Store comment IDs and thread IDs for tracking
  • Batch operations where possible to reduce API calls
  • Add delays between API calls to respect rate limits
  • Log all API responses for debugging
  • Handle errors gracefully (comment might be deleted, PR might be closed)

Future Enhancement

When gh pr review-thread command becomes available (gh cli #12419), it will provide:

  • gh pr review-thread resolve <thread-id>
  • gh pr review-thread unresolve <thread-id>
  • gh pr review-thread list --unresolved

Until then, use the GraphQL mutations shown above.