关于 check-pr
check-pr 是用于检查 GitHub PR、GitLab MR 和 Perforce shelved changelist 的审查技能,面向需要汇总检查状态与反馈的开发者。它会核实 Greptile 结果是否对应当前提交,并可协助处理发现的问题。
主要功能
- 01识别 GitHub、GitLab 或 Perforce
- 02检查状态检查、描述和评论
- 03等待未完成的检查
- 04验证 Greptile 结果对应当前提交
- 05分类问题并协助修复与解决讨论
适用场景
- 01合并前汇总 PR 或 MR 的待处理事项
- 02确认 Greptile 审查针对最新提交
- 03检查 Perforce shelved changelist 的审查反馈
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ paperclipai/ paperclip --skill check-pr安装后在 Claude Code 中输入/check-pr确认已加载。
附带文件references/gitlab-api.mdreferences/graphql-queries.md
详细介绍
检查 PR
分析拉取请求(GitHub)、合并请求(GitLab)或已搁置的变更列表(Perforce),检查审查评论、状态检查和描述是否完整,然后帮助解决发现的问题。
输入
- PR/MR/CL 编号(可选):如果未提供,则检测当前分支对应的 PR/MR,或 p4 的默认待处理变更列表。
指令
0. 检测平台
首先,检查用户是否在 Perforce depot 中工作:查找 .p4config 文件或 P4CLIENT/P4PORT 环境变量:
# Check for Perforce environment
if p4 info >/dev/null 2>&1; then
VCS="perforce"
else
# Fall back to git remote detection
REMOTE_URL=$(git remote get-url origin)
if echo "$REMOTE_URL" | grep -qi "gitlab"; then
VCS="gitlab"
else
VCS="github"
fi
fi
对于主机名中不含 "gitlab" 的自托管 GitLab 实例,用户可以通过输入 --vcs gitlab 覆盖检测结果。对于 Perforce,用户可以通过输入 --vcs perforce 覆盖检测结果。
1. 确定 PR/MR/CL
如果已提供编号,则使用该编号。否则,检测编号:
GitHub:
gh pr view --json number,headRefName,headRefOid -q '{number: .number, branch: .headRefName, head: .headRefOid}'
GitLab:
glab mr view --output json | jq '.iid'
Perforce:
# List pending changelists for the current user/client
p4 changes -s pending -u $P4USER -c $P4CLIENT
各平台字段的主要差异:
- GitHub:
number、headRefName、headRefOid - GitLab:
iid、source_branch、sha - Perforce:变更列表编号(CL);正在审查的 CL 中的
shelved文件
2. 获取 PR/MR/CL 详情
GitHub:
gh pr view <PR_NUMBER> --json title,body,state,reviews,comments,headRefName,headRefOid,statusCheckRollup
OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
gh api "repos/$OWNER_REPO/pulls/<PR_NUMBER>/comments"
gh api --paginate "repos/$OWNER_REPO/issues/<PR_NUMBER>/comments?per_page=100"
GitHub PR 同时也是 issue,因此常规 PR 评论位于 issue 评论端点。Greptile 可能会在每轮审查中编辑一条常规 PR 评论,而不是创建新的审查或评论。得出 PR 没有问题的结论前,务必按 updated_at 检查 Greptile 撰写的最新常规评论,包括其中的 "Prompt to fix all with AI" 部分。
GitLab:
glab mr view <MR_IID> --output json
# Fetch discussions (inline diff comments are type "DiffNote"; general comments have null type)
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions"
对于 GitLab,如果需要,请对讨论进行分页(添加 ?per_page=100&page=N)。
Perforce:
# Get changelist description, files, and status
p4 describe -s <CL_NUMBER>
# Get shelved files (for in-review CLs)
p4 describe -S <CL_NUMBER>
# Get the diff of the shelved changelist
p4 diff2 //...@=<CL_NUMBER> //...@=<CL_NUMBER>
# List review comments (if using p4 review workflow)
p4 review -c <CL_NUMBER>
Perforce CL 的主要字段:
Change:变更列表编号Status:pending、submitted、shelvedDescription:CL 描述/提交消息Files:CL 中的文件列表
3. 等待待处理检查完成
分析之前,确保所有状态检查均已完成。如果有检查处于 PENDING 或 IN_PROGRESS(GitHub)/running 或 pending(GitLab)状态,则每隔 30 秒轮询一次,直到所有检查都达到终止状态。
**GitHub:**通过 gh pr view 轮询 statusCheckRollup。
GitLab:
glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines"
流水线状态:running、pending、success、failed、canceled、skipped。持续轮询,直到没有流水线处于 running 或 pending 状态。
**Perforce:**Perforce 原生没有内置 CI 检查。如果团队使用审查工具(Swarm 等)或由搁置事件触发的外部 CI,请检查相关系统。否则,立即继续分析。
4. 要求针对当前 head 进行新的 Greptile 审查
对于 GitHub PR,除非现有 Greptile 审查、评论或摘要与 PR 的当前 headRefOid 完全一致,否则不要将其视为最新内容。向现有 PR 推送新提交后,这一点尤为重要:针对较早提交的 Greptile 审查已过时,即使 PR 中仍有 Greptile 评论或之前的审查也不例外。
在 Greptile 检查前立即获取当前 head SHA:
HEAD_SHA=$(gh pr view <PR_NUMBER> --json headRefOid -q .headRefOid)
然后检查该提交的检查运行,并要求 Greptile 运行已完成:
OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
GREPTILE_CHECKS=$(gh api "repos/$OWNER_REPO/commits/$HEAD_SHA/check-runs?per_page=100" \
--jq '[.check_runs[] | select(.name | test("greptile"; "i"))]')
# A run only counts as a valid fresh pass when it has completed AND concluded cleanly.
# GitHub check-run conclusions: success, neutral, skipped, failure, timed_out,
# cancelled, action_required, stale. Treat success/neutral as clean;
# everything else (especially failure and action_required) must block.
FRESH_GREPTILE_COMPLETED=$(echo "$GREPTILE_CHECKS" \
| jq '[.[] | select(.status == "completed")] | length')
FRESH_GREPTILE_CLEAN=$(echo "$GREPTILE_CHECKS" \
| jq '[.[] | select(.status == "completed" and (.conclusion | IN("success","neutral")))] | length')
FRESH_GREPTILE_BLOCKING=$(echo "$GREPTILE_CHECKS" \
| jq '[.[] | select(.status == "completed" and ((.conclusion | IN("success","neutral")) | not))] | length')
if [ "$FRESH_GREPTILE_COMPLETED" = "0" ]; then
echo "Blocked: no completed Greptile review/check is tied to current PR head $HEAD_SHA."
echo "Request a fresh Greptile review against this head before marking the PR check done."
echo "Suggested trigger: gh pr comment <PR_NUMBER> --body \"@greptile review\""
exit 1
fi
if [ "$FRESH_GREPTILE_BLOCKING" != "0" ] || [ "$FRESH_GREPTILE_CLEAN" = "0" ]; then
echo "Blocked: Greptile completed on head $HEAD_SHA but did not conclude clean"
echo "(conclusion was failure/action_required/timed_out/cancelled/stale, or no clean run exists)."
echo "Address the findings, push, and re-run Greptile until it concludes success/clean on the new head."
exit 1
fi
如果当前 head 存在 Greptile 检查,但仍处于待处理或进行中状态,请使用 greploop 中相同的轮询模式等待,而不要依据较早的审查材料继续操作。如果等待合理时长后,当前 head 仍未出现 Greptile 检查,请报告 PR 因等待针对 HEAD_SHA 的新 Greptile 审查而受阻,并停止操作。不得依据 PR 评论、PR 审查,或无法关联到当前 head SHA 的 Greptile 摘要,将检查标记为已完成。
对于集成了 Greptile 的 GitLab 安装环境,针对 MR 当前 head SHA 应遵循相同的时效规则:
# 1. Get the MR's current head SHA
MR_SHA=$(glab mr view <MR_IID> --output json | jq -r '.sha // .diff_refs.head_sha')
# 2. Find the latest pipeline for that EXACT sha, then the Greptile job within it.
LATEST_PIPELINE_ID=$(glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines" \
| jq -r --arg sha "$MR_SHA" '[.[] | select(.sha == $sha)] | sort_by(.id) | last | .id // empty')
if [ -n "$LATEST_PIPELINE_ID" ]; then
GREPTILE_JOBS=$(glab api "projects/:fullpath/pipelines/$LATEST_PIPELINE_ID/jobs" \
| jq --arg sha "$MR_SHA" '[.[] | select(.name | test("greptile"; "i"))
| {name, status, pipeline_sha: $sha}]')
else
GREPTILE_JOBS='[]'
fi
GREPTILE_JOB_SUCCESS=$(echo "$GREPTILE_JOBS" \
| jq '[.[] | select(.status == "success")] | length')
GREPTILE_JOB_BLOCKING=$(echo "$GREPTILE_JOBS" \
| jq '[.[] | select(.status != "success")] | length')
# 3. If Greptile integrates via MR notes instead of a CI job, require the newest
# Greptile note to reference the current head sha and report a clean review.
GREPTILE_NOTES=$(glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100" \
| jq --arg sha "$MR_SHA" '[.[].notes[]
| select(.author.username | test("greptile"; "i"))]
| sort_by(.updated_at // .created_at)')
GREPTILE_NOTE_CLEAN=$(echo "$GREPTILE_NOTES" \
| jq --arg sha "$MR_SHA" 'if length == 0 then 0
elif ((last.body // "") | contains($sha) and test("Confidence Score:[[:space:]]*5/5|Confidence:[[:space:]]*5/5|\\b5/5\\b"; "i") and (test("Prompt To Fix|blocking issue|failed|action required"; "i") | not)) then 1
else 0 end')
if [ "$GREPTILE_JOB_SUCCESS" = "0" ] && [ "$GREPTILE_NOTE_CLEAN" = "0" ]; then
echo "Blocked: no successful Greptile job or completed-clean current-head Greptile note is tied to MR head $MR_SHA."
exit 1
fi
if [ "$GREPTILE_JOB_BLOCKING" != "0" ]; then
echo "Blocked: at least one Greptile job for MR head $MR_SHA did not succeed."
exit 1
fi
如果对于 MR_SHA 出现以下情况,则阻止完成:(a) 完全没有 Greptile 作业或备注(缺失);(b) 最新的 Greptile 作业/备注关联到不同的 SHA(过时);或 (c) Greptile 作业状态不是 success。针对不同 SHA 的已完成 Greptile 结果已过时,必须阻止完成。
对于集成了 Greptile 的 Perforce 安装环境,使用 CL 当前搁置修订的标识以及与其关联的 Greptile webhook/审查产物应用相同规则;针对较早搁置版本的 Greptile 结果已过时,必须阻止完成。
5. 分析 PR/MR
所有检查完成后,评估以下方面:
A. 状态检查
- 所有 CI 检查是否都已通过?
- 如果有检查失败,请指出具体失败项及失败原因。
B. PR/MR 描述
- 描述是否完整且符合团队规范?
- 所有必填部分是否都已填写?
- 是否有需要更新的 TODO 或占位内容?
C. 审查评论
- 需要处理的内联代码审查评论
- 查找机器人审查评论(例如 GitHub 上来自
greptile-apps[bot]的评论,或 GitLab 上 Greptile 机器人用户的评论、代码检查工具的评论等) - 人工审查者的评论
- **Perforce:**来自
p4 review或外部审查工具的审查评论
D. 一般评论
- PR/MR 上的讨论评论
- 对于 GitHub,检查 issue 评论端点,并使用
updated_at捕捉原地编辑过的机器人评论。即使没有新的内联评论,Greptile 最新编辑的摘要也可能包含可执行事项。 - 机器人评论(部署预览等)——通常仅供参考
- **Perforce:**CL 描述应包含清晰的摘要、受影响文件的理由说明和测试备注
6. 问题分类
对发现的每个问题进行分类:
| 类别 | 含义 |
|---|---|
| 需处理 | 需要进行代码更改、改进测试或修复 |
| 仅供参考 | 验证备注、问题或供参考的信息,无需更改 |
| 已处理 | 后续提交似乎已解决的问题 |
7. 报告发现
提供摘要表:
| 方面 | 问题 | 状态 | 需要采取的措施 |
|---|---|---|---|
| 状态检查 | CI 构建失败 | 失败 | 修复 src/api.ts 中的类型错误 |
| 审查 | “添加空值检查” - @reviewer | 需处理 | 添加保护子句 |
| 描述 | 测试计划中有 TODO 占位内容 | 需处理 | 填写测试计划 |
| 审查 | “看起来不错” - @teammate | 仅供参考 | 无 |
8. 修复问题(如有要求)
如果存在需处理的事项:
- 如果尚未切换到 PR/MR 分支(git),请切换过去;如果是 Perforce,请确保文件已在正确的 CL 中打开。
- 询问用户是否希望修复这些问题。
- 如果用户同意,进行修复,然后:
**GitHub/GitLab:**提交并推送:
git add <files>
git commit -m "address review feedback"
git push
**Perforce:**打开文件以供编辑,进行更改,然后重新搁置:
p4 edit <file>
# make changes
p4 shelve -f -c <CL_NUMBER>
9. 解决评审讨论串
处理完评论后,解决相应的评审讨论串。
Perforce - Perforce 没有原生的“解决讨论串”概念。相反,可以通过更新 CL 描述,或在使用的评审工具(Swarm 等)中回复,将评论标记为已处理。如果使用 p4 review:
# Mark files as reviewed after addressing feedback
p4 review -c <CL_NUMBER>
GitHub - 获取尚未解决的讨论串 ID(必要时分页 - 参见GraphQL 参考):
gh api graphql -f query='
query($cursor: String) {
repository(owner: "OWNER", name: "REPO") {
pullRequest(number: PR_NUMBER) {
reviewThreads(first: 100, after: $cursor) {
pageInfo { hasNextPage endCursor }
nodes {
id
isResolved
comments(first: 1) {
nodes { body path }
}
}
}
}
}
}'
如果 hasNextPage 为 true,使用 -f cursor=ENDCURSOR 重复执行,以获取剩余讨论串。
然后解决已处理或仅供参考的讨论串:
gh api graphql -f query='
mutation {
resolveReviewThread(input: {threadId: "THREAD_ID"}) {
thread { isResolved }
}
}'
使用别名(t1、t2 等)将多个解决操作合并到一次 mutation 中。
GitLab - 获取尚未解决的讨论(参见 GitLab API 参考):
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100"
筛选 "resolved": false 的讨论。收集每个讨论的 id。
逐个解决每个讨论(GitLab 不支持批量解决):
glab api --method PUT \
"projects/:fullpath/merge_requests/<MR_IID>/discussions/<DISCUSSION_ID>" \
--field resolved=true
对每个尚未解决的讨论 ID 重复此操作。
10. 多个 PR/MR/CL
如果要检查一系列 PR/MR/CL,请按顺序处理。
Perforce - 一次检查多个变更列表:
p4 changes -s pending -u $P4USER -c $P4CLIENT -l
输出格式
总结:
- PR/MR/CL 标题或描述及当前状态
- 检测到的平台(GitHub / GitLab / Perforce)
- 状态检查摘要(通过/失败/待处理)- Perforce 则填写 N/A
- 发现的问题总数
- 可执行的事项及其描述
- 可忽略的事项及原因
- 建议的后续步骤