关于 attach-review-to-pr
介绍如何在 GitHub 拉取请求中发布针对具体代码行的审查意见。说明优先使用可用的 MCP 工具,也涵盖 GitHub CLI API 备用方案、批量审查和问题排查。
主要功能
- 01针对 diff 的具体行发表评论
- 02将多条意见合并为一次审查
- 03使用 GitHub CLI REST API 端点
- 04指定多行评论范围
- 05排查提交和行号验证问题
适用场景
- 01对 PR 中更改的代码行提供反馈
- 02将相关意见作为一次审查提交
- 03内联评论 MCP 工具不可用时发表评论
MCP 相关
建议在可用时使用 `mcp__github_inline_comment__create_inline_comment` 工具添加 PR 行内评论,并将 GitHub CLI API 调用作为备用方案。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ neolabhq/ context-engineering-kit --skill attach-review-to-pr安装后在 Claude Code 中输入/attach-review-to-pr确认已加载。
详细介绍
如何为拉取请求添加针对特定行的审查评论
本指南介绍如何使用 GitHub CLI(gh)API,或在无法使用 mcp__github_inline_comment__create_inline_comment 时,通过该工具为拉取请求添加针对特定行的审查评论,类似于在 GitHub UI 中对代码的特定行发表评论。
首选方法:使用 MCP GitHub 工具
如果可用,请使用 mcp__github_inline_comment__create_inline_comment MCP 工具,在拉取请求中发布针对特定行的行内评论。此方法与 GitHub UI 的集成更好,也是推荐的方法。
备用方法:如果 MCP 工具不可用,请使用下文所述的 GitHub CLI(gh)API 方法:
- 单条评论:使用
/comments端点(参见添加单条针对特定行的评论) - 多条评论:使用
/reviews端点(参见一次添加多条针对特定行的评论)
概述
虽然 gh pr review 提供了基本的审查功能(批准、请求更改、一般评论),但它不支持直接添加针对特定行的评论。要对代码的特定行发表评论,必须使用较底层的 gh api 命令直接调用 GitHub REST API。
前提条件
-
已安装并完成身份验证的 GitHub CLI:
gh auth status -
有权访问要审查的仓库和拉取请求
了解 GitHub 的审查评论系统
GitHub 有两种 PR 评论:
- Issue 评论——在 PR 对话中的一般评论
- 审查评论——针对代码更改特定行的评论
审查评论可通过两种方式添加:
- 单条评论——使用
/pulls/{pr}/comments端点 - 包含多条评论的审查——使用
/pulls/{pr}/reviews端点
添加单条针对特定行的评论
基本语法
gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \
-f body='Your comment text here' \
-f commit_id='<commit-sha>' \
-f path='path/to/file.js' \
-F line=42 \
-f side='RIGHT'
参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
body | string | 是 | 审查评论的文本(支持 Markdown) |
commit_id | string | 是 | 要发表评论的提交 SHA |
path | string | 是 | 被评论文件的相对路径 |
line | integer | 是 | 差异中的行号(整数请使用 -F) |
side | string | 是 | 新增或修改的行使用 RIGHT,已删除的行使用 LEFT |
start_line | integer | 否 | 多行评论的起始行 |
start_side | string | 否 | 多行评论的起始侧 |
参数标志
-f(--field)——用于字符串值-F(--field)——用于整数值(注意大写 F)
完整示例
# First, get the latest commit SHA for the PR
gh api repos/NeoLabHQ/learning-platform-app/pulls/4 --jq '.head.sha'
# Then add your comment
gh api repos/NeoLabHQ/learning-platform-app/pulls/4/comments \
-f body='Consider adding error handling here. Should we confirm the lesson was successfully marked as completed before navigating away?' \
-f commit_id='e152d0dd6cf498467eadbeb638bf05abe11c64d4' \
-f path='src/components/LessonNavigationButtons.tsx' \
-F line=26 \
-f side='RIGHT'
了解行号
line 参数指的是差异中的位置,而非文件中的绝对行号:
- 对于新文件:行号与文件中的行号一致
- 对于已修改的文件:使用“Files changed”选项卡中显示的行号
- 对于多行评论:使用
start_line和line指定范围
响应
成功时会返回包含评论详情的 JSON 对象:
{
"id": 2532291222,
"pull_request_review_id": 3470545909,
"path": "src/components/LessonNavigationButtons.tsx",
"line": 26,
"body": "Consider adding error handling here...",
"html_url": "https://github.com/NeoLabHQ/learning-platform-app/pull/4#discussion_r2532291222",
"created_at": "2025-11-16T22:40:46Z"
}
一次添加多条针对特定行的评论
要在一次审查中为不同文件添加多条评论,请使用 /reviews 端点并提供 JSON 输入。
为什么要用审查一次添加多条评论?
- 原子操作——所有评论会一并添加
- 单条通知——避免发送多条通知造成骚扰
- 更好的用户体验——评论会作为一条连贯的审查显示
- 与 GitHub UI 使用相同机制——“Start a review” → “Finish review”
基本语法
cat <<'EOF' | gh api repos/{owner}/{repo}/pulls/{pr_number}/reviews --input -
{
"event": "COMMENT",
"body": "Overall review summary (optional)",
"comments": [
{
"path": "file1.tsx",
"body": "Comment on file 1",
"side": "RIGHT",
"line": 15
},
{
"path": "file2.tsx",
"body": "Comment on file 2",
"side": "RIGHT",
"line": 30
}
]
}
EOF
审查事件类型
| 事件 | 说明 | 使用场景 |
|---|---|---|
COMMENT | 一般审查评论 | 仅提供反馈,不批准 |
APPROVE | 批准 PR | 更改看起来不错,可以合并 |
REQUEST_CHANGES | 请求更改 | 合并前必须修复的问题 |
完整示例
cat <<'EOF' | gh api repos/NeoLabHQ/learning-platform-app/pulls/4/reviews --input -
{
"event": "COMMENT",
"body": "Testing multiple line-specific comments via gh api",
"comments": [
{
"path": "src/components/CourseCard.tsx",
"body": "Test comment generated by Claude",
"side": "RIGHT",
"line": 15
},
{
"path": "src/components/CourseProgressWidget.tsx",
"body": "Test comment generated by Claude",
"side": "RIGHT",
"line": 30
},
{
"path": "src/components/LessonProgressTracker.tsx",
"body": "Test comment generated by Claude",
"side": "RIGHT",
"line": 20
}
]
}
EOF
响应
{
"id": 3470546747,
"state": "COMMENTED",
"html_url": "https://github.com/NeoLabHQ/learning-platform-app/pull/4#pullrequestreview-3470546747",
"submitted_at": "2025-11-16T22:42:43Z",
"commit_id": "e152d0dd6cf498467eadbeb638bf05abe11c64d4"
}
常见问题和解决方案
问题 1:"user_id can only have one pending review per pull request"
错误消息:
gh: Validation Failed (HTTP 422)
{"message":"Validation Failed","errors":[{"resource":"PullRequestReview","code":"custom","field":"user_id","message":"user_id can only have one pending review per pull request"}]}
原因: GitHub 只允许每位用户对每个 PR 有一条待处理(尚未提交)的评审。如果你之前通过 UI 或 API 开始了评审但没有提交,就会阻止创建新的评审。
解决方案 1:提交待处理的评审
# Check for pending reviews
gh api repos/{owner}/{repo}/pulls/{pr_number}/reviews | jq '.[] | select(.state=="PENDING")'
# Submit it through the UI or ask the user to submit it
解决方案 2:改用单条评论端点
# Add individual comments without creating a review
gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \
-f body='Comment text' \
-f commit_id='<sha>' \
-f path='file.tsx' \
-F line=26 \
-f side='RIGHT'
问题 2:使用 --raw-field 时数组语法无效
尝试失败:
# This does NOT work - GitHub API receives an object, not an array
gh api repos/{owner}/{repo}/pulls/{pr}/reviews \
--raw-field 'comments[0][path]=file1.tsx' \
--raw-field 'comments[0][line]=15' \
--raw-field 'comments[1][path]=file2.tsx' \
--raw-field 'comments[1][line]=30'
错误:
Invalid request. For 'properties/comments', {"0" => {...}, "1" => {...}} is not an array.
解决方案: 通过 heredoc 使用 JSON 输入:
cat <<'EOF' | gh api repos/{owner}/{repo}/pulls/{pr}/reviews --input -
{
"comments": [...]
}
EOF
问题 3:行号无效
错误消息:
Pull request review thread line must be part of the diff
原因: 此文件的差异中不存在该行号。
解决方案:
- 确认此 PR 确实修改了该文件
- 查看“Files changed”标签页,确认差异中的实际行号
- 确保使用正确的
commit_id(PR 中的最新提交)
问题 4:commit_id 错误
错误消息:
commit_sha is not part of the pull request
解决方案: 获取最新提交的 SHA:
gh api repos/{owner}/{repo}/pulls/{pr_number} --jq '.head.sha'
最佳实践
1. 首先获取 PR 信息
添加评论前,先收集必要信息:
# Get PR details
gh pr view {pr_number} --json headRefOid,files
# Or use the API
gh api repos/{owner}/{repo}/pulls/{pr_number} --jq '{commit: .head.sha, files: [.changed_files]}'
# List files changed
gh api repos/{owner}/{repo}/pulls/{pr_number}/files --jq '.[] | {filename: .filename, additions: .additions, deletions: .deletions}'
2. 检查是否有待处理的评审
# Check if you have a pending review
gh api repos/{owner}/{repo}/pulls/{pr_number}/reviews \
--jq '.[] | select(.state=="PENDING" and .user.login=="YOUR_USERNAME")'
3. 使用有意义的评论文本
- 具体且具有建设性
- 引用文档或最佳实践
- 请求修改时提供替代方案
- 使用代码块提供代码建议:
Consider using async/await:
\`\`\`typescript
async function getData() {
const result = await fetch(url);
return result.json();
}
\`\`\`
4. 批量提交相关评论
使用评审端点将相关评论分组:
- 同一文件或区域的所有评论
- 针对特定问题(安全、性能等)的所有评论
- 完整的评审会话
5. 选择合适的事件类型
# For feedback during development
"event": "COMMENT"
# When approving
"event": "APPROVE"
# When blocking merge
"event": "REQUEST_CHANGES"
工作流示例
示例 1:快速添加单条评论
#!/bin/bash
OWNER="NeoLabHQ"
REPO="learning-platform-app"
PR=4
# Get latest commit
COMMIT=$(gh api repos/$OWNER/$REPO/pulls/$PR --jq '.head.sha')
# Add comment
gh api repos/$OWNER/$REPO/pulls/$PR/comments \
-f body='Consider extracting this into a separate function for better testability' \
-f commit_id="$COMMIT" \
-f path='src/utils/validation.ts' \
-F line=45 \
-f side='RIGHT'
示例 2:全面评审
#!/bin/bash
OWNER="NeoLabHQ"
REPO="learning-platform-app"
PR=4
# Create review with multiple comments
cat <<EOF | gh api repos/$OWNER/$REPO/pulls/$PR/reviews --input -
{
"event": "COMMENT",
"body": "Thanks for the PR! I've reviewed the changes and have a few suggestions.",
"comments": [
{
"path": "src/components/CourseCard.tsx",
"body": "Consider memoizing this component to prevent unnecessary re-renders",
"side": "RIGHT",
"line": 25
},
{
"path": "src/utils/courseProgress.ts",
"body": "This function could benefit from error handling for invalid course IDs",
"side": "RIGHT",
"line": 12
},
{
"path": "src/state/CourseProgressState.ts",
"body": "Consider adding JSDoc comments to document the expected behavior",
"side": "RIGHT",
"line": 8
}
]
}
EOF
示例 3:多行评论
# Comment on a range of lines (e.g., lines 10-15)
gh api repos/$OWNER/$REPO/pulls/$PR/comments \
-f body='This entire block could be simplified using array destructuring' \
-f commit_id="$COMMIT" \
-f path='src/utils/parser.ts' \
-F start_line=10 \
-f start_side='RIGHT' \
-F line=15 \
-f side='RIGHT'
实用辅助脚本
获取 PR 文件和行号
#!/bin/bash
# pr-files.sh - List all files changed in a PR with line counts
OWNER="$1"
REPO="$2"
PR="$3"
gh api repos/$OWNER/$REPO/pulls/$PR/files --jq '.[] | "\(.filename): +\(.additions)/-\(.deletions)"'
检查评审状态
#!/bin/bash
# check-reviews.sh - Check review status for a PR
OWNER="$1"
REPO="$2"
PR="$3"
echo "=== Reviews ==="
gh api repos/$OWNER/$REPO/pulls/$PR/reviews --jq '.[] | "\(.user.login): \(.state) at \(.submitted_at)"'
echo -e "\n=== Pending Reviews ==="
gh api repos/$OWNER/$REPO/pulls/$PR/reviews --jq '.[] | select(.state=="PENDING") | "\(.user.login): \(.state)"'
相关文档
API 参考
POST /repos/{owner}/{repo}/pulls/{pull_number}/comments
在特定行创建评审评论。
端点: https://api.github.com/repos/{owner}/{repo}/pulls/{pull_number}/comments
参数:
body(string,必填):评论文本commit_id(string,必填):提交的 SHApath(string,必填):相对文件路径line(integer,必填):差异中的行号side(string,必填):"LEFT" 或 "RIGHT"start_line(integer,可选):多行评论的起始行start_side(string,可选):多行评论的起始侧
POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews
创建评审,并可选择添加特定行的评论。
端点: https://api.github.com/repos/{owner}/{repo}/pulls/{pull_number}/reviews
参数:
event(string,必填):"APPROVE"、"REQUEST_CHANGES" 或 "COMMENT"body(string,可选):总体评审评论comments(array,可选):评论对象数组commit_id(string,可选):要评审的提交 SHA
评论对象:
path(string,必填):相对文件路径body(string,必填):评论文本line(integer,必填):差异中的行号side(string,必填):"LEFT" 或 "RIGHT"start_line(integer,可选):多行评论的起始行start_side(string,可选):多行评论的起始侧