ClaudeClaude Code系列第 6 / 11 篇

在 GitLab CI/CD 里用 Claude Code:把 issue 变成 MR 的作业怎么写,走中转站和国内 Runner 要改的几处

按 Claude Code 官方的 GitLab 文档整理:在 .gitlab-ci.yml 里加一个跑 claude -p 的作业,让它改代码、开 MR。讲清最小的作业怎么写、评论触发和开 MR 靠什么、走中转站和国内 Runner 要改哪几处;作业里那条命令本站在服务器上照样跑了四遍。

发布 · 约 9 分钟读完 · 经人工审核()· 本站的内容怎么来的

本文根据公开分享整理,本站尚未实测。操作前请对照文末的原始来源。

本页目录(9 节)
  1. 一、它是怎么工作的
  2. 二、最小的作业
  3. 三、评论里 @claude 怎么触发
  4. 四、走中转站、在国内的 Runner 上要改的几处
  5. 五、实测:作业里这条命令到底做了什么
  6. 六、安全和花费
  7. 七、出了问题先查
  8. 这次没有覆盖到的
  9. 相关文章

这篇解决一个问题:代码在 GitLab 上(包括公司自建的),想让 Claude Code 像在 GitHub 上那样,评论里 @ 一下就去改代码、开 MR,该怎么配。

GitLab 没有 GitHub 那样的现成 Action。做法是在 .gitlab-ci.yml 里加一个作业,作业里装好 Claude Code、跑一条 claude -p。官方文档注明这个集成还是测试版,由 GitLab 一方维护,有问题要去 GitLab 的 issue 里反馈。

本站没有 GitLab 实例,GitLab 一侧(Runner、触发、评论、开 MR)都是按文档整理的。能测的是作业里那条命令:本站在服务器上用一个干净的配置目录、只靠环境变量给凭据(和 CI 容器里一样),照官方的写法跑了四遍,结果在第五节。用 GitHub 的看《用 GitHub Actions 让 Claude Code 审 PR、修 issue》。

一、它是怎么工作的

按官方文档:

  1. 触发。 GitLab 等你选定的事件,比如 issue、MR 或审查线程里出现 @claude 的评论。作业从这个线程和仓库里收集上下文,拼成提示词,交给 Claude Code。
  2. 跑在你的 Runner 上。 每次都在一个容器里跑,网络和文件系统按你的规则限制;Claude Code 只能在工作区里写。
  3. 改动走 MR。 所有改动都通过 MR 交回来,审查和审批照旧。

模型可以走 Claude API,也可以走 Amazon Bedrock 或 Google Cloud。云平台那两种本站不写,只讲 Claude API 和中转站。

文档举的用法:在 issue 里评论 @claude implement this feature based on the issue description,它分析 issue 和代码、在分支上改、开 MR;在 MR 讨论里让它给出具体方案并改进 MR;在评论里让它修某个报错。

二、最小的作业

两步:在 Settings → CI/CD → Variables 加一个 masked 的变量 ANTHROPIC_API_KEY;在 .gitlab-ci.yml 里加这个作业(官方示例原样):

stages:
  - ai

claude:
  stage: ai
  image: node:24-alpine3.21
  rules:
    - if: '$CI_PIPELINE_SOURCE == "web"'
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
  variables:
    GIT_STRATEGY: fetch
  before_script:
    - apk update
    - apk add --no-cache git curl bash
    - curl -fsSL https://claude.ai/install.sh | bash
    - export PATH="$HOME/.local/bin:$PATH"
  script:
    - /bin/gitlab-mcp-server || true
    - echo "$AI_FLOW_INPUT for $AI_FLOW_CONTEXT on $AI_FLOW_EVENT"
    - >
      claude
      -p "${AI_FLOW_INPUT:-'Review this MR and implement the requested changes'}"
      --permission-mode acceptEdits
      --allowedTools "Bash Read Edit Write mcp__gitlab"
      --debug

逐行说一下:

