前言
本文介绍如何在自建 GitLab 中实现基于 Claude Code 的自动代码评审,而无需依赖 GitLab 企业版的 AI 能力(GitLab Duo)。
只需:
- 一个 Claude Code Max 订阅
- 一个配置了代理的 GitLab Runner
就能为团队带来 AI 代码评审的能力,生成 Markdown 和 PDF 格式的评审报告。
前置准备
个人建议
不要在 CI 中使用个人订阅,应使用 Anthropic 的 API 服务而不是个人订阅,个人订阅会因为违反使用条款中的多人共享规则而被封禁,这是我个人被封禁 2 个 Max 帐号后的经验。
如果不方便接入 Anthropic API,可以考虑接入 OpenRouter 等第三方 API 服务商。 另外,阿里云的 Qwen3 也是一个可行的方案,但实测下来报告质量不如 Opus 4.5,表达不够简洁,内容相对价值下降。
订阅 Claude Code Max
为了保证代码评审报告的质量,我们选择了支持 Opus 模型的 Max 套餐。
对于在中国的用户,可通过 iOS 应用内购买完成订阅:
- 通过 giffgaff 获取英国手机号,使用 Google 账号登录 claude.ai 完成注册
- 准备美区 Apple ID,在 Apple 官网购买礼品卡并充值
- 在 iPhone 上下载 Claude App,使用应用内购买完成订阅
| 订阅方式 | Max 套餐(5x) | Max 套餐(20x) |
|---|---|---|
| 官网直接订阅(需美国信用卡) | $100/月 | $200/月 |
| iOS 应用内购买 | $125/月 | $250/月 |
网络环境要求
Claude Code 使用 OAuth Token 认证,需要访问 Anthropic 服务。如果 GitLab Runner 部署在中国大陆,需要配置透明代理,使流量通过美国等地区的代理服务器进行转发,也可直接使用美国地区的服务器作为 Runner。
实现步骤
构建 Docker 镜像
将 Claude Code 及依赖封装到 Docker 镜像中,避免每次 CI 都执行安装操作:
FROM ghcr.io/puppeteer/puppeteer:24
USER root
WORKDIR /root
RUN npm install -g @anthropic-ai/claude-code md-to-pdf
镜像包含 Claude Code 和 md-to-pdf 的运行环境。
配置 GitLab CI
获取并配置 Token
执行 claude setup-token 获取以 sk-ant-oat01- 开头的 Token。
在 GitLab 项目的 Settings -> CI/CD -> Variables 中添加:
- Key:
CLAUDE_CODE_OAUTH_TOKEN - Protected: 开启(只有保护分支可读取,确保 Token 安全)
- Masked: 开启
配置 Markdown 转 PDF 的配置文件
这份配置文件可解决代码高亮和代码过长导致的显示不全问题。
在 GitLab 项目的 Settings -> CI/CD -> Variables 中添加:
- Key:
MD_TO_PDF_CONFIG_FILE - Protected: 开启
- Masked: 关闭
- Type: File
module.exports = {
stylesheet: [
'https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.5.1/github-markdown.min.css'
],
highlight_style: 'atom-one-light',
body_class: 'markdown-body',
marked_options: {
headerIds: true,
smartypants: true,
gfm: true,
breaks: false,
},
pdf_options: {
format: 'A4',
margin: {
top: '20mm',
right: '20mm',
bottom: '25mm',
left: '20mm'
},
printBackground: true,
displayHeaderFooter: true,
headerTemplate: '<div></div>',
footerTemplate: `
<div style="font-size: 10px; width: 100%; text-align: center; color: #888;">
<span class="pageNumber"></span> / <span class="totalPages"></span>
</div>
`,
},
launch_options: {
args: [
"--no-sandbox",
"--disable-setuid-sandbox"
]
},
css: `
pre,
pre code,
pre code.hljs,
code,
.hljs {
white-space: pre-wrap !important;
word-wrap: break-word !important;
word-break: break-all !important;
overflow-wrap: break-word !important;
}
pre {
max-width: 100% !important;
overflow-x: visible !important;
padding: 12px;
border-radius: 8px;
font-size: 12px;
line-height: 1;
background-color: #f6f8fa !important;
page-break-inside: avoid;
}
pre > code {
display: block !important;
max-width: 100% !important;
overflow: visible !important;
}
code {
font-family: 'Cascadia Code', 'JetBrains Mono', 'Fira Code', monospace;
}
@media print {
pre, pre code, .hljs {
white-space: pre-wrap !important;
word-break: break-all !important;
overflow: visible !important;
}
}
.markdown-body {
font-size: 12px;
max-width: 100% !important;
overflow: hidden;
}
`
};
CI 配置
stages:
- code-review
- build-assets
- build-docker-image
- deploy
claude-code-review:
image: registry.example.com/infrastructure/claude-code:v0.0.1
tags:
- us-proxy # 配置了透明代理的 Runner
stage: code-review
variables:
GIT_DEPTH: 100
script:
- git fetch --depth=20 origin main:main
- |
claude \
--model opus \
--permission-mode acceptEdits \
--allowedTools "Bash(*) Read(*) Edit(*) Write(*)" \
-p "$(cat << EOF
对 main 到 ${CI_COMMIT_BRANCH} 的所有 commits 进行代码审查。
要求:
1. 将中文报告写入到 ${CI_PIPELINE_ID}_review.md 文件内,不要改动其他文件
2. 分析当前代码状态中仍存在的问题
3. 对于每个问题,必须包含以下内容:
- 问题所在的文件路径和行号(基于当前代码状态)
- 问题代码片段(使用 markdown 代码块)
- 问题分析:解释为什么这是一个问题
- 修复建议:给出具体的修复方案或代码示例
4. 按严重程度分类:严重、高、中、低
5. 不要使用 emoji
6. 使用 markdown list 格式(避免 markdown table)
7. 如果没有发现问题,说明代码质量良好即可
重点关注:
- 潜在的 bug 和逻辑错误
- 安全漏洞
- 性能问题
- 未清理的调试代码
- 类型错误或类型不安全
分析策略:
1. 按时间顺序(从旧到新)分析所有 commits
2. 对于每个 commit 中发现的问题,检查后续 commits 是否已修复该问题
3. 如果问题已被后续 commit 修复,则不要在最终报告中包含该问题
4. 只报告在当前代码状态中仍然存在的问题
判断问题已修复的标准:
- 问题代码在后续 commit 中被删除或重写
- 后续 commit 的改动明确解决了该问题(如修复了 bug、添加了缺失的校验等)
- 同一位置的代码逻辑在后续 commit 中被优化或改进
EOF
)"
- md2pdf --config-file ${MD_TO_PDF_CONFIG_FILE} ${CI_PIPELINE_ID}_review.md
- |
echo \
"markdown: ${CI_SERVER_URL}/${CI_PROJECT_PATH}/-/jobs/${CI_JOB_ID}/artifacts/raw/${CI_PIPELINE_ID}_review.md"
- |
echo \
"pdf: ${CI_SERVER_URL}/${CI_PROJECT_PATH}/-/jobs/${CI_JOB_ID}/artifacts/file/${CI_PIPELINE_ID}_review.pdf"
artifacts:
paths:
- "*_review.md"
- "*_review.pdf"
when: always
rules:
- if: '$CI_COMMIT_BRANCH != "main"'
# 省略了后续的构建和部署阶段
工作流程
main → feature/* → release → 触发 CI 代码评审 → 审阅报告 → 测试环境验证通过 → main
开发者从 main 拉出 feature 分支进行开发,运维从 main 拉出 release 分支。开发完成后,将 feature 分支合并到 release 分支,此时触发代码评审并部署测试环境。评审报告通过且测试环境验证无误后,再将 release 分支合并回 main。
安全策略
将 release 分支设置为保护分支,配合 Protected Variable:
- 只有保护分支的 CI 任务能读取
CLAUDE_CODE_OAUTH_TOKEN - 普通 feature 分支无法获取 Token,避免泄露风险
- 保护分支只有运维可以删除
代码评审在开发分支合并到 release 分支时触发,作为 CI 的第一个 Stage 执行。
使用方式
CI 完成后,日志末尾会输出报告链接:
- 通过 PDF 文件链接,直接在线预览报告
- 通过 Markdown 文件链接,下载到本地后在 VSCode 中查看(方便复制黏贴)
报告作为 GitLab Artifacts 永久保存。
总结
这种方式的优势:
- 低门槛:基于 GitLab CE 即可实现,无需企业版
- 低成本:只需 Claude Code Max 订阅费用
- 安全可控:Token 通过 Protected Variable 保护,代码和报告都在自建 GitLab 中
- 灵活定制:Prompt 可根据团队需求调整评审重点