☰
以 glab api 驱动 GitLab 审查闭环:elsa-core 内置 greploop 技能的 GitLab REST API 实战参考
2026/9/28 18:37:07 网站建设 项目流程
  • 后端
  • 工作流自动化
  • 流程编排
  • 低代码

【免费下载链接】elsa-core

The Workflow Engine for .NET

项目地址:https://gitcode.com/gh_mirrors/el/elsa-core
点击查看免费下载

本篇文章围绕 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 的对应关系
iidMR 内部编号,后续所有接口都用它,不要用全局idGitHub 的number
source_branch源分支名GitHub 的headRefName
shaHEAD 提交的 SHAGitHub 的headRefOid
descriptionMR 描述正文,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 来说,只有以下三种是终态,脚本遇到它们就可以停止轮询:

  • success
  • failed
  • canceled

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:按创建时间倒序,最新的评论排在最前。

过滤与扫描逻辑:

  1. 用author.username过滤出 Greptile bot 的评论;
  2. 在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 没有批量解决接口——必须对每个 discussionid各发一次 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 迭代循环如下:

  1. 识别 MR:glab mr view --output json | jq '{iid, branch}',并切换到source_branch;
  2. 推送最新改动:git push,然后sleep 5等待 CI 触发;
  3. 防抖触发:检查运行中 pipeline 数量,为 0 才执行glab mr note <MR_IID> --message "@greptile review";
  4. 轮询审查:按第 9 节循环,直到 Greptile job 进入success/failed/canceled;
  5. 读取结果:从 MRdescription与 notes 中提取最新置信度分数(3/5、5/5等),从 discussions 中收集未解决的内联评论;
  6. 判定退出:置信度达到5/5且未解决评论为 0,则循环结束;否则继续;
  7. 修复评论:逐个读取notes[0].position.new_path对应文件,判断评论是否可执行(需要改代码)还是仅提示性(记录后同样解决该讨论);
  8. 解决讨论:对每个未解决 discussion 的id执行一次第 12 节的 PUT;
  9. 提交并推送,进入下一轮迭代:
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

项目地址:https://gitcode.com/gh_mirrors/el/elsa-core
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询