- 人工智能
- AI 应用
- 语音
- 音频
- 本地部署
- 桌面应用
【免费下载链接】auto-subs
On-device subtitle generation that connects directly to DaVinci Resolve, Premiere, and After Effects.
本文聚焦 auto-subs 仓库中 Greploop Agent 技能的 GitLab 侧 API 参考文档 gitlab-api.md。Greploop 是一个驱动 AI 代码评审机器人 Greptile 反复评审 PR/MR 直至拿到 5/5 置信度且零未解决评论的循环工作流,本文以 GitLab(glabCLI + GitLab REST API)为对象,完整讲解如何用glab api获取 MR 详情、轮询 pipeline/job 状态、从 MR notes 中解析置信度分数、抓取并逐条解决 Greptile 的 inline 讨论。读完本文,你可以把整套“触发评审 → 轮询完成 → 提取结果 → 修复 → 解决讨论 → 再触发”的闭环命令组合直接落地到自己的 GitLab 项目上。
1. 背景:greploop 循环与 GitLab API 参考的定位
Greploop 技能的完整定义见 SKILL.md,其核心是一个有限轮次的迭代循环:
- 触发 Greptile 评审(GitHub 发
@greptile review评论、GitLab 发 MR note、Perforce 重新 shelve); - 轮询评审完成状态(GitHub 用 check runs、GitLab 用 pipelines/jobs);
- 从 MR/PR 描述、评论、review 中解析置信度分数(如
3/5、5/5); - 修复所有可执行的 inline 评论;
- 解决所有已处理的讨论线程;
- 提交并推送,回到第 1 步。
退出条件在 SKILL.md 中写得很明确:置信度 5/5 且零未解决评论,或达到最多 5 次迭代上限(防止失控循环)。
references/目录为该循环提供了两个平台的 API 参考:GitHub 侧是 graphql-queries.md(GraphQL review threads 与批量 resolve),GitLab 侧即本文主体 gitlab-api.md(REST +glab api)。SKILL.md 的 GitLab 轮询伪代码中直接引用了后者(原文见 SKILL.md 第 164 行的 “see GitLab API reference”)。
2. 前提:glab api 与 :fullpath 占位符
GitLab 侧所有命令都通过glab api发起 REST 请求,文档开头给出的关键前提是:
glab apiautomatically resolves:fullpathto the URL-encoded project path from the local git remote.
即glab api会自动从本地 git remote 解析出 URL 编码后的项目路径,替换命令中的:fullpath占位符。你不需要手动拼接owner%2Frepo,这对以下场景尤其关键:
- 自托管 GitLab 实例(URL 编码规则可能与实例路径有关);
- 仓库路径中包含特殊字符或大小写混用的 group 名;
- 命令要在脚本中复用、不硬编码仓库标识的情况。
适用前提:本地目录是一个已配置origin远端的 git 工作区,且glab已完成认证(SKILL.md 的 compatibility 声明为 “Requires git, gh (GitHub CLI) or glab (GitLab CLI) authenticated, and Greptile installed on the repo”)。
另外注意一个平台映射关系(SKILL.md 中的 “Key field differences”):
| 概念 | GitHub 字段 | GitLab 字段 |
|---|---|---|
| MR/PR 内部编号 | number | iid(用这个,不是全局id) |
| 源分支 | headRefName | source_branch |
| HEAD 提交 | headRefOid | sha |
| 评审触发 | issue comment@greptile review | MR note@greptile review |
| 评审运行状态 | check runs | pipelines + jobs |
| 通用评论 | issue comments | MR notes |
| inline 评审线程 | GraphQL review threads | discussions(DiffNote) |
| 解决线程 | resolveReviewThreadmutation(可批量) | discussions PUT(无批量接口) |
3. 获取 MR 详情
第一步永远是定位 MR 本体。文档给出的命令是glab mr view <MR_IID> --output json:
glab mr view <MR_IID> --output json需要重点关注的字段(原文 Key fields 部分):
iid— 项目内部的 MR 编号。必须使用它而不是id:GitLab 中id是全局唯一的数据库主键,而所有merge_requests/<MR_IID>形式的 REST 路径参数都要求项目内的iid;source_branch— 等价于 GitHub 的headRefName,后续git push前可用来确认自己位于正确的分支;sha— 该 MR 当前 HEAD 提交的 SHA,后面“按提交 SHA 定位 pipeline”一节会用到;description— MR 正文。注意Greptile 可能会在每轮评审后回写/更新这个字段(例如追加置信度分数块),所以每轮循环都要重新拉取而不是缓存。
SKILL.md 的实际用法是配合jq快速取两个字段并切分支:
glab mr view --output json | jq '{iid: .iid, branch: .source_branch}'4. 触发 Greptile 评审:MR note
GitLab 上没有 GitHub check run 那种显式触发接口,Greploop 的触发方式是给 MR 发一条 note(评论):
glab mr note <MR_IID> --message "@greptile review"触发前有一个重要的去重判断:先查当前 MR 是否已有 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这段逻辑来自 SKILL.md 第 147–160 行的 GitLab 分支:只有当running/pendingpipeline 计数为0时才发触发评论,否则直接进入等待轮询。
5. Pipeline 与 Job:状态轮询的完整模式
5.1 获取 MR 的 pipelines
glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines"返回数组中每个 pipeline 对象有一个status字段,文档列出的取值集合为:running、pending、success、failed、canceled、skipped。
“是否有任何 pipeline 在跑”的判定一行完成:
glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines" | \ jq '[.[] | select(.status == "running" or .status == "pending")] | length'返回0即表示当前没有 running/pending 的 pipeline。注意这里只统计running和pending——success/failed/canceled是终态,skipped也不会阻塞新评审,因此都不应计入“仍在运行”。
5.2 按提交 SHA 定位 pipeline
Greptile 的 pipeline 是针对某个 HEAD 提交触发的,因此轮询时不能只取“最新 pipeline”,而必须按 MR 当前 HEAD SHA 匹配,防止拿到上一轮提交的 pipeline:
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"— 通过参数注入 SHA,避免把 SHA 直接拼进 jq 程序;实际使用时 SHA 来自glab mr view <MR_IID> --output json | jq -r '.sha';[.[] | select(.sha == $sha)]— 过滤出该 SHA 的 pipeline(同一 SHA 理论上可能有多个 pipeline 对象,例如重跑场景);sort_by(.id) | last— pipeline ID 单调递增,取最大 ID 即该 SHA 的最新一次运行;.id // empty—关键的防空处理:匹配不到时输出空(而不是null字符串),外层 bash 可以用[ -z "$PIPELINE_ID" ]判断“pipeline 还没出现,继续等”。
5.3 获取 pipeline 的 jobs 并锁定 Greptile job
glab api "projects/:fullpath/pipelines/<PIPELINE_ID>/jobs"在返回的 jobs 里,按name字段与greptile做大小写不敏感匹配(文档原文:Filter jobs wherenamematchesgreptile(case-insensitive));job 的终态集合是success、failed、canceled。
SKILL.md 把它组合成了完整的轮询循环(第 166–199 行),这就是 Greploop 在 GitLab 上的“等待评审完成”实现:
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") # Find the most recent pipeline for this SHA 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 对象本身可能尚未由 webhook 创建(等 5 秒重试),pipeline 存在但 Greptile job 尚未生成(再等 5 秒重试);job 出现后每 10 秒轮询一次直到终态。对照 GitHub 侧的实现(轮询check-runs的status/conclusion),可以看到 greploop 的设计模式是统一的:“先判存在、再判终态、固定间隔退避”。
6. 从 MR notes 中提取 Greptile 置信度分数
Greptile 评审完成后,分数与总结会以 note(评论)形式出现在 MR 上。GitLab 侧的获取命令:
glab api "projects/:fullpath/merge_requests/<MR_IID>/notes?per_page=100&sort=desc&order_by=created_at"三个查询参数的作用:
per_page=100— 单页最多 100 条 notes;order_by=created_at与sort=desc— 按创建时间倒序,最新的评论在前。
提取分数时需要两步过滤:
- 按作者过滤:检查
author.username是否是 Greptile bot。文档特别提醒:“The Greptile bot username on GitLab may differ from GitHub'sgreptile-apps[bot]— check the first Greptile comment on the MR to identify the exact username.”也就是说 GitLab 上的 bot 用户名与 GitHub 侧的greptile-apps[bot]可能不同(取决于该实例的 Greptile 安装配置),首次运行时必须打开 MR 找到 Greptile 的第一条评论,以其中的真实 username 为准,之后再把它固化进脚本; - 按正文模式匹配:在
body中扫描3/5、5/5这类置信度模式(SKILL.md 中统一表述为 pattern like3/5or5/5,或Confidence: 3/5形式)。
SKILL.md 在 GitLab 侧还要求同时检查两个来源:MR 描述(glab mr view <MR_IID> --output json | jq -r '.description')和 MR notes,因为 Greptile 可能把分数写回 description,也可能只在 notes 里留总结。以“最近一次更新”的分数为准。
7. 抓取未解决的 inline 讨论(discussions)
GitLab 把 inline 评审意见组织在discussions(讨论串)里,每个 discussion 包含一组 notes。获取命令:
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100"分页规则(文档原文):加&page=2、&page=3依次请求,直到返回数组长度小于per_page为止——这是 GitLab REST API 列表接口的通用分页约定,长度等于 100 说明后面可能还有页。
从中筛出“Greptile 发的、未解决的 inline diff 评论”的 jq 过滤:
jq '[.[] | select(.resolved == false and (.notes[0].type == "DiffNote") and (.notes[0].author.username == "GREPTILE_BOT_USERNAME"))]'三个条件的含义:
.resolved == false— 讨论尚未解决(resolved是 discussion 级字段);.notes[0].type == "DiffNote"— 首条 note 是 diff 内联评论(而非普通 MR note),这是 GitLab 区分“评论串是否锚定在 diff 上”的类型标记;.notes[0].author.username == "GREPTILE_BOT_USERNAME"— 作者为 Greptile bot(占位符替换为第 6 节确定的真实用户名)。
每个命中的 discussion 对象里,Greploop 会用到三个字段(文档列出的 “Each discussion has”):
id— 讨论串 ID,解决讨论时作为 URL 参数;notes[0].body— 评论正文,即要理解与修复的评审意见文本;notes[0].position.new_path— 被评论的文件路径,用于定位到仓库中的目标文件。
SKILL.md 还补充了一个约束:这些 DiffNote 应位于最新一次提交上且未解决(Filter toDiffNotetype discussions from Greptile that are on the latest commit and not yet resolved),避免把历史提交的旧评论误算进本轮修复清单。
8. 解决讨论:无批量接口的逐条 PUT
修复完成后,需要把已处理的讨论标记为已解决,否则循环的退出条件“零未解决评论”永远不成立。GitLab 的解决接口:
glab api --method PUT \ "projects/:fullpath/merge_requests/<MR_IID>/discussions/<DISCUSSION_ID>" \ --field resolved=true要点:
- 方法是PUT,不是 POST;
resolved通过--field以请求体形式提交; <DISCUSSION_ID>取第 7 节过滤结果里每个 discussion 的id;- GitLab 没有批量解决接口(文档原文:GitLab has no batch resolution — issue one PUT per discussion)。这一点与 GitHub 形成鲜明对比——GitHub 侧可以一条 GraphQL mutation 里挂
t1: resolveReviewThread(...) t2: resolveReviewThread(...)批量解决(见 graphql-queries.md),GitLab 侧则必须对每个 discussion 发一次 PUT。
脚本化的写法就是一个循环:
for id in $UNRESOLVED_DISCUSSION_IDS; do glab api --method PUT \ "projects/:fullpath/merge_requests/<MR_IID>/discussions/$id" \ --field resolved=true done9. 端到端串联:gitlab-api.md 在 greploop 循环中的落位
把参考文档中的命令按 SKILL.md 的循环步骤(A 触发 → 等待 → B 取结果 → C 判退出 → D 修复 → E 解决 → F 提交推送)串起来,GitLab 侧的完整数据流是:
glab mr view <MR_IID> --output json # 取 iid / source_branch / sha / description │ ▼ GET .../merge_requests/<MR_IID>/pipelines # 有 running/pending? │ 无 → glab mr note <MR_IID> --message "@greptile review" ▼ GET .../merge_requests/<MR_IID>/pipelines # 按 HEAD_SHA 匹配,sort_by(.id)|last ▼ GET .../pipelines/<PIPELINE_ID>/jobs # test("greptile";"i") 锁定 job │ success / failed / canceled → break ▼ GET .../merge_requests/<MR_IID>/notes?per_page=100&sort=desc&order_by=created_at │ 过滤 Greptile bot 作者,body 中解析 X/5 置信度 ▼ GET .../merge_requests/<MR_IID>/discussions?per_page=100 (&page=N 翻页) │ 过滤 resolved==false && DiffNote && Greptile 作者 ▼ 修复每个 DiffNote 指向的新问题 ▼ PUT .../discussions/<DISCUSSION_ID> --field resolved=true # 逐条 ▼ git commit + git push → 回到 pipelines 轮询(SKILL.md 步骤 F 后回 A)退出判定(SKILL.md 步骤 C):置信度 5/5 且未解决评论为零则结束并输出报告;达到 5 次迭代上限则报告当前状态并列出剩余未解决评论。
10. 小结与实践提示
- 占位符约定:文中
<MR_IID>、<PIPELINE_ID>、<DISCUSSION_ID>、COMMIT_SHA、GREPTILE_BOT_USERNAME均为运行时变量;:fullpath是glab api原生支持、由本地 remote 自动解析的占位符,不要手写成字面量。 - iid 而非 id:所有
merge_requests/<MR_IID>路径参数一律使用 MR 的项目内编号iid。 - SHA 锚定轮询:按 MR 的
sha过滤 pipeline 并用sort_by(.id) | last取最新,// empty保证“未出现”时轮询能继续等待,而不是拿到错误 pipeline。 - 状态枚举要写全:pipeline 关注
running/pending(非终态)与success/failed/canceled(job 终态);skipped不在运行判定内。 - bot 用户名要现场确认:Greptile 在 GitLab 上的 bot 用户名因安装而异,首次运行从 MR 上它的第一条评论里确认,再固化到过滤条件中。
- 解决讨论只能逐条 PUT:没有批量接口,循环发 PUT 是唯一方式;这也是 GitLab 与 GitHub(GraphQL 批量
resolveReviewThread)在 API 设计上的实质差异。
以上命令与流程均可在 gitlab-api.md 中逐条对照原文,循环的整体编排(触发去重、轮询节奏、退出条件、报告格式)见 SKILL.md,GitHub 侧的 GraphQL 对照实现见 graphql-queries.md。
- 人工智能
- AI 应用
- 语音
- 音频
- 本地部署
- 桌面应用
【免费下载链接】auto-subs
On-device subtitle generation that connects directly to DaVinci Resolve, Premiere, and After Effects.
相关推荐
danswer 仓库自动化评审实战:基于 glab 的 GitLab MR 讨论与流水线 API 速查
danswer 仓库自动化评审实战:基于 glab 的 GitLab MR 讨论与流水线 API 速查 在 AI 驱动的代码评审自动化场景中,GitLab Me
AI 应用大模型RAGAI Agent后端前端以 glab api 驱动 GitLab 审查闭环:elsa-core 内置 greploop 技能的 GitLab REST API 实战参考
以 glab api 驱动 GitLab 审查闭环:elsa core 内置 greploop 技能的 GitLab REST API 实战参考 本篇文章围绕
后端工作流自动化流程编排低代码Greploop 实战指南:基于 Greptile 自动迭代优化 PR/MR/CL 直至满分评审
Greploop 实战指南:基于 Greptile 自动迭代优化 PR/MR/CL 直至满分评审 导读 Greploop 是存放在本仓库 .agents/ski
后端工作流自动化流程编排低代码
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考