- 后端
- 工作流自动化
- 流程编排
- 低代码
【免费下载链接】elsa-core
The Workflow Engine for .NET
本篇文章围绕 elsa-core 仓库.claude/skills/greploop技能中沉淀的 GitLab REST API 参考,系统讲解如何用glab api完成「获取 MR 详情 → 触发 Greptile 审查 → 轮询 Pipeline/Job → 提取置信度分数 → 获取并逐个解决未解决讨论」的完整审查闭环。读完你可以直接把这套命令套用到自己的 GitLab 项目上,将 Greptile 的代码审查从手动操作升级为可脚本化的自动迭代循环。
1. 背景:greploop 技能中的 GitLab 支线
greploop是仓库内置的一个 Claude 技能(定义见 SKILL.md),目标非常明确:迭代改进一个 PR(GitHub)/ MR(GitLab)/ CL(Perforce),直到 Greptile 给出 5/5 置信度评分且零未解决评论。它会在触发 Greptile 审查、修复全部可执行评论、推送(或 re-shelve)、再次触发审查之间循环,最多迭代 5 次,避免失控死循环。
技能按平台分三条支线,GitLab 支线完全基于本参考文档所覆盖的 REST API 调用。与它配合的还有 GraphQL 查询参考,后者专门服务 GitHub 支线的reviewThreads查询与resolveReviewThread批量解决,而 GitLab 支线因 REST API 不支持批量解决,需要逐条 PUT(详见第 12 节)。
整个技能以 MIT 协议开源(见 LICENSE),依赖已认证的git、gh或glabCLI,以及仓库上已安装的 Greptile 集成。
2. 前置准备:glab CLI 与:fullpath魔法变量
所有命令都通过 GitLab 官方 CLIglab执行,其glab api子命令可以直接向 GitLab REST API 发请求。一个关键便利点是:
glab api会自动把:fullpath解析为从本地 git remote 读取的、经 URL 编码的项目路径。
这意味着你不需要手写projects/{owner}%2F{repo}这样的编码路径,直接写projects/:fullpath即可,前提是当前目录位于已配置 remote 的 Git 仓库内(例如本仓库根目录)。
技能在平台检测阶段(SKILL.md 第 0 步)用如下方式识别 GitLab:
REMOTE_URL=$(git remote get-url origin) if echo "$REMOTE_URL" | grep -qi "gitlab"; then VCS="gitlab" fi对于自建 GitLab 实例、主机名不含 "gitlab" 的情况,可以通过给技能传入--vcs gitlab显式覆盖。后续所有命令统一使用glab mr/glab api而非gh。
3. 获取 MR 详情:glab mr view
审查闭环的第一步是拿到 MR 的元数据,命令为:
glab mr view <MR_IID> --output json<MR_IID>是 MR 在项目内部的编号(Internal ID)。该命令输出的 JSON 中有四个关键字段,后续流程都依赖它们:
| 字段 | 含义 | 与 GitHub 的对应关系 |
|---|---|---|
iid | MR 内部编号,后续所有接口都用它,不要用全局id | GitHub 的number |
source_branch | 源分支名 | GitHub 的headRefName |
sha | HEAD 提交的 SHA | GitHub 的headRefOid |
description | MR 描述正文,Greptile 可能把置信度分数更新到这里 | GitHub 的body |
在 SKILL.md 第 1 步中,识别当前分支对应的 MR 时,就是用glab mr view加 jq 精简输出:
glab mr view --output json | jq '{iid: .iid, branch: .source_branch}'拿到sha后,它与后续「按 commit SHA 定位 Pipeline」(第 7 节)直接衔接,是轮询循环中定位最新审查结果的关键锚点。
4. 触发 Greptile 审查:glab mr note
触发一次审查本质上就是在 MR 上发一条评论:
glab mr note <MR_IID> --message "@greptile review"glab mr note会向projects/:fullpath/merge_requests/<MR_IID>/notes追加一条评论。但不要盲目每次都触发:Greptile 对同一 commit 的重复审查是浪费。SKILL.md 中的防护逻辑是:先查 MR 关联的 pipeline,若有running/pending状态的 pipeline 就不重复发评论:
PIPELINES=$(glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines") GREPTILE_RUNNING=$(echo "$PIPELINES" | jq '[.[] | select(.status == "running" or .status == "pending")] | length') if [ "$GREPTILE_RUNNING" = "0" ]; then glab mr note <MR_IID> --message "@greptile review" fi这条防抖逻辑正是第 5 节「检查是否有 Pipeline 在运行」命令的实际用途。
5. 查询 MR 关联的 Pipeline 列表
MR 与 CI pipeline 是一对多的关系,接口为:
glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines"响应是 pipeline 对象数组,需要重点检查的status字段取值包括:
running— 正在运行pending— 排队等待success— 成功failed— 失败canceled— 已取消skipped— 被跳过
该接口同时服务于「防重复触发」(第 4 节)和「按 SHA 定位最新 pipeline」(第 7 节)两个场景。
6. 检查是否有 Pipeline 在运行
一个更直接的判断命令,输出「正在运行/排队中的 pipeline 数量」:
glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines" | \ jq '[.[] | select(.status == "running" or .status == "pending")] | length'- 返回
0:没有 pipeline 在运行/排队,可以放心触发新审查。 - 返回
> 0:已有审查在进行,应等待其完成,避免重复触发。
7. 按 commit SHA 定位最新 Pipeline
一个 MR 通常关联多条 pipeline(每次 push 都会生成新的),而 Greptile 的审查针对的是最新一次提交。因此需要按当前 HEAD 的sha精确过滤,并取id最大(最新)的那条:
glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines" | \ jq -r --arg sha "COMMIT_SHA" '[.[] | select(.sha == $sha)] | sort_by(.id) | last | .id // empty'拆解这条 jq 表达式:
--arg sha "COMMIT_SHA":把外部变量传入 jq,避免字符串拼接的转义问题;select(.sha == $sha):只保留与目标 SHA 一致的 pipeline;sort_by(.id) | last:按 id 升序后取最后一条,即最新 pipeline;// empty:若过滤结果为空则输出空值,方便脚本做「还没出现,继续等待」的判断。
实际使用中COMMIT_SHA直接来自第 3 节的glab mr view <MR_IID> --output json | jq -r '.sha'。
8. 获取 Pipeline 的 Jobs,定位 Greptile Job
定位到 pipeline 之后,需要进一步找到其中的 Greptile 任务:
glab api "projects/:fullpath/pipelines/<PIPELINE_ID>/jobs"然后用 jq 按任务名过滤(大小写不敏感):
glab api "projects/:fullpath/pipelines/<PIPELINE_ID>/jobs" | \ jq '.[] | select(.name | test("greptile"; "i"))'GitLab 的test("greptile"; "i")即正则匹配且忽略大小写。对 Greptile job 来说,只有以下三种是终态,脚本遇到它们就可以停止轮询:
successfailedcanceled
9. 轮询闭环:等待 Greptile 审查完成
把第 3、7、8 节组合起来,就是 SKILL.md GitLab 支线中完整的「推送后等待 Greptile 审查」轮询脚本:
HEAD_SHA=$(glab mr view <MR_IID> --output json | jq -r '.sha') while true; do PIPELINES=$(glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines") # 找到该 SHA 对应的最新 pipeline PIPELINE_ID=$(echo "$PIPELINES" | jq -r --arg sha "$HEAD_SHA" \ '[.[] | select(.sha == $sha)] | sort_by(.id) | last | .id // empty') if [ -z "$PIPELINE_ID" ]; then echo "Waiting for Greptile pipeline to appear..." sleep 5 continue fi JOBS=$(glab api "projects/:fullpath/pipelines/$PIPELINE_ID/jobs") GREPTILE_JOB=$(echo "$JOBS" | jq '.[] | select(.name | test("greptile"; "i"))') if [ -z "$GREPTILE_JOB" ]; then echo "Waiting for Greptile job to appear..." sleep 5 continue fi JOB_STATUS=$(echo "$GREPTILE_JOB" | jq -r '.status') if [ "$JOB_STATUS" = "success" ] || [ "$JOB_STATUS" = "failed" ] || [ "$JOB_STATUS" = "canceled" ]; then echo "Greptile job completed with: $JOB_STATUS" break fi echo "Waiting for Greptile... (status: $JOB_STATUS)" sleep 10 done该循环的三个阶段清晰可辨:pipeline 未出现(5 秒重试)→job 未出现(5 秒重试)→job 进行中(10 秒重试),直到 job 进入终态。这是整个 GitLab 支线的时间轴主干,其余命令都是在它完成之后读取审查产物。
10. 提取 Greptile 置信度分数:查询 MR Notes
Greptile 的评分可能出现在两个地方,GitLab 支线需要同时检查:MR 描述(glab mr view的description字段)和 MR 评论。查询评论用:
glab api "projects/:fullpath/merge_requests/<MR_IID>/notes?per_page=100&sort=desc&order_by=created_at"参数含义:
per_page=100:单页最多 100 条,防止长讨论页截断;sort=desc&order_by=created_at:按创建时间倒序,最新的评论排在最前。
过滤与扫描逻辑:
- 用
author.username过滤出 Greptile bot 的评论; - 在
body中扫描置信度模式,形如3/5或5/5(也可能带前缀,如Confidence: 3/5)。
参考文档特别提醒一个易踩的坑:
GitLab 上 Greptile bot 的用户名可能与 GitHub 的
greptile-apps[bot]不同——先在 MR 的第一条 Greptile 评论里确认确切的用户名。
因此脚本中不应硬编码用户名,而应在首次运行时探测。当两个来源(MR description 与 notes)都有分数时,取时间上更新的那个。
11. 获取未解决的 Diff 讨论(内联评论)
除了整体置信度,Greptile 还会以「讨论(discussion)」的形式留下内联 diff 评论。接口为:
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100"分页策略:用&page=2、&page=3…… 依次翻页,直到某次响应数组长度小于per_page,说明已到最后一页。
过滤出 Greptile 的未解决内联评论:
jq '[.[] | select(.resolved == false and (.notes[0].type == "DiffNote") and (.notes[0].author.username == "GREPTILE_BOT_USERNAME"))]'每个 discussion 对象有三个关键字段:
| 字段 | 用途 |
|---|---|
id | 解决该讨论时使用的标识 |
notes[0].body | 评论正文(即 Greptile 的审查意见) |
notes[0].position.new_path | 评论所在的文件路径 |
其中type == "DiffNote"表示这是挂在 diff 行上的内联评论,resolved == false表示尚未解决,author.username对应第 10 节探测到的 Greptile bot 用户名。SKILL.md 还补充了notes[0].type与「最新提交」的判断要求,确保只处理针对当前版本的评论。
12. 解决一条讨论:PUTdiscussions/:id
拿到未解决讨论的id后,逐个标记为已解决:
glab api --method PUT \ "projects/:fullpath/merge_requests/<MR_IID>/discussions/<DISCUSSION_ID>" \ --field resolved=true要点:
--method PUT:覆盖glab api默认的 GET 动词;--field resolved=true:以表单字段形式提交,等价于PUT ...?resolved=true;- GitLab 没有批量解决接口——必须对每个 discussion
id各发一次 PUT,SKILL.md 中通过 for 循环逐条处理:
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100"过滤出"resolved": false的讨论后,对每个 id 重复上面的 PUT 即可。注意这不同于 GitHub 支线用 GraphQL 的resolveReviewThreadmutation 批量解决——GitLab REST API 没有等价能力,只能逐个来。
13. 完整闭环:GitLab 支线的 greploop 迭代
把以上所有命令串起来,一次完整的 GitLab 迭代循环如下:
- 识别 MR:
glab mr view --output json | jq '{iid, branch}',并切换到source_branch; - 推送最新改动:
git push,然后sleep 5等待 CI 触发; - 防抖触发:检查运行中 pipeline 数量,为 0 才执行
glab mr note <MR_IID> --message "@greptile review"; - 轮询审查:按第 9 节循环,直到 Greptile job 进入
success/failed/canceled; - 读取结果:从 MR
description与 notes 中提取最新置信度分数(3/5、5/5等),从 discussions 中收集未解决的内联评论; - 判定退出:置信度达到
5/5且未解决评论为 0,则循环结束;否则继续; - 修复评论:逐个读取
notes[0].position.new_path对应文件,判断评论是否可执行(需要改代码)还是仅提示性(记录后同样解决该讨论); - 解决讨论:对每个未解决 discussion 的
id执行一次第 12 节的 PUT; - 提交并推送,进入下一轮迭代:
git add -A git commit -m "address greptile review feedback (greploop iteration N)" git push循环最多 5 次(SKILL.md 中明确写有Max 5 iterations以规避失控循环)。
14. 汇报输出格式
循环退出后(无论达成 5/5 还是达到迭代上限),技能按固定格式汇报。达成目标的示例:
Greploop complete. Platform: GitLab Iterations: 2 Confidence: 5/5 Resolved: 7 comments Remaining: 0若因迭代上限退出,则如实列出剩余未解决评论及其位置:
Greploop stopped after 5 iterations. Platform: GitLab Confidence: 4/5 Resolved: 12 comments Remaining: 2 Remaining issues: - src/auth.ts:45 — "Consider rate limiting this endpoint" - src/db.ts:112 — "Missing index on user_id column"这份参考文档所覆盖的正是上述闭环中 GitLab 支线的全部 REST API 操作:1 个glab mr查看命令、1 个评论命令、6 类glab api查询、1 类带--method PUT的写操作,配合 jq 完成过滤、分页与轮询。如果你想把这套自动化搬进自己的 GitLab 仓库,直接复用本文所有命令块,替换MR_IID、PIPELINE_ID、DISCUSSION_ID与 Greptile bot 用户名即可;相关技能定义与配套参考可继续查阅 SKILL.md、gitlab-api.md 与 graphql-queries.md。
- 后端
- 工作流自动化
- 流程编排
- 低代码
【免费下载链接】elsa-core
The Workflow Engine for .NET
相关推荐
GitLab API 与 greploop 自动化评审循环:glab 命令、jq 过滤与流水线轮询实战参考
GitLab API 与 greploop 自动化评审循环:glab 命令、jq 过滤与流水线轮询实战参考 本篇文章以 .agents/skills/grepl
后端工作流自动化流程编排低代码danswer 仓库自动化评审实战:基于 glab 的 GitLab MR 讨论与流水线 API 速查
danswer 仓库自动化评审实战:基于 glab 的 GitLab MR 讨论与流水线 API 速查 在 AI 驱动的代码评审自动化场景中,GitLab Me
AI 应用大模型RAGAI Agent后端前端GitHub GraphQL 实战:分页抓取并批量解决 Pull Request 未解决评审线程(elsa-core 仓库 Greploop 技能参考全解)
GitHub GraphQL 实战:分页抓取并批量解决 Pull Request 未解决评审线程(elsa core 仓库 Greploop 技能参考全解) 本
后端工作流自动化流程编排低代码
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考