处理 GitLab MR 审阅评论
概述
GitLab MR 上的内联审阅评论存在于 discussions(锚定到文件和行的线程)中。整个流程(获取位置 → 修复 → 回复 → 解决)通过 glab api 运行。该技能提供了经过验证的命令序列;关键点在于,明显的命令 (glab mr view --comments) 虽然能提供评论文本,但不提供文件/行位置,因此无法判断每条评论所指的内容。
必需的背景知识: 使用 superpowers:receiving-code-review 进行判断:严格评估每条评论,确保在应用之前其正确性。本技能仅涵盖 GitLab 的操作机制。
设置
MR=511 # MR 的 iid
PROJ="<group>%2F<subgroup>%2F<project>" # URL 编码的完整路径
API="projects/$PROJ/merge_requests/$MR"
对路径进行 URL 编码(/ 替换为 %2F)。如果不确定,可以通过 glab repo view 获取。
1. 获取包含位置的评论
glab mr view $MR --comments 不包含行位置,因此不要将其用于内联评论。应当调用 Discussions API 并解析 position。--paginate 是必需的:该端点每页返回 20 个线程,如果不使用该参数,其余线程会被静默丢弃。已解决的线程会被跳过:
glab api --paginate --output ndjson "$API/discussions" | python3 -c '
import sys, json
for line in sys.stdin:
d = json.loads(line)
n = d["notes"][0]
if n.get("system") or n.get("resolved"): continue
p = n.get("position") or {}
print(d["id"], "|", n["author"]["username"], "|", n["body"])
if p: print(" ->", p.get("new_path"), "new_line:", p.get("new_line"), "old_line:", p.get("old_line"))
'
new_line= 当前(更改后)文件中的行 → 阅读此信息以解释评论。- 对更改行的评论同时包含
old_line和new_line;应以new_path和new_line为锚点。 - 没有
position→ 表示这是一条一般性(非内联)评论。
2. 读取每个 new_path:new_line 处的代码,然后修复
在引用的行处打开文件,以便在上下文中理解评论。仅在评估后(参见 receiving-code-review)应用修复。创建一个审阅修复提交并推送:
git add <files>
git commit -m "fix(<scope>): address review on <thing>" # 常规提交规范,ticket ID 放在正文中
git fetch origin <target> && git rebase origin/<target>
git push --force-with-lease # 仅当 rebase 无操作时,普通的 `git push` 才足够
3. 回复并解决每个线程
向 discussion 的 notes 端点发送 POST 请求会自动将回复加入线程(无需 in_reply_to_id)。然后通过 PUT 请求设置 resolved=true:
DISC="<step 1 获取的 discussion id>"
glab api -X POST "$API/discussions/$DISC/notes" -f "body=已完成: <你更改的内容>."
glab api -X PUT "$API/discussions/$DISC?resolved=true"
永远不要将 glab 包装在 shell 函数中:权限允许规则只匹配字面命令,因此需要为每个线程完整写出这两个调用。
编写回复
保持简洁,说明更改了什么以及为什么。审阅者想要的是差异,而不是调查过程。
- 已采纳:一到两句话。你更改了什么,是否将更改范围扩大到引用的行之外,以及提交的 SHA。
已完成,块级样式统一应用:所有六个组件,而不仅仅这一行。渲染输出未变。f6511f29 - 不同意或推迟:先说决定性的事实,再说选项,最后将决定权交还给审阅者。最多两个短段落。省略保留意见、第三个支持论据和“很高兴讨论”的收尾。
- 永远不要叙述自己修正的过程,也不要重复审阅者的评论。
哪些线程需要解决
只解决你实际关闭的线程。
- 已应用更改 -> 回复 + 解决。
- 回答了问题且答案解决了问题 -> 回复 + 解决。
- 需要他人做决定的事项(目标环境、范围、优先级)-> 回复,不要解决。解决一个审阅者仍需仲裁的线程,会被视为草率处理,并且该线程会从他们的审阅列表中消失。
快速参考
| 步骤 | 命令 |
|---|---|
| 列出内联评论及位置 | glab api --paginate --output ndjson "$API/discussions" → 解析 .notes[].position.{new_path,new_line,old_line} |
| 回复一个线程 | glab api -X POST "$API/discussions/<id>/notes" -f "body=..." |
| 解决一个线程 | glab api -X PUT "$API/discussions/<id>?resolved=true" |
常见错误
- 对内联评论使用
glab mr view --comments:只能获取文本,没有文件/行信息;无法定位评论。应使用 Discussions API。 - 编造
glab mr note resolve:通过glab api -X PUT ".../discussions/<id>?resolved=true"解决。 - 读取
old_line而不是new_line:对于更改行上的评论,当前代码位于new_line。 - 忘记
--paginate:超过 20 个线程后,Discussions API 会静默地只返回第一页。 - rebase 后使用裸
--force:应使用--force-with-lease,以免覆盖审阅者在此期间推送的提交。 - 盲目应用评论:先评估(receiving-code-review)。回复时说明你实际更改了什么,然后解决。
- 列出线程时截断 discussion id:API 需要完整的 40 字符 id,8 字符前缀会返回
404 Discussion Not Found。输出完整的d["id"]。 - 在回复中过度解释:参见“编写回复”。论证内容应放在 MR 描述或 ticket 中。
- 解决推迟的决定:如果审阅者仍需选择,请保持线程打开。