open-code-review 的 GitLab CI 如何避免每次 push 都重复评审浪费 Token?
2026/9/14 10:54:55 网站建设 项目流程

open-code-review 的 GitLab CI 如何避免每次 push 都重复评审浪费 Token?

【免费下载链接】open-code-reviewFast, efficient, battle-tested at Alibaba's scale. Hybrid architecture code review tool: deterministic pipelines + LLM Agent, precise line-level comments, built-in multi-language ruleset (NPE, thread-safety, XSS, SQL injection), OpenAI & Anthropic compatible.项目地址: https://gitcode.com/GitHub_Trending/op/open-code-review

如果你已经把 open-code-review(下称 OCR)接入了 GitLab CI,会发现一个费 token 的现象:默认流水线使用only: [merge_requests]触发,这会响应所有MR 事件——创建、更新、重开。也就是说,一个长期迭代中的 MR,作者每 push 一次新提交,ocr review就会对整个 MR diff 重新跑一遍 LLM 评审。文档明确指出这会“burn a lot of LLM tokens on long-running MRs”。

GitLab CI 没有原生的“仅在 MR 创建时触发”事件,所以文档给出的推荐模式是:在运行评审之前先查询 MR 上是否已经存在 OCR 的评论,如果存在就直接退出,不消耗任何 token

这篇文章基于仓库自带的示例(examples/gitlab_ci 下的.gitlab-ci.ymlpost_review.py)和文档pages/src/content/docs/en/integrations/ci.md中的 GitLab CI 章节,说明如何改造这条流水线。

准备条件:接入默认 GitLab 流水线

如果还没接入 OCR,先完成以下两步(已接入的可以直接跳到改造步骤)。

  1. .gitlab-ci.ymlpost_review.py两个文件都放到你的仓库根目录(或子目录——如果放在别处,记得同步修改 YAML 中python3 post_review.py的路径)。仓库已有.gitlab-ci.yml时,可以把配方 vendor 到其他路径并用include:引入,例如:

    include: - local: 'ci/ocr-review.gitlab-ci.yml'
  2. 在项目的Settings → CI/CD → Variables中配置 CI/CD 变量:

    变量必填Masked说明
    OCR_LLM_URLLLM API 端点 URL,例如https://api.openai.com/v1/chat/completions
    OCR_LLM_AUTH_TOKENLLM API 认证 token,会被写入ocr config set llm.auth_token
    OCR_LLM_MODEL模型名。OCR 没有内置默认模型,不设置流水线会直接失败
    GITLAB_API_TOKEN否(本文需要,见下)apiscope 的 Project / Personal / Group access token

    GITLAB_API_TOKEN在默认流水线中是可选项:不设置时回退到内置的CI_JOB_TOKEN(例如 fork MR 场景,它可以通过/discussions发讨论),文档仍然建议用专门的 token 保证可靠性。但本文的去重检查脚本直接读取GITLAB_API_TOKEN,不会回退到CI_JOB_TOKEN,所以要启用这个模式,必须配置带apiscope 的GITLAB_API_TOKEN

    另外注意:GitLab CI/CD 不支持值少于 8 个字符的变量,因此llm.use_anthropic无法作为 CI 变量传入,流水线里被硬编码为false;需要使用 Anthropic Claude 模型时要直接改.gitlab-ci.yml脚本。

改造:用 Python 包装器替代直接的 ocr review 调用

code-reviewjob 里直接执行ocr review ... > .ocr/ocr-result.json的那一步,替换为下面的 Python 包装脚本。它先调用 GitLab API 列出 MR 的 notes(per_page=100),逐条检查 body 中是否含OpenCodeReview;找到即说明该 MR 已经被 OCR 评审过,打印日志后直接退出,ocr review根本不会执行;没找到才运行评审并把 JSON 输出写到发布步骤期望的.ocr/ocr-result.json

script: # Install OpenCodeReview - npm install -g @alibaba-group/open-code-review # Configure OCR - | : "${OCR_LLM_URL:?set OCR_LLM_URL in Settings -> CI/CD -> Variables}" : "${OCR_LLM_AUTH_TOKEN:?set OCR_LLM_AUTH_TOKEN in Settings -> CI/CD -> Variables}" : "${OCR_LLM_MODEL:?set OCR_LLM_MODEL in Settings -> CI/CD -> Variables}" ocr config set llm.url "$OCR_LLM_URL" ocr config set llm.auth_token "$OCR_LLM_AUTH_TOKEN" ocr config set llm.model "$OCR_LLM_MODEL" ocr config set llm.use_anthropic false ocr config set llm.extra_body '{"thinking": {"type": "disabled"}}' # Check for existing OCR reviews and run review only if not found - | python3 << 'WRAPPER_SCRIPT' import json import os import subprocess import sys import urllib.request GITLAB_URL = os.environ.get("CI_SERVER_URL", "https://gitlab.com") PROJECT_ID = os.environ["CI_PROJECT_ID"] MR_IID = os.environ["CI_MERGE_REQUEST_IID"] API_TOKEN = os.environ["GITLAB_API_TOKEN"] TARGET_BRANCH = os.environ["CI_MERGE_REQUEST_TARGET_BRANCH_NAME"] # Check for existing OCR reviews url = f"{GITLAB_URL}/api/v4/projects/{PROJECT_ID}/merge_requests/{MR_IID}/notes?per_page=100" req = urllib.request.Request(url, headers={"PRIVATE-TOKEN": API_TOKEN}) with urllib.request.urlopen(req) as resp: notes = json.loads(resp.read().decode("utf-8")) for note in notes: if "OpenCodeReview" in note.get("body", ""): print("OCR has already reviewed this MR. Skipping to save tokens.") # 写一个空的 comments 结果,避免后续 post_review.py 因找不到输入文件而报错 os.makedirs(".ocr", exist_ok=True) with open(".ocr/ocr-result.json", "w") as f: f.write('{"comments": []}') sys.exit(0) # No existing review found - run OCR print("No existing OCR review found. Running review...") COMMIT_SHA = os.environ["CI_COMMIT_SHA"] result = subprocess.run([ "ocr", "review", "--from", f"origin/{TARGET_BRANCH}", "--to", COMMIT_SHA, "--format", "json", "--audience", "agent" ], capture_output=True, text=True) # Save output for the posting script os.makedirs(".ocr", exist_ok=True) with open(".ocr/ocr-result.json", "w") as f: f.write(result.stdout) with open(".ocr/ocr-stderr.log", "w") as f: f.write(result.stderr) print("OCR review completed.") WRAPPER_SCRIPT # Post review comments to MR - python3 post_review.py .ocr/ocr-result.json

