Onyx 仓库实战:用 Greptile check-pr 技能实现 GitHub / GitLab / Perforce 全平台 PR 自动检查与修复
【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer
导读
本篇文章围绕 Onyx(danswer)开源仓库中内置的.cursor/skills/greptile/check-prAgent 技能(SKILL.md),完整讲解如何让 AI Agent 自动检查 GitHub Pull Request、GitLab Merge Request 与 Perforce shelved changelist 中的未解决评审评论、失败状态检查与不完整的 PR 描述,并在征得同意后自动修复问题、解决评审线程。读完本文,你将掌握一套可复用的"检测平台 → 识别变更 → 等待检查 → 分类问题 → 报告 → 修复 → 解决线程"的自动化 PR 审查闭环方法论,并能直接在本仓库的 Agent 环境(Cursor / Claude Code 等)中按需触发。
一、技能概览与运行前提
check-pr是 Greptile 提供的三个 Agent 技能之一(另外两个为 cli-review 与 greploop,三者共同构成完整的自动化评审能力),其核心职责是:
- 检查 GitHub Pull Request / GitLab Merge Request / Perforce shelved changelist 的评审评论、状态检查与描述完整性;
- 等待 pending 中的检查全部进入终态;
- 将发现的问题归类为 actionable(需行动)与 informational(仅告知);
- 在用户授权后自动修复并解决对应评论线程。
该技能通过 sync-vendored-skills.sh 从 Greptile 上游仓库以git read-tree方式整体 vendor 到.cursor/skills/greptile/,CI 每周自动同步,版本为 1.3,许可证为 MIT。
运行前提(compatibility)
技能头部元数据明确声明了环境要求:
| 平台 | 必需 CLI | 认证方式 |
|---|---|---|
| GitHub | git+gh | gh auth login |
| GitLab | git+glab | glab auth login |
| Perforce | p4 | 配置P4PORT/P4USER/P4CLIENT |
技能通过allowed-tools声明其仅被允许调用Bash(gh:*)、Bash(glab:*)、Bash(git:*)、Bash(p4:*)四类命令,这是一条重要的安全边界:Agent 不会在评审流程中执行任意系统命令。
输入
技能唯一的输入是PR/MR/CL 编号(可选)。未提供编号时,技能会自动探测当前分支对应的 PR/MR,或 Perforce 的默认 pending changelist。调用方式为/check-pr 123或在 Agent 中自然语言描述需求。
二、第一步:平台自动检测
check-pr 与 greploop 都会在开始前自动判定当前仓库所属的版本控制系统。检测顺序如下(SKILL.md 第 0 节):
# 检查是否为 Perforce 环境 if p4 info >/dev/null 2>&1; then VCS="perforce" else # 回退到 git remote 检测 REMOTE_URL=$(git remote get-url origin) if echo "$REMOTE_URL" | grep -qi "gitlab"; then VCS="gitlab" else VCS="github" fi fi判定逻辑分两级:
- Perforce 优先:若
p4 info能成功执行(说明存在.p4config文件或P4CLIENT/P4PORT环境变量),判定为 perforce; - Git remote 兜底:否则读取
git remote get-url origin,URL 中含 "gitlab"(忽略大小写)判定为 gitlab,其余默认 github。
覆盖机制:自托管 GitLab 实例的主机名若不包含 "gitlab",或 Perforce 自动检测失败,用户可通过传入--vcs gitlab/--vcs perforce显式覆盖检测结果。
三、识别 PR/MR/CL:三种平台的编号语义差异
技能支持用户直接传入编号,否则按平台执行自动探测:
GitHub:
gh pr view --json number -q .numberGitLab:
glab mr view --output json | jq '.iid'Perforce:
# 列出当前用户/client 下的 pending changelists p4 changes -s pending -u $P4USER -c $P4CLIENT关键字段在平台间的映射关系是理解后续 API 调用的基础:
| 语义 | GitHub | GitLab | Perforce |
|---|---|---|---|
| 变更编号 | number | iid(内部编号,非id) | changelist 编号(CL) |
| 源分支 | headRefName | source_branch | — |
| HEAD 提交 | headRefOid | sha | — |
| 描述/正文 | body | description | Description |
| 评审中文件 | — | — | shelved文件 |
特别要注意 GitLab 的iid与全局id的区别:所有 GitLab API 调用必须使用iid。这一字段对照表同样出现在 GitLab API 参考 中。
四、拉取 PR/MR/CL 详情:REST 与 GraphQL 双通道
GitHub
gh pr view <PR_NUMBER> --json title,body,state,reviews,comments,headRefName,statusCheckRollup 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 上的普通评论(general comment)存放在 issue comments 端点,而pulls/{n}/comments只返回行内评论。另外,Greptile 在每个评审周期可能编辑同一条普通评论而不是新建评论,因此必须按updated_at而非created_at取最新版本,且在判定 "PR 已干净" 之前必须检查其 "Prompt to fix all with AI" 区块。
GitLab
glab mr view <MR_IID> --output json # 拉取 discussions(行内 diff 评论 type 为 "DiffNote",普通评论 type 为 null) glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions"glab api会自动把:fullpath解析为本地 git remote 对应 URL 编码后的项目路径。discussions 需要时按?per_page=100&page=N分页。
Perforce
# 获取 changelist 的描述、文件与状态 p4 describe -s <CL_NUMBER> # 获取 shelved 文件(评审中的 CL) p4 describe -S <CL_NUMBER> # 获取 shelved changelist 的 diff p4 diff2 //...@=<CL_NUMBER> //...@=<CL_NUMBER> # 列出评审评论(使用 p4 review 工作流时) p4 review -c <CL_NUMBER>Perforce 的 CL 关键字段:Change(编号)、Status(pending/submitted/shelved)、Description(CL 描述/提交信息)、Files(文件清单)。
五、等待 pending 检查完成:轮询策略与超时保护
在分析之前,必须等待所有状态检查进入终态,否则会把"尚未出结果"误判为"通过"。技能给出的策略是每 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:原生没有内置 CI 检查。若团队使用 Swarm 等评审工具或由 shelve 事件触发的外部 CI,需查询对应系统;否则直接进入分析阶段(状态检查记为 N/A)。
从 greploop/SKILL.md 可以看到同族技能更完整的轮询实现:通过gh api repos/{owner}/{repo}/commits/$HEAD_SHA/check-runs按 commit SHA 拉取 check-run,以status = "completed"作为终止条件,并设置了MAX_ATTEMPTS=60、POLL_INTERVAL_SECONDS=10的约 10 分钟超时保护——超时即停止工作流并如实报告,绝不基于过期或缺失的评审结果继续。check-pr 采用同样的超时纪律(30 秒间隔)。
六、PR 分析清单:四个评估维度
检查全部完成后,技能从四个维度评估变更:
A. 状态检查(Status Checks)
- 所有 CI 检查是否通过?
- 若有失败项,定位是哪些检查、失败原因是什么。
B. PR/MR 描述(Description)
- 描述是否完整、是否符合团队规范?
- 必需段落是否全部填写?
- 是否存在需要更新的 TODO 或占位符?
C. 评审评论(Review Comments)
- 需要处理的行内代码评审评论;
- 机器人评审评论(GitHub 上的
greptile-apps[bot]、GitLab 上的 Greptile bot 用户、各类 linter 等); - 人工评审者的评论;
- Perforce 场景下来自
p4 review或外部评审工具的评论。
D. 普通评论(General Comments)
- PR/MR 上的讨论评论;
- GitHub 需检查 issue comments 端点并用
updated_at捕捉原地编辑过的 bot 评论——Greptile 最新编辑过的摘要即使在没有新行内评论时也可能包含可执行事项; - bot 评论(如部署预览)通常仅作告知;
- Perforce 的 CL 描述应包含清晰摘要、受影响文件理由与测试说明。
七、问题分类:Actionable / Informational / Already addressed
对发现的每个问题,技能强制使用统一分类口径,避免把"告知性内容"误当成必须修改的缺陷:
| 分类 | 含义 |
|---|---|
| Actionable | 需要代码修改、测试改进或修复 |
| Informational | 验证说明、问题或仅供知会,无需改动 |
| Already addressed | 后续提交似乎已解决的问题 |
八、报告输出:结构化的汇总表
技能要求以汇总表形式呈现检查结论,示例格式如下:
| Area | Issue | Status | Action Needed |
|---|---|---|---|
| Status Checks | CI build failing | Failing | Fix type error insrc/api.ts |
| Review | "Add null check" — @reviewer | Actionable | Add guard clause |
| Description | TODO placeholder in test plan | Actionable | Fill in test plan |
| Review | "Looks good" — @teammate | Informational | None |
最终输出还应包含:PR/MR/CL 标题或描述与当前状态、检测到的平台(GitHub / GitLab / Perforce)、状态检查汇总(通过/失败/等待中,Perforce 记为 N/A)、问题总数、可执行事项及描述、可忽略事项及理由、建议的下一步操作。
九、修复问题与解决评审线程
修复流程(需用户授权)
- 切换到 PR/MR 的分支(git),或确保文件已在正确的 CL 中打开(Perforce);
- 先询问用户是否要修复;
- 用户同意后执行修复。
GitHub / GitLab:提交并推送:
git add <files> git commit -m "address review feedback" git pushPerforce:打开文件编辑后强制重新 shelve:
p4 edit <file> # 修改内容 p4 shelve -f -c <CL_NUMBER>解决评审线程
GitHub——通过 GraphQL 拉取未解决线程 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 } } }'批量解决是 GitHub 的杀手锏能力:利用 GraphQL alias(t1、t2…)在单次 mutation 中解决多个线程。完整的三线程示例见 graphql-queries.md。
GitLab——拉取未解决 discussions(参考 GitLab API 参考):
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100"筛选"resolved": false的 discussion,收集每个id。GitLab没有批量解决能力,必须逐个解决:
glab api --method PUT \ "projects/:fullpath/merge_requests/<MR_IID>/discussions/<DISCUSSION_ID>" \ --field resolved=truePerforce——没有原生的 "resolve thread" 概念。处理完评论后,通过更新 CL 描述或在所用评审工具(Swarm 等)中回复来标记已处理;使用p4 review时执行:
p4 review -c <CL_NUMBER>十、进阶补充:评论筛选与 Greptile 评分解析
check-pr 的配套参考文件提供了两个高价值技巧,值得单独提炼:
1. 定位 Greptile 原地编辑过的汇总评论(GitHub)
gh api --paginate "repos/{owner}/{repo}/issues/<PR_NUMBER>/comments?per_page=100" \ | jq -s 'add | map(select(.user.login | test("greptile"; "i"))) | sort_by(.updated_at) | last | {author: .user.login, updated_at, body}'先过滤 Greptile 作者,再按updated_at排序取最后一条——这正是"原地编辑而非新建评论"场景下的正确取数方式。
2. 筛选未解决的行内 diff 评论(GitLab)
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100" | \ jq '[.[] | select(.resolved == false and (.notes[0].type == "DiffNote"))]'配合 note 对象字段(type、author.username、body、position.new_path),可在本地精准还原"谁在哪个文件、哪个 diff 位置、留下了什么未解决评论"。
3. 与 greploop 的协同
check-pr 解决单次评审;若希望迭代直至 Greptile 给出 5/5 置信度且零未解决评论,应使用 greploop。它会重复"推送/shelve → 触发@greptile review→ 轮询 check-run → 拉取评分(从 PR 描述、普通评论、PR reviews 三个来源取最新)→ 修复 → 解决 → 再推送"的循环,最大 5 轮,并输出包含平台、迭代次数、最终置信度、解决/剩余评论数的结构化报告。
十一、多个 PR/MR/CL 与使用边界
链式变更处理
若需要检查一列相互依赖的 PR/MR/CL,按顺序逐个处理。Perforce 批量查看多个 pending changelist:
p4 changes -s pending -u $P4USER -c $P4CLIENT -l使用边界与适用前提
- 本技能解决的是"评审状态管理",而非"评审本身":它负责发现未解决评论、失败检查、不完整描述,并提供修复与解决线程的自动化管线;深度代码评审能力由 Greptile 服务本身及 greploop/cli-review 承担。
- 依赖
gh/glab/p4已安装并完成认证,Perforce 还要求正确的P4CLIENT工作区。 - 自托管 GitLab 需按前述
--vcs gitlab覆盖规则处理。 - 仓库中的 Cursor 技能目录由 sync-vendored-skills.sh 管理,要求同步时工作区干净(
git diff-index --quiet HEAD),避免同步提交与本地改动混杂。
总结
check-pr 技能为 Onyx 仓库的日常开发提供了一个可审计、可重复的 PR 提交前检查管线:从平台探测、编号识别、详情拉取、检查等待,到四维分析、三态分类、表格报告、授权修复与线程解决,全部环节都有明确的 CLI/API 依据(gh、glab、p4与 GitHub GraphQL / GitLab REST)。配合 GraphQL 查询参考、GitLab API 参考 两份参考文件,开发者可以按需将其中任意环节移植为自己的自动化脚本,或直接在本仓库的 Agent 中通过/check-pr <编号>触发,让"评审反馈清零"成为可量化的工程纪律。
【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考