简体中文 | English | 日本語 | Русский | Tiếng Việt | 한국어 | Deutsch | Français
配套文档:
../docs/AIDevOps融合GitLab落地方案.md(设计)、../docs/AIDevOps融合GitLab实现文档.md(实现细节) 本手册目标:从零开始,按步骤部署,最终跑通「AI 评审 / 自动修复 / 失败自愈 / 安全扫描」四条链路。
| 已在脚手架中,可直接部署 | 设计文档中有、脚手架未含(路线图项) |
|---|---|
| LiteLLM 模型网关配置 | dsh 编排/审批/审计插件 |
| webhook-gateway(Python/Node 双实现) | mcp-kb 企业知识库 Server |
| mcp-gitlab(Python/Node 双实现,16 个工具) | mcp-prometheus / mcp-k8s / mcp-argocd |
| 4 个 CI 模板(review/autofix/heal/security) | 研发数据底座(Kafka/Flink/数据湖) |
| 3 个 AI Runner 镜像 + 2 个回写脚本 | 金丝雀智能发布(ArgoCD 联动) |
| 5 套编码工具接入模板 | HITL 数据飞轮与模型微调流水线 |
本文档部署的是阶段一~阶段二的核心链路。路线图项的接入方式见实现文档「扩展点」章节。
开发者 ──► GitLab EE ──webhook──► webhook-gateway ──创建Pipeline──► GitLab API
│ │
│(Cursor/OpenCode/Codex/…) └──事件流──► Kafka(可选)
▼
LiteLLM 网关 ◄── OPENAI_BASE_URL ── AI Runner Job(opencode/codex/swe-agent)
│ │ 回写评论/建MR
▼ ▼
私有化模型(DeepSeek/Qwen) GitLab API(机器人 PAT)
dsh / 编码工具 ──MCP──► mcp-gitlab ──► GitLab API
全文出现的内网域名均为示例,部署时替换为实际地址:
| 示例域名 | 指向 | 默认端口 |
|---|---|---|
gitlab.internal |
GitLab EE 实例 | 443 |
llm-gateway.internal |
LiteLLM 网关 | 4000 |
mcp-gitlab.internal |
mcp-gitlab 服务 | 8080 |
webhook-gateway.internal |
webhook-gateway 服务 | 8000 |
registry.internal |
内网镜像仓库 | — |
| # | 依赖 | 要求 | 检查命令 |
|---|---|---|---|
| 1 | GitLab | EE/极狐私有化 ≥ 16.x,有管理员账号 | curl https://gitlab.internal/api/v4/version |
| 2 | 模型服务 | 私有化 DeepSeek/Qwen,OpenAI 兼容 API(vLLM 等) | curl http://internal-llm-strong/v1/models |
| 3 | Docker 构建机 | 能推内网 Registry | docker info |
| 4 | 部署环境 | K8s 集群或 2~3 台 Docker 主机 | kubectl get ns |
| 5 | GitLab Runner | 可注册新 Runner 的权限 | 见 Step 4 |
| 步骤 | 内容 | 预计耗时 |
|---|---|---|
| 0 | 创建机器人账号与访问令牌 | 5 min |
| 1 | 部署 LiteLLM 模型网关 | 10 min |
| 2 | 构建并推送 5 个镜像 | 15 min |
| 3 | 部署 mcp-gitlab | 5 min |
| 4 | 注册 ai-runner | 10 min |
| 5 | 部署 webhook-gateway | 5 min |
| 6 | 接入第一个业务项目 | 15 min |
| 7 | 端到端验证四条链路 | 20 min |
| 8 | 开发者编码工具接入 | 10 min/人 |
- GitLab 管理员登录 → Admin Area → Users → New user:创建
ai-devops-bot(Regular 即可) - 将
ai-devops-bot加入目标 Group/Project,角色 Developer(需建分支、推代码、评论 MR) - 用 bot 账号 → Preferences → Access Tokens,创建 PAT:
- 名称:
ai-devops-pat,勾选 scope:api,有效期按需
- 名称:
- 记录令牌,下文统一记为
<BOT_PAT>
同时生成一个随机串作为 Webhook 密钥:
openssl rand -hex 32,记为<WEBHOOK_SECRET>。
1.1 先改配置:编辑 deploy/litellm-config.yaml,把两个 api_base 改成你的模型服务实际地址:
api_base: http://internal-llm-strong/v1 # ← 改成 DeepSeek 服务地址
api_base: http://internal-llm-fast/v1 # ← 改成 Qwen 服务地址1.2 启动(Docker,推荐):
export LITELLM_MASTER_KEY=<随机强串> # 网关主 Key,openssl rand -hex 32
export INTERNAL_LLM_KEY=<模型服务的Key> # vLLM 无认证可填任意非空串
docker run -d --name litellm --restart unless-stopped -p 4000:4000 \
-e LITELLM_MASTER_KEY -e INTERNAL_LLM_KEY \
-v $PWD/deploy/litellm-config.yaml:/app/config.yaml \
ghcr.io/berriai/litellm:main-stable \
--config /app/config.yaml --port 40001.3 验证:
curl http://<网关IP>:4000/v1/models -H "Authorization: Bearer $LITELLM_MASTER_KEY"
# 预期返回包含 code-strong、code-fast 的模型列表
curl http://<网关IP>:4000/v1/chat/completions \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" \
-d '{"model":"code-fast","messages":[{"role":"user","content":"ping"}]}'
# 预期返回正常补全;失败则检查 api_base 与 INTERNAL_LLM_KEY1.4 为 CI 和团队签发子 Key(成本归集):
curl -X POST http://<网关IP>:4000/key/generate \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" -H "Content-Type: application/json" \
-d '{"key_alias":"ci-runner","max_budget":100,"budget_duration":"30d"}'
# 返回的 "key"(sk-...)记为 <CI_LLM_KEY>,Step 6 配置 CI 变量用1.5 配置 DNS:将 llm-gateway.internal 解析到网关地址(或后续所有配置中直接用 IP:4000)。
在 gitlab-integration/ 目录下执行(runner 镜像的构建上下文必须是此目录,因为 Dockerfile 里 COPY 了 scripts/ 等):
# 3 个 AI Runner 镜像
docker build -f runner-images/Dockerfile.opencode -t registry.internal/ai/opencode-runner:v1 .
docker build -f runner-images/Dockerfile.codex -t registry.internal/ai/codex-runner:v1 .
docker build -f runner-images/Dockerfile.swe-agent -t registry.internal/ai/swe-agent-runner:v1 .
# 2 个服务镜像(Python 版示例;Node 版见 Step 3/5)
docker build -t registry.internal/ai/webhook-gateway:v1 webhook-gateway/
docker build -t registry.internal/ai/mcp-gitlab:v1 mcp-gitlab/
docker push registry.internal/ai/opencode-runner:v1
docker push registry.internal/ai/codex-runner:v1
docker push registry.internal/ai/swe-agent-runner:v1
docker push registry.internal/ai/webhook-gateway:v1
docker push registry.internal/ai/mcp-gitlab:v1内网无互联网时:提前在有网环境
docker pull基础镜像(node:22-slim、python:3.12-slim)并docker save/load导入。
Python(mcp-gitlab/)与 Node(mcp-gitlab-node/)二选一,接口完全一致。
docker run -d --name mcp-gitlab --restart unless-stopped -p 8080:8080 \
-e GITLAB_URL=https://gitlab.internal \
-e GITLAB_TOKEN=<BOT_PAT> \
-e ALLOW_HIGH_RISK=false \
registry.internal/ai/mcp-gitlab:v1验证:
curl http://<IP>:8080/healthz # Node 版返回 {"status":"ok"};Python(FastMCP) 版无此端点,跳过本行
# 用 MCP Inspector 验证工具列表(推荐):
npx @modelcontextprotocol/inspector http://<IP>:8080/mcp
# 预期列出 get_project / get_mr_diff / post_mr_note 等 16 个工具若暂不使用编码工具的 MCP 能力,Step 3 可延后——四条 CI 链路不依赖它。
AI Job 与普通 Job 用 Runner Tag 隔离。以下以 Docker Executor 为例(最简):
gitlab-runner register \
--url https://gitlab.internal \
--token <项目或Group的Runner注册令牌> \
--executor docker \
--docker-image registry.internal/ai/opencode-runner:v1 \
--tag-list ai-runner \
--description "ai-runner-01" \
--docker-privileged=false要点:
- tag 必须是
ai-runner(CI 模板tags: [ai-runner]与之对应) - Runner 所在网络必须能访问:GitLab API、
llm-gateway.internal:4000、内网 Registry - 生产建议 K8s Executor + 独立命名空间 + NetworkPolicy(仅放行上述三项)
Python(webhook-gateway/)与 Node(webhook-gateway-node/)二选一,行为一致。
docker run -d --name webhook-gateway --restart unless-stopped -p 8000:8000 \
-e GITLAB_URL=https://gitlab.internal \
-e GITLAB_TOKEN=<BOT_PAT> \
-e WEBHOOK_SECRET=<WEBHOOK_SECRET> \
registry.internal/ai/webhook-gateway:v1
# Node 版可加 -e PORT=8000;Kafka 上报可选:-e KAFKA_BOOTSTRAP=kafka1:9092验证:
curl http://<IP>:8000/healthz
# {"status":"ok"}
curl -X POST http://<IP>:8000/webhook/gitlab -H "X-Gitlab-Token: wrong" -d '{}'
# 预期 401(验签生效)6.1 引入 CI 文件(方式二选一):
- 方式 A(复制):把
gitlab-integration/下的.gitlab-ci.yml、ci-templates/、scripts/复制到业务仓库根目录 - 方式 B(远程引用,推荐多项目):把脚手架推到专门仓库
devops/ai-templates,业务项目只需:
include:
- project: 'devops/ai-templates'
ref: main
file:
- '/ci-templates/ai-review-opencode.yml'
- '/ci-templates/ai-review-codex.yml'
- '/ci-templates/ai-autofix.yml'
- '/ci-templates/ai-heal.yml'
- '/ci-templates/ai-security.yml'注意方式 B 下
scripts/也要在同一模板仓库中,并把模板里/opt/scripts/...路径改为 CI 中可访问的位置(或打进镜像——脚手架的 runner 镜像已内置到/opt/scripts/,无需改动)。
6.2 配置 CI/CD 变量(项目 → Settings → CI/CD → Variables):
| 变量 | 值 | 属性 |
|---|---|---|
LLM_GATEWAY_URL |
http://llm-gateway.internal:4000/v1 |
普通 |
LLM_GATEWAY_KEY |
<CI_LLM_KEY>(Step 1.4 签发) |
Masked |
GITLAB_TOKEN |
<BOT_PAT> |
Masked |
AI_REVIEW_ENGINE |
不填=opencode(默认);codex 切换引擎 |
普通,可选 |
6.3 配置 Webhook(项目 → Settings → Webhooks):
- URL:
http://webhook-gateway.internal:8000/webhook/gitlab - Secret token:
<WEBHOOK_SECRET> - 勾选 Trigger:Merge request events、Issue events、Pipeline events
- 保存后点 Test → Merge request events,应返回 200
6.4 配置合并门禁(项目 → Settings → Merge requests / Protected branches):
- 开启 All threads must be resolved(AI 阻断级意见未解决则无法合并)
- 主分支设为 Protected;Settings → Merge request approvals:Required approvals ≥ 1(AI 修复 MR 强制人工审批)
6.5 替换项目测试命令:编辑业务仓库 .gitlab-ci.yml 的 unit-test job 和 ci-templates/ai-autofix.yml 中标注「按项目技术栈替换」的 echo 行,改为真实测试命令(如 mvn test / pytest)。
git checkout -b test/ai-review && echo "# test" >> README.md
git add -A && git commit -m "test: trigger ai review" && git push -u origin test/ai-review
# 在 GitLab 上创建 MR(不要勾选 Draft)预期(1~3 分钟内):
- 网关日志出现
trigger pipeline ... AI_TASK=review - 项目 Pipelines 出现一条新流水线,
ai-review-opencodeJob 运行 - MR 页面出现 AI 评论(汇总 Note:阻断/重要/提示数量)
排查见 FAQ Q1。
- 建一个真实可修的小 bug Issue(描述 ≥ 30 字,含复现步骤),打上标签
ai-fix - 预期:触发
AI_TASK=autofix流水线 →ai-autofixJob → 产出fix/ai-<iid>分支的 MR(带ai-generated标签、描述含三重准入 checklist) - 该 MR 走正常 CI + AI 评审 + 人工审批后合并
无合适 bug 时,可手工触发验证:
CI/CD → Run pipeline,变量填AI_TASK=autofix、ISSUE_IID=<某个Issue号>。
在测试分支提交一个会导致单测失败的改动并推 MR → 等流水线失败 → 预期:
- 网关收到 Pipeline failed 事件 → 归因 → 触发
AI_TASK=heal流水线 ai-healJob 产出修复 MR- 同一分支 24h 内第 3 次失败 → 不再触发自愈,改为创建
incident标签 Issue(熔断生效)
# 手工触发
CI/CD → Run pipeline → 添加变量 AI_TASK=security → Run或配置 CI/CD → Schedules 每日定时扫描(无需变量,schedule 流水线自动命中规则)。
先在网关为本人签发 Key(Step 1.4 同款命令,key_alias 用姓名/工号),然后:
| 工具 | 步骤 |
|---|---|
| Cursor | ① 项目根建 .cursor/mcp.json,内容复制 dev-tool-configs/cursor/mcp.json(域名替换为实际 mcp-gitlab 地址)② Settings → Models → 添加 OpenAI 兼容端点 http://llm-gateway.internal:4000/v1 + 个人 Key |
| OpenCode | ① 复制 dev-tool-configs/opencode/opencode.json 到项目根 ② export LLM_GATEWAY_KEY=<个人Key> ③ opencode 启动,/models 应看到 code-strong/code-fast |
| Codex CLI | ① 复制 dev-tool-configs/codex/config.toml 到 ~/.codex/config.toml ② export LLM_GATEWAY_KEY=<个人Key> |
| Claude Code | 复制 dev-tool-configs/claude-code/.mcp.json 到项目根(模型侧需网关 Anthropic 代理,属路线图项) |
| Aider | ① 复制 dev-tool-configs/aider/.aider.conf.yml 到项目根 ② export OPENAI_API_KEY=<个人Key> |
验证:在任一工具中询问「用 gitlab 工具查一下项目 X 最近的 MR」——能返回真实数据即 MCP 链路通。
| 服务 | 变量 | 必填 | 说明 |
|---|---|---|---|
| litellm | LITELLM_MASTER_KEY / INTERNAL_LLM_KEY |
是 | 主 Key / 模型服务 Key |
| webhook-gateway | GITLAB_URL GITLAB_TOKEN WEBHOOK_SECRET |
是 | — |
| webhook-gateway | KAFKA_BOOTSTRAP HEAL_MAX_RETRIES_PER_DAY(默认 2)DEDUP_WINDOW_SECONDS(默认 300) |
否 | — |
| mcp-gitlab | GITLAB_URL GITLAB_TOKEN |
是 | — |
| mcp-gitlab | ALLOW_HIGH_RISK(默认 false) |
否 | true 才开放 merge 工具 |
LLM_GATEWAY_URL、LLM_GATEWAY_KEY(Masked)、GITLAB_TOKEN(Masked)、AI_REVIEW_ENGINE(可选)
| AI_TASK | 附加变量 | 触发源 |
|---|---|---|
review |
MR_IID、MR_SOURCE_SHA |
MR open/update |
autofix |
ISSUE_IID |
Issue 打 ai-fix 标签 |
heal |
FAILED_PIPELINE_ID |
流水线失败(代码类) |
| 场景 | 操作 |
|---|---|
| 临时停用全部 AI 能力 | 项目变量删除 LLM_GATEWAY_KEY(Job 失败但 allow_failure: true 不阻断);或停用项目 Webhook |
| 自愈被熔断 | 处理自动创建的 incident Issue,次日零点自动恢复 |
| 更换/新增模型 | 改 deploy/litellm-config.yaml → docker restart litellm,业务零改动 |
| 切换评审引擎 | 项目变量 AI_REVIEW_ENGINE=codex(默认 opencode) |
| 查看 AI 成本 | 网关 /key/info 按 Key 查用量;接 Langfuse 后看调用明细 |
| 审计追溯 | GitLab 审计事件 + webhook-gateway 日志 + Langfuse 三链对照 |
Q1: MR 提交后没有 AI 评论?
按序排查:① 项目 Webhook → Recent deliveries 是否 200(401=Secret 不一致;其他=网关没收到)→ ② 网关日志是否 trigger pipeline AI_TASK=review(没有=事件被跳过:Draft MR / ai-generated 标签 / 5 分钟去重窗口)→ ③ Pipeline 里 ai-review-opencode Job 日志(401=LLM_GATEWAY_KEY 错;DNS 失败=Runner 网络不通网关)→ ④ Job 成功但无评论:GITLAB_TOKEN 权限不足或 MR 无实质 diff。
Q2: 会不会 AI 触发 AI 死循环?
不会。双保险:AI 产生的 MR 强制带 ai-generated 标签(网关跳过);网关自身触发的 Pipeline 带 AI_TASK 变量(失败事件不再触发自愈)。
Q3: 修复 MR 变更超过 5 个文件?
create_fix_mr.py 内置门禁直接退出(退出码 3),不建 MR——复杂修复属预期转人工行为。
Q4: opencode 版评审输出解析失败?
Job 会降级为空评审(评论 0 条)并不报错。追求强结构化输出可切 AI_REVIEW_ENGINE=codex(--output-schema 硬约束)。
Q5: Job 报 401 Unauthorized 调模型?
LLM_GATEWAY_KEY 未配/失效。注意网关 master_key 开启后所有调用方(CI Job、编码工具)都必须带 Key。
Q6: 内网无法访问 ghcr.io / npm / pypi? 基础镜像与 CLI(opencode-ai、sweagent、litellm)需在有网环境预下载,经内网 Registry / Nexus 代理分发。