脚本要点:

  • --to使用CI_COMMIT_SHA而不是目标分支名,这是示例流水线对 fork MR 的支持方式(同仓库 MR 同样适用)。
  • 评审仍保持--format json --audience agent:前者给出可解析的 JSON,后者抑制进度输出,保持 stdout 干净。
  • 文档示例在命中时只sys.exit(0)并打印提示;上面的版本额外在跳过分支写了一个{"comments": []}空结果,因为post_review.py的输入参数默认读取.ocr/ocr-result.json,文件不存在会打印Failed to parse OCR output并尝试发一条空的错误 summary。如果你的 YAML 在跳过分支会整体终止 job,则不需要这一行。

验证是否生效

判断方法直接看 pipeline 日志和 MR 评论:

  • 首次(MR 上还没有 OCR 评论)的 pipeline 日志出现No existing OCR review found. Running review...,评审完成后 MR 上出现 inline discussions 和 summary note(summary note 默认带OpenCodeReview标识)。
  • 之后作者再次 push触发的新 pipeline,日志出现OCR has already reviewed this MR. Skipping to save tokens.,job 正常结束(exit 0),MR 上不会新增评审评论,也没有产生新的 LLM 调用。
  • 如果想确认为什么某次运行评审结果异常,可以在 job 里cat .ocr/ocr-result.jsoncat .ocr/ocr-stderr.log查看 OCR 的原始输出(对应文档的 Debugging 建议)。

需要强制重新评审时,文档给出的方法是手动删除 MR 上已有的 OCR notes——下一次 pipeline 运行检测不到 OCR 评论,就会重新执行完整评审。

限制与排查

  • 检查逻辑是在 notes 列表的前 100 条per_page=100)里查找OpenCodeReview字样。如果某个 MR 的 notes 已经超过 100 条且 OCR 评论不在前 100 条内,跳过逻辑可能检测不到、从而重复评审。
  • 跳过分支只保证不再消耗 LLM token,但 pipeline 本身仍会被 MR update 事件触发并跑完安装与配置步骤;resource_group: mr-review-$CI_MERGE_REQUEST_IIDinterruptible: true只负责并发管理,不会阻止 token 消耗。
  • 跳过分支中API_TOKEN直接取自os.environ["GITLAB_API_TOKEN"],变量未配置时脚本会在这一行抛异常而不是优雅回退,所以本文场景下该变量是必配项。
  • 常见报错与默认流水线相同,对照文档的 Troubleshooting:Cannot find merge-base说明 runner 用了浅克隆,请保留 job 里的GIT_DEPTH: 0全量克隆设置;API error 403说明GITLAB_API_TOKENapiscope、不是项目成员,或自托管实例上 token 不是由本实例签发;Failed to parse OCR output则检查OCR_LLM_URLOCR_LLM_AUTH_TOKEN
  • 自托管 GitLab 无需改代码:发布脚本读取 GitLab 自动设置的CI_SERVER_URL,但要确保GITLAB_API_TOKEN由你的自托管实例签发,而不是gitlab.com

参考

  • 完整 CI/CD 集成说明:pages/src/content/docs/en/integrations/ci.md(GitLab CI 章节的 “Avoid re-reviewing on every push”)
  • 可运行的示例流水线与发布脚本:examples/gitlab_ci/.gitlab-ci.ymlexamples/gitlab_ci/post_review.pyexamples/gitlab_ci/README.md
  • JSON 输出格式(comments[]信封结构)见 CLI Reference

【免费下载链接】open-code-reviewFast, efficient, battle-tested at Alibaba's scale. Hybrid architecture code review tool: deterministic pipelines + LLM Agent, precise line-level comments, built-in multi-language ruleset (NPE, thread-safety, XSS, SQL injection), OpenAI & Anthropic compatible.项目地址: https://gitcode.com/GitHub_Trending/op/open-code-review

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

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

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

立即咨询