跳过正文
  1. 博客文章/

Claude Code + GitLab pr-agent:AI 驱动的持续迭代开发实践

·1309 字·7 分钟·
DevOps AI Claude Code Pr-Agent Gitlab CI/CD Devops AI
Zayn
作者
Zayn
专注 Kubernetes、CI/CD、可观测性等云原生技术栈,记录生产环境中的实战经验与踩坑复盘。
目录
Blowfish 主题实践 - 这篇文章属于一个选集。
4: 本文
当 AI 编码助手不再只是"写代码",而是融入 Git 工作流、CI 流水线、Code Review 的完整闭环时,开发效率会发生什么变化?本文以一次博客优化项目的 32 个 MR 为实证,记录 Claude Code + GitLab pr-agent 协作的完整实践。

工具链全景
#

flowchart LR
    subgraph 开发["开发环境"]
        CC["Claude Code
(AI 编码)"] end subgraph VCS["版本控制"] GL["GitLab
(代码托管)"] end subgraph CI["持续集成"] Pipeline["CI Pipeline
(构建验证)"] PRA["pr-agent
(AI Code Review)"] end subgraph CD["持续部署"] SSH["SSH 远程部署
(Docker Compose)"] end CC -->|"git push"| GL GL -->|"触发"| Pipeline GL -->|"MR 创建"| PRA PRA -->|"评审反馈"| CC Pipeline -->|"构建成功"| SSH style CC fill:#8b5cf6,color:#fff style GL fill:#fc6d26,color:#fff style Pipeline fill:#3b82f6,color:#fff style PRA fill:#10b981,color:#fff style SSH fill:#ef4444,color:#fff
工具角色核心能力
Claude CodeAI 编码助手代码编写、脚本批处理、问题诊断、Git 操作
GitLab CI持续集成Hugo 构建验证、Docker 镜像打包
pr-agentAI 代码评审自动 Code Review、安全扫描、改进建议
glab CLIGitLab 命令行MR 创建、CI 状态查询、变量管理

核心工作流
#

每一次代码变更都遵循严格的闭环流程:

flowchart TD
    A["1. Claude Code
分析需求 + 编写代码"] --> B["2. git commit
遵循 Conventional Commits"] B --> C["3. git push
推送到功能分支"] C --> D["4. glab mr create
创建 Merge Request"] D --> E["5. CI Pipeline
自动触发构建"] D --> F["6. /review
触发 pr-agent 评审"] E --> G{"构建通过?"} F --> H{"评审通过?"} G -->|"失败"| I["诊断日志
修复问题"] H -->|"有问题"| I I --> B G -->|"通过"| J{"全部通过?"} H -->|"通过"| J J -->|"是"| K["7. glab mr merge
--squash 合并"] K --> L["8. 自动部署
SSH + Docker Compose"] L --> M["9. 清理分支"] style A fill:#8b5cf6,color:#fff style F fill:#10b981,color:#fff style K fill:#3b82f6,color:#fff style L fill:#ef4444,color:#fff

实战案例详解
#

案例 1:顺利通过——一次性合并
#

MR #8:about 页面 shortcodes 增强

# 1. Claude Code 编写代码
# (修改 content/about.md,使用 timeline/alert/mermaid/button)

# 2. 提交推送
git checkout -b optimize/content-enhancement
git add content/about.md
git commit -m "style: 增强 about 页面,使用 Blowfish shortcodes 优化展示"
git push origin optimize/content-enhancement

# 3. 创建 MR + 触发评审
glab mr create --title "style: 增强 about 页面展示效果" --target-branch main
glab mr note 8 --message "/review"

pr-agent 评审结果

评审工作量: 1/5
安全问题: 邮箱地址暴露(建议级别,非阻断)
重大问题: 无

邮箱是博主有意公开的联系方式,评审建议合理但不需要修复。直接合并。

结果:1 次提交,1 次评审,直接合并。这是最理想的流程。

案例 2:CI 失败 → 修复 → 再次通过
#

MR #7:全面优化博客质量

第一次提交后 CI 构建失败:

ERROR: error calling Fill: this method is only available for raster images.

根因:启用了 author.svg 作为头像,但 Blowfish 主题对头像调用 .Fill 方法(仅支持 PNG/JPG)。

修复流程

# 1. 诊断:查看 CI 日志
glab api "projects/.../jobs/47046/trace" | tail -20

# 2. 修复:SVG → PNG 转换
python3 -c "import cairosvg; cairosvg.svg2png(...)"

# 3. 追加提交
git add assets/img/author.png config/_default/languages.zh-cn.toml
git commit -m "fix: 修复 author image SVG 导致 Hugo 构建失败"
git push origin optimize/blog-quality-improvements

# 4. CI 自动重跑 → 通过 → 合并
教训:SVG 是矢量格式,Hugo 的图片处理管线(Resize/Fill)只支持光栅图。这个错误如果直推 main 就会导致线上构建失败。MR + CI 的价值在此。

案例 3:pr-agent 发现问题 → 修复 → 迭代
#

MR #10:Favicon + 分类统一 + 分享按钮

pr-agent 评审发现了一个真实的命名不一致:

分类命名不一致:
categories: ["Docker", "docker-compose", "DevOps"]

建议统一命名风格,例如将 docker-compose 改为 Docker Compose,
以保持与其他分类的一致性。

修复

# 接受评审建议,修改 2 个文件
# gitlab-deploy.md: "docker-compose" → "Docker Compose"
# nexus-use-traefik-proxy.md: "docker-compose" → "Docker Compose"

git add content/posts/gitlab-deploy.md content/posts/nexus-use-traefik-proxy.md
git commit -m "fix: 统一 docker-compose 分类命名为 Docker Compose"
git push origin optimize/favicon-sharing-categories

CI 重跑通过,合并。

价值:pr-agent 发现了人工容易忽略的命名不一致问题。32 个 MR 中,pr-agent 给出了有效建议的占比约 40%,真正需要修复的约 15%。

案例 4:多轮迭代——SSH 部署调试
#

MR #22 → #23 → #24 → #25:这是迭代最多的一组。

第 1 轮(MR #22):添加 SSH 部署 job,pr-agent 指出 StrictHostKeyChecking=no 安全问题,修复后合并。

第 2 轮(MR #23):部署失败,error in libcrypto。Docker Alpine 镜像的 OpenSSL 不支持 OpenSSH 密钥格式。改用默认 runner 镜像。

第 3 轮(MR #24):默认 runner 同样报 libcrypto 错误。添加 ssh-keygen -p -m PEM 运行时转换。

第 4 轮(MR #25):ssh-keygen 本身也无法读取 OpenSSH 格式。最终方案:本地预先转换为 PEM 格式,通过 glab variable update 重新上传。

# 本地转换密钥格式
ssh-keygen -p -m PEM -f /tmp/key -N "" -q
# -----BEGIN RSA PRIVATE KEY----- (PEM 格式)

# 更新 GitLab CI 变量
glab variable update SSH_PRIVATE_KEY --type file --value "$(cat /tmp/key)"
flowchart LR
    A["MR #22
SSH 部署"] -->|"pr-agent:
安全问题"| B["修复
StrictHostKeyChecking"] B --> C["MR #23
libcrypto 错误"] C -->|"换 runner"| D["MR #24
仍然报错"] D -->|"ssh-keygen
也失败"| E["MR #25
本地转 PEM"] E -->|"重试 job"| F["部署成功"] style A fill:#ef4444,color:#fff style F fill:#10b981,color:#fff

复盘:4 轮迭代看似低效,但每轮都精确缩小了问题范围。如果一开始就"猜"答案直推 main,可能需要更多次试错还会影响线上。


Claude Code 的 Git 操作模式
#

Claude Code 在整个流程中承担的不仅是"写代码",而是完整的 Git 工作流:

标准操作序列
#

# 1. 创建功能分支
git checkout -b fix/xxx

# 2. 编写代码(Claude Code 核心工作)
# ... 修改文件 ...

# 3. 提交(Conventional Commits 规范)
git add <specific-files>
git commit -m "fix: 具体修复内容"

# 4. 推送
git push origin fix/xxx

# 5. 创建 MR
glab mr create --title "fix: ..." --target-branch main

# 6. 触发评审
glab mr note <mr-id> --message "/review"

# 7. 等待 CI + 评审
sleep 45 && glab ci list --per-page=1

# 8. 检查评审结果
glab api "projects/.../merge_requests/<id>/notes"

# 9. 合并
glab mr merge <id> --squash --yes

# 10. 清理
git checkout main && git pull && git branch -D fix/xxx

关键设计决策
#

为什么用 squash merge?

每个 MR 可能有多次 fix 提交(主提交 + 评审修复),squash 合并后 main 分支保持干净的线性历史。

为什么每次都创建新分支?

GitLab 的 pre-receive hook 会校验提交信息格式,直接推 main 的长提交信息可能被拒绝。分支 + MR 是最安全的路径。

为什么用 glab 而不是 Web UI?

Claude Code 运行在终端环境,glab CLI 让整个流程可以自动化,无需切换到浏览器。从创建 MR 到合并到清理分支,全部在命令行完成。


pr-agent 评审模式分析
#

评审触发方式
#

# 在 MR 中添加评论触发
glab mr note <mr-id> --message "/review"

pr-agent 收到 /review 后自动分析 diff,生成 Persistent Review(会随新提交自动更新)。

评审输出结构
#

每次评审包含 4 个维度:

维度说明示例
Effort评审工作量(1-5)1 🔵⚪⚪⚪⚪
Tests测试相关建议No relevant tests
Security安全扫描SSH 密钥暴露、邮箱泄露
Focus Areas重点关注区域具体代码行 + 建议

32 个 MR 的评审统计
#

评审结果数量占比
无问题直接通过1959%
有建议但非阻断825%
发现需修复的问题516%

pr-agent 发现的真实有效问题:

  1. docker-compose 分类命名不一致(MR #10)
  2. StrictHostKeyChecking=no 安全风险(MR #22)
  3. CSS 选择器全局作用域过大(MR #11)
  4. Favicon 文件路径需确认存在(MR #10)
  5. 硬编码路径缺乏灵活性(MR #11)

CI 流水线架构
#

stages:
  - build          # Hugo 构建(MR + main 都触发)
  - docker-build   # Docker 镜像(仅 main)
  - deploy         # Pages + SSH 远程部署(仅 main)
flowchart TB
    subgraph MR["MR 触发"]
        B1["build
(Hugo 构建验证)"] end subgraph Main["main 触发"] B2["build"] --> D["docker-build
(镜像打包推送)"] D --> P["pages
(GitLab Pages)"] D --> S["deploy-production
(SSH 远程部署)"] end style B1 fill:#3b82f6,color:#fff style D fill:#f59e0b,color:#fff style P fill:#10b981,color:#fff style S fill:#ef4444,color:#fff

MR 阶段只跑 build 验证(Hugo 能否成功构建),不触发部署。这保证了评审阶段的安全性——即使代码有问题也不会影响线上。

合并到 main 后触发完整流水线:构建 → Docker 打包 → 双通道部署(Pages + SSH)。


效率数据
#

时间分布
#

环节平均耗时说明
代码编写1-5 分钟Claude Code 自动化
CI 构建30-45 秒Hugo 增量构建
pr-agent 评审10-30 秒自动触发
合并 + 部署2 分钟全自动
单次迭代4-8 分钟从提交到上线

32 个 MR 总耗时
#

整个博客优化项目(32 个 MR、涉及 200+ 文件变更)在单次会话中完成。


最佳实践总结
#

1. 小步提交,快速迭代
#

每个 MR 只做一件事。宁可多开 4 个 MR 调试 SSH 部署(#22-#25),也不要把所有改动塞进一个巨型 MR。

2. CI 是安全网
#

所有代码必须通过 CI 验证才能合并。author.svg 导致构建失败、summaryLength=0 导致卡片拉伸——这些问题都被 CI 拦住了。

3. 认真对待 pr-agent 建议
#

pr-agent 的建议不一定都需要修复(59% 无问题直接通过),但 16% 的真实问题值得认真对待。docker-compose 命名不一致这种细节,人工评审很难注意到。

4. 善用 glab CLI
#

# 创建 MR
glab mr create --title "..." --target-branch main

# 触发评审
glab mr note <id> --message "/review"

# 查看 CI 状态
glab ci list --per-page=1

# 查看评审结果
glab api "projects/.../merge_requests/<id>/notes"

# 合并
glab mr merge <id> --squash --yes

# 管理 CI 变量(敏感信息不入代码库)
glab variable set SSH_PRIVATE_KEY --type file --value "$(cat key)"

5. Conventional Commits 不是形式主义
#

GitLab pre-receive hook 强制校验提交信息格式。feat:fix:style:docs: 等前缀让 changelog 自动生成成为可能,也便于快速定位每个 MR 的性质。


附录:pr-agent 部署指南
#

本项目的 pr-agent 采用 Helm Chart + Kubernetes 方式部署,源码托管在 devops/gitops-apps 仓库。

架构概览
#

flowchart LR
    GL["GitLab"] -->|"Webhook
(MR event)"| PA["pr-agent
(K8s Pod)"] PA -->|"API 调用"| LLM["LLM 网关
(Claude Sonnet 4.6)"] LLM -->|"评审结果"| PA PA -->|"MR Comment"| GL style GL fill:#fc6d26,color:#fff style PA fill:#10b981,color:#fff style LLM fill:#8b5cf6,color:#fff

Helm Chart 结构
#

pr-agent/
├── Chart.yaml          # Chart 元信息
├── values.yaml         # 配置参数
└── templates/
    ├── deployment.yaml       # Pod 部署
    ├── service.yaml          # NodePort 服务
    ├── configmap.yaml        # 环境变量
    ├── secret.yaml           # 敏感信息
    ├── serviceaccount.yaml   # 服务账号
    └── ingress-traefik.yaml  # Traefik 路由(可选)

核心配置(values.yaml)
#

# 镜像配置
image:
  repository: yangzun/pr-agent
  tag: "gitlab"
  pullPolicy: Always

# 服务端口
service:
  type: NodePort
  port: 38081

# LLM 模型配置
env:
  CONFIG__MODEL: "claude-sonnet-4-6"
  CONFIG__MODEL_TURBO: "claude-sonnet-4-6"
  CONFIG__FALLBACK_MODELS: '["claude-sonnet-4-6"]'
  CONFIG__CUSTOM_MODEL_MAX_TOKENS: "2048000"

  # GitLab 集成
  CONFIG__GIT_PROVIDER: "gitlab"
  GITLAB__URL: "https://gitlab.cpinnov.run"
  CONFIG__RESPONSE_LANGUAGE: "zh-CN"

  # 评审行为
  CONFIG__IGNORE_BOT_COMMENTS: "true"
  PR_CODE_SUGGESTIONS__COMMITABLE_CODE_SUGGESTIONS: "true"
  CONFIG__LARGE_PATCH_POLICY: "compress"

  # 自定义标签
  PR_DESCRIPTION__CUSTOM_LABELS: >-
    ["Bug 修复", "功能增强", "文档更新", "测试覆盖",
     "配置变更", "代码重构", "CI/CD 维护", "依赖升级"]
  PR_DESCRIPTION__PUBLISH_LABELS: "true"

部署步骤
#

# 1. 克隆 GitOps 仓库
git clone git@gitlab.cpinnov.run:devops/gitops-apps.git
cd gitops-apps/pr-agent

# 2. 配置密钥(values.yaml 中的 secret 部分)
# GITLAB__PERSONAL_ACCESS_TOKEN: GitLab PAT(api scope)
# GITLAB__SHARED_SECRET: Webhook 签名密钥
# OPENAI__KEY: LLM API 密钥

# 3. 部署到 Kubernetes
helm install pr-agent . -n pr-agent --create-namespace

# 4. 配置 GitLab Webhook
# URL: http://<node-ip>:38081/webhook
# Trigger: Merge request events + Note events
# Secret: 与 GITLAB__SHARED_SECRET 一致

GitLab Webhook 配置
#

在每个需要启用 pr-agent 的仓库中:

Settings → Webhooks → Add webhook

配置项
URLhttp://<pr-agent-host>:38081/webhook
Secret tokenGITLAB__SHARED_SECRET 一致
TriggerMerge request events, Comments
SSL verification按实际环境选择

配置完成后,在任意 MR 中评论 /review 即可触发 AI 代码评审。


写在最后
#

这套工作流的核心价值不在于"AI 写了代码",而在于 AI 融入了完整的工程化闭环

  • Claude Code 不只是代码生成器,它理解 Git 规范、操作 glab CLI、诊断 CI 日志
  • pr-agent 不只是语法检查器,它能发现命名不一致、安全隐患、架构建议
  • CI Pipeline 不只是构建工具,它是防止错误上线的最后一道防线

三者协同,让 32 个 MR 在一次会话中从创建到上线,每个变更都经过构建验证和 AI 评审,没有一次直推 main。

查看博客优化复盘
Blowfish 主题实践 - 这篇文章属于一个选集。
4: 本文

相关文章

企业级 GitLab 平台部署与运维完整指南
·3964 字·19 分钟
Docker Docker Compose DevOps Gitlab Docker Devops Git CI/CD
Python DevOps 完整实战指南
·5640 字·27 分钟
DevOps 编程 自动化运维 Python Devops 自动化 运维开发 基础设施即代码 CI/CD
在 Kubernetes 中使用 localPv 部署 Gitlab
·616 字·3 分钟
Kubernetes DevOps Ingress Gitlab CI/CD Localpv Postgres Redis