部分 做什么
rules 什么时候跑:这里是在网页上手动跑,和 MR 事件。按需要改
before_script 在 Alpine 镜像里装 git、curl、bash,再用官方安装脚本装 Claude Code,把 ~/.local/bin 加进 PATH
/bin/gitlab-mcp-server 启动 GitLab 的 MCP 服务器,Claude 靠它读 issue、发评论、开 MR。没有就跳过(`
AI_FLOW_INPUT 等 从网页或接口触发时带进来的上下文:要做的事、来自哪个 issue 或 MR、什么事件。由触发流水线的一方(比如第三节说的监听程序)传入
-p "..." 提示词。没有 AI_FLOW_INPUT 时用后面那句默认的
--permission-mode acceptEdits 改文件不用确认。-p 从 2.1.302 起默认是 Manual,不写这个就改不了文件
--allowedTools 放行 Bash、读写文件和 GitLab 的 MCP 工具
--debug 打出调试信息

加好之后,可以在 CI/CD → Pipelines 里手动跑一次,或者开一个 MR 触发。

生产环境文档建议手动配:凭据用 masked 变量;读写 GitLab 用默认的 CI_JOB_TOKEN,权限不够就建一个带 api 范围的项目访问令牌,存成 GITLAB_ACCESS_TOKEN。

三、评论里 @claude 怎么触发

这一点容易误会:示例作业的 rules 只管手动运行和 MR 事件。按文档手动配置的第 4 步,要让评论里的 @claude 触发,得给项目加一个 “Comments (notes)” 的 webhook,指向你的事件监听程序;监听程序看到评论里有 @claude,就调 GitLab 的流水线触发接口,把 AI_FLOW_INPUT、AI_FLOW_CONTEXT 这些变量带过去。文档把这一步标为可选,监听程序要自己准备。

文档的排错里也写了:评论里要写 @claude,不是 /claude;没反应时先看流水线有没有被触发、凭据变量在不在、监听程序配了没有。

四、走中转站、在国内的 Runner 上要改的几处

官方文档没有讲中转站。作业里跑的就是 Claude Code 命令行,它认的环境变量和平时一样,见《Claude Code 接入中转站》。

1. 凭据换成两个变量。 不用 ANTHROPIC_API_KEY,在 CI/CD 变量里加:

变量 值 设置
ANTHROPIC_BASE_URL 中转站给的地址,不带 /v1 可以不 mask
ANTHROPIC_AUTH_TOKEN 中转站给的 key masked,按需要设成 protected

本站第五节的四次运行就是这样:配置目录是空的,凭据只来自这两个环境变量,都正常。中转站要的是 x-api-key 的,把 key 放进 ANTHROPIC_API_KEY 而不是 ANTHROPIC_AUTH_TOKEN,两个不要同时设。

2. 模型名要这把 key 有的。 不指定时用的是 Claude Code 的默认模型(本站这次是 Opus 5.5)。key 没开这个模型的,在命令里加 --model,或者设 ANTHROPIC_MODEL。

3. 安装脚本可能下不来。 示例用 curl https://claude.ai/install.sh 安装,国内的 Runner 访问这个地址不一定顺。安装文档给了另一条路:用 npm 装 npm install -g @anthropic-ai/claude-code,装的是同一个二进制,支持 linux-x64-musl 这类平台。示例的 node 镜像里本来就有 npm,配上国内的 npm 镜像源就行。镜像本身从 Docker Hub 拉,国内也可能要配镜像加速。

4. Alpine 镜像要多装几样。 安装文档说,在 Alpine 这类 musl 系统上,运行时还要 libgcc、libstdc++ 和 ripgrep,并且在设置里把 USE_BUILTIN_RIPGREP 设成 0。官方的 GitLab 示例只装了 git、curl、bash。照安装文档补上:

  before_script:
    - apk update
    - apk add --no-cache git curl bash libgcc libstdc++ ripgrep
    - export USE_BUILTIN_RIPGREP=0

ripgrep 在 Alpine 的 community 仓库里。这一条是本站对照两页官方文档补的,服务器上没有 Docker,没有在 Alpine 镜像里测过。

5. 网络要放行。 Runner 要能连上你的中转站地址。文档建议限制作业的出网,放行的时候别漏了它。

五、实测:作业里这条命令到底做了什么

项目 内容
日期 2026-10-21
版本 Claude Code 2.1.304
环境 本站测试服务器,Ubuntu 24.04;不是容器,也没有 GitLab
凭据 空的配置目录,只有 ANTHROPIC_BASE_URL 和 ANTHROPIC_AUTH_TOKEN 两个环境变量,通过酷站AI 中转站
示例仓库 一个很小的 Python 项目:list_available() 把库存为 0 的商品也返回了。仓库里有一份 CLAUDE.md:改完要跑 python3 -m unittest,提交说明用中文、第一行不超过 50 个字,不要推送
命令 官方示例那一条,去掉了 --debug,没有 GitLab 的 MCP 服务器

AI_FLOW_INPUT 设成“实现 issue #12:库存为 0 的商品不应该出现在 list_available() 的结果里,补上测试。”

运行 结果 用时 Claude Code 估算的花费
照官方原样 改对了,补了 3 个测试,4 个测试全过。没有提交,最后说“要提交的话我按 CLAUDE.md 的规矩写中文说明,不推送” 22 秒 0.08 美元
提示词末尾加“改完在新分支 claude/issue-12 上提交” 建了分支 claude/issue-12,提交说明是中文、第一行不超过 50 个字,没有推送 21 秒 0.08 美元
照官方原样,加 --max-turns 2 输出 Error: Reached max turns (2),退出码 1,什么也没改 9 秒 0.04 美元

几件值得知道的事:

  • 这条命令本身不提交,也不开 MR。 没有 GitLab 的 MCP 服务器时,它只改了工作区。要它提交,提示词里得说;要开 MR,靠 mcp__gitlab 工具,或者在作业的 script 里自己 git push 再调 GitLab 的接口。
  • 它会试着用 glab 去读 issue。 两次都先试着用 glab 读 issue #12(有一次还试了 gh),机器上没装,就按提示词里的描述做了。想让它看到 issue 原文和讨论,装好 GitLab 的 MCP 服务器,或者把 issue 内容拼进提示词。
  • CLAUDE.md 的规矩它照着做了:跑了测试,提交说明的格式对,没有推送。
  • 提交里会带一行 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>。 这是 Claude Code 的默认做法,不想要就在设置里把 attribution.commit 设成空字符串。设置文档还说,认不出模型版本时写 Claude,模型 ID 对不上任何 Claude 模型(比如通过自定义地址用别家的模型)时写 Claude Code。本站经中转站用的是 claude-opus-5-5,写的是完整的名字。
  • 容器里要先配 git 身份。 本站的测试机上已经配过 user.name 和 user.email,所以提交成功了。CI 容器里一般没有,在 before_script 里先 git config 一下,不然提交会失败。
  • --max-turns 到了上限,作业就算失败。 文档把它列为控制花费的办法,值别设得太小。
  • 回复的语言不固定。 同样的中文提示词,三次里两次用英文汇报,一次用中文。要它在 MR 里用中文,写进 CLAUDE.md。
  • 那条默认提示词会带着引号。 没有 AI_FLOW_INPUT 时,"${AI_FLOW_INPUT:-'Review this MR ...'}" 在 bash 和 sh 里都会把那对单引号原样带进提示词。不影响它理解,嫌难看就把单引号去掉。
  • --debug 排查完就去掉。 它会把大量调试信息打进作业日志,能看作业日志的人都看得到。本站测试时没有加。

六、安全和花费

文档的建议:

  • key 和云凭据只放在 CI/CD 变量里,设成 masked,绝不提交进仓库;云平台优先用 OIDC,不用长期的 key。
  • 限制作业的权限和出网。
  • Claude 开的 MR 和别人的一样审。示例里放行了整个 Bash,又是 acceptEdits,它在容器里基本什么命令都能跑,靠的是容器和 Runner 的隔离。

花费分两块:Runner 的计算时间,和模型的 token。控制的办法:@claude 后面把要做的事说具体;设 --max-turns 和作业的 timeout(比如 timeout: 30m);限制同时跑几个。本站这个小仓库每次 4 到 8 美分(Opus 5.5,按官方价估算),真实项目的上下文大得多,会贵不少。

七、出了问题先查

现象 先查什么
评论里 @claude 没反应 流水线有没有被触发;评论里是 @claude 而不是 /claude;webhook 和监听程序配了没有;凭据变量在不在
作业发不了评论、开不了 MR CI_JOB_TOKEN 的权限够不够,不够就用带 api 范围的项目访问令牌;--allowedTools 里有没有 mcp__gitlab;作业是不是在 MR 的上下文里跑,或者 AI_FLOW_* 带够了上下文
认证失败 走 Claude API 的,看 ANTHROPIC_API_KEY 有没有过期;走中转站的,看地址和 key 是不是放对了变量,见《Claude Code 常见报错怎么查》
Error: Reached max turns --max-turns 设小了(本站实测,退出码 1)
提交失败 容器里没配 git 身份
装不上 安装脚本下载不了就改用 npm;Alpine 上缺运行库见第四节

文档还提醒:命令行参数可能随版本变,在作业里跑一下 claude --help 看当前支持什么。

这次没有覆盖到的

  • GitLab 一侧全部没有测:Runner、@claude 的触发、GitLab 的 MCP 服务器、发评论和开 MR、CI_JOB_TOKEN 的权限。
  • Alpine 镜像和 npm 安装没有测,第四节是对照安装文档写的。
  • Amazon Bedrock 和 Google Cloud 两种接法不写,本站不写云平台接入。
  • 实测的仓库很小,四次运行,只说明这条命令在这个版本上的行为。

相关文章

来源

通过 API 中转站使用这些模型?到 Veridrop 免费检测中转站给你的是不是它声称的模型,或者看看中转站排行榜前 100 名。

相关文章