PR 是人审查代码的环节,CI/CD 是机器自动检查和自动发布的环节。两者配合实现"提交 PR → 机器自动验证 → 人工审批 → 自动发布上线"的全自动化流程。
一、PR 与 CI/CD 的定位差异
PR 和 CI/CD 不是替代关系,而是接力配合。理解两者的定位差异是掌握现代开发流程的前提。
核心定位对比
| 是什么 | ||
| 执行者 | 人 | 机器 |
| 核心作用 | ||
| 触发时机 | ||
| 解决问题 |
协作关系
PR 提供了人和机器协作的关键节点:
代码变更
↓
机器做粗筛 (CI 自动测试)
↓
人做精审 (Code Review)
↓
机器自动发布 (CD 自动部署)
关键认知:PR 是决策点,CI/CD 是执行层。PR 解决"改得对不对",CI/CD 解决"怎么自动验证和上线"。
二、CI 和 CD 的本质区别
CI/CD 是两个独立的概念,必须分开理解。
CI:Continuous Integration(持续集成)
定义:每次代码变动,自动运行测试和构建,确保新代码不破坏已有功能。
触发时机:
提交代码到分支 发起 Pull Request 更新 PR 代码
执行内容:
自动运行测试(单元测试、集成测试) 代码规范检查(Linting) 安全漏洞扫描 构建产物验证
核心目标:早发现问题,阻止有问题的代码合并。
CD:Continuous Delivery/Deployment(持续交付/部署)
定义:CI 通过后,自动把代码发布到测试或生产环境。
触发时机:
CI 检查通过 代码合并到主分支 创建发布标签(tag)
执行内容:
打包构建产物 部署到服务器 重启服务 灰度发布 发送通知
核心目标:让代码自动上线,消除手动部署环节。
CI 和 CD 的执行顺序
代码变动
↓
┌─────────┐
│ CI │ 自动测试 + 构建 ← 验证"这代码能不能用"
└─────────┘
↓ 通过
┌─────────┐
│ CD │ 自动部署 + 发布 ← 执行"把它上线"
└─────────┘
↓
用户可以使用新功能
三、PR 与 CI/CD 的完整配合流程
这是理解两者协作的核心。一次完整的开发流程包含以下步骤:
步骤 1:开发者提交代码
# 在 feature 分支开发
git checkout -b feature/login-fix
# 编写代码
git commit -m "fix: 修复登录超时问题"
git push origin feature/login-fix
步骤 2:创建 PR,触发 CI
PR 一旦创建,CI 立即自动触发:
┌──────────────────────────────────────────────────────────────┐
│ CI 自动执行流程 (在 PR 页面实时显示) │
│ │
│ ✅ Lint Check 代码规范检查 │
│ ✅ Unit Tests (128/128) 单元测试全部通过 │
│ ✅ Integration Tests 集成测试通过 │
│ ✅ Build Docker Image 构建镜像成功 │
│ ✅ Security Scan 无安全漏洞 │
│ ✅ Coverage Check 测试覆盖率 85% │
│ │
│ → PR 状态: "All checks passed ✅" │
└──────────────────────────────────────────────────────────────┘
CI 检查的内容:
┌────────────────────────────────────────────────────┐
│ 🔍 代码质量检查 (Lint) │
│ ├── ESLint / Pylint 代码规范验证 │
│ ├── 静态类型检查(TypeScript/Rust 编译) │
│ └── 测试覆盖率检查(不低于 80%) │
├────────────────────────────────────────────────────┤
│ 📦 构建阶段 (Build) │
│ ├── 编译代码生成产物 │
│ └── 打包 Docker 镜像 │
├────────────────────────────────────────────────────┤
│ 🧪 测试阶段 (Test) │
│ ├── 单元测试(函数级验证) │
│ ├── 集成测试(模块协作验证) │
│ └── 端到端测试(完整流程验证) │
├────────────────────────────────────────────────────┤
│ 📊 报告阶段 (Report) │
│ ├── 测试覆盖率报告 │
│ ├── 代码规范得分 │
│ └── 性能基准测试 │
└────────────────────────────────────────────────────┘
步骤 3:CI 通过,等待人工审查
PR 页面显示:
┌──────────────────────────────────────────────────────────────┐
│ Pull Request #234: 修复登录超时问题 │
│ │
│ ✅ All checks have passed │
│ │
│ [View Details] CI 检查全部通过,可以进行代码审查 │
│ [Merge] │
└──────────────────────────────────────────────────────────────┘
CI 在 PR 阶段的作用称为 PR Gate(PR 门禁):
CI 全部通过 → Merge 按钮点亮 CI 有失败项 → Merge 按钮置灰,无法合并
步骤 4:人工审查代码
审查重点:
同事审查内容:
├── 业务逻辑是否正确
├── 代码设计是否合理
├── 是否有更优的实现方案
├── 是否符合团队规范
└── 是否有潜在风险
(语法、测试、构建问题已被 CI 过滤)
审查流程:
1. 查看代码差异(Diff)
2. 逐行评论、提建议
3. 讨论实现方案
4. 确认无问题后点击 "Approve"
步骤 5:合并代码,触发 CD
审查通过后点击 Merge:
# 代码自动合并到 main 分支
git merge feature/login-fix
CD 流水线立即触发:
┌──────────────────────────────────────────────────────────────┐
│ CD 自动执行流程(合并到 main 后触发) │
│ │
│ ① 构建 Production 镜像 │
│ └── docker build -t app:v1.2.3 . │
│ │
│ ② 推送到镜像仓库 │
│ └── docker push registry.company.com/app:v1.2.3 │
│ │
│ ③ 部署到测试环境 │
│ └── kubectl apply -f deployment-test.yaml │
│ │
│ ④ 运行验收测试 (Smoke Test) │
│ └── 验证核心功能是否正常 │
│ │
│ ⑤ 部署到生产环境 │
│ └── 灰度发布:5% → 20% → 50% → 100% │
│ │
│ ⑥ 发送通知 │
│ └── 钉钉/飞书: "v1.2.3 已成功发布到生产环境 ✅" │
└──────────────────────────────────────────────────────────────┘
步骤 6:用户使用新功能
整个流程完成,用户可以使用修复后的登录功能。
开发者实际操作:
编写代码 提交 PR 等待 CI 检查通过 等待同事审查 点击 Merge
自动化完成的工作:
CI:运行测试、检查代码、构建镜像 CD:部署测试环境、运行验收、发布生产、发送通知
四、PR 的三大核心作用
一个 PR 不只是一次代码提交,它是一个完整的代码变更提案。
PR 的组成部分
| 代码差异 (Diff) | ||
| 描述说明 | ||
| 审查讨论 | ||
| CI 检查 | ||
| 关联信息 |
PR 的三大价值
1. 代码质量把关
多人审查机制:
- 主开发者实现功能
- 至少 1-2 位同事审查
- 发现设计问题、逻辑漏洞
- 确保代码可维护性
2. 知识传播和团队协作
审查过程中的知识流动:
- 审查者了解代码改动
- 讨论中分享最佳实践
- 新人通过审查学习
- 团队统一代码风格
3. 保护主分支安全
主分支(main/master)保护机制:
- 禁止直接推送
- 必须通过 PR 合并
- CI 检查必须通过
- 至少 N 人审查批准
代码流向:
feature 分支(你的改动)
↓
PR(审查关卡)
↓
main 分支(受保护的稳定代码)
主分支始终保持稳定,有问题的代码在 PR 阶段就被拦截。
五、三种主流的 CI/CD 触发策略
不同团队根据自动化程度和风险偏好,采用不同的触发策略。
策略对比
| 保守型 | |||
| 平衡型 | |||
| 激进型 |
CD 的两种自动化程度
Continuous Delivery(持续交付):
CD 流水线构建完成后:
├── 自动部署到测试环境
├── 运行自动化测试
└── 发布到生产需要人工点击确认 ← 人工决策
特点:最后一步需要人工批准,安全性更高。
Continuous Deployment(持续部署):
CD 流水线构建完成后:
├── 自动部署到测试环境
├── 运行自动化测试
├── 测试通过后自动发布到生产 ← 全自动
└── 用户立即可用
特点:测试通过后完全自动发布,发布速度最快。
选择建议:
大多数公司使用 Continuous Delivery(持续交付),保留人工决策点 高度自动化的互联网公司使用 Continuous Deployment(持续部署),追求极致速度
六、真实场景:修复 Bug 的完整流程
通过一个完整的 Bug 修复流程,展示 PR 和 CI/CD 的实际配合。
场景:修复登录超时问题
第 1 天:发现问题
用户反馈:登录时经常超时
问题定位:登录接口超时设置为 5 秒,实际需要 10 秒
解决方案:修改超时配置为 15 秒
第 2 天:开发和提交
# 1. 创建修复分支
git checkout -b fix/login-timeout
git checkout main
git pull origin main
git checkout -b fix/login-timeout
# 2. 修改代码
# 文件: src/auth/config.ts
- timeout: 5000, // 5 秒
+ timeout: 15000, // 15 秒
# 3. 添加测试用例
# 文件: tests/auth.test.ts
test('登录接口应该在 15 秒内响应', async ()=>{
const result = await login({ timeout: 15000});
expect(result).toBeDefined();
});
# 4. 提交代码
git add src/auth/config.ts tests/auth.test.ts
git commit -m "fix: 修复登录超时问题,将超时时间从 5s 调整为 15s"
git push origin fix/login-timeout
第 3 天:创建 PR,CI 自动检查
┌──────────────────────────────────────────────────────────────┐
│ Pull Request #456 │
│ 标题: fix: 修复登录超时问题 │
│ │
│ 描述: │
│ - 问题:用户反馈登录经常超时 │
│ - 原因:超时设置为 5 秒,实际需要 10 秒 │
│ - 方案:调整超时为 15 秒,增加缓冲 │
│ - 关联:Issue #123 │
│ │
│ CI 检查状态: │
│ ✅ ESLint Check (0 errors) │
│ ✅ Unit Tests (136/136 passed) │
│ ✅ Integration Tests (24/24 passed) │
│ ✅ Build (success) │
│ ✅ Security Scan (no vulnerabilities) │
│ │
│ All checks passed ✅ │
│ [Merge] │
└──────────────────────────────────────────────────────────────┘
CI 运行详情:
GitHub Actions 运行日志:
Job: CI Check
├── Step 1: Checkout code ✅ 2s
├── Step 2: Setup Node.js 18 ✅ 5s
├── Step 3: Install dependencies ✅ 23s
├── Step 4: Run linter ✅ 4s
│ └── ESLint: 0 errors, 0 warnings
├── Step 5: Run unit tests ✅ 12s
│ └── 136 tests passed, 0 failed
├── Step 6: Run integration tests ✅ 45s
│ └── 24 tests passed, 0 failed
├── Step 7: Build Docker image ✅ 67s
│ └── Image: app:pr-456
└── Step 8: Security scan ✅ 18s
└── No vulnerabilities found
Total time: 2m 56s
第 4 天:人工审查
审查者 A (Tech Lead):
✅ 代码改动合理
💬 评论: "建议在文档中说明超时时间的选择依据"
审查者 B (Backend Developer):
✅ 已批准
💬 评论: "测试用例覆盖充分,LGTM"
作者回复:
💬 "已更新 README,添加了超时配置说明"
审查者 A:
✅ 最终批准 (Approved)
第 5 天:合并代码,CD 自动发布
点击 Merge 按钮
↓
┌──────────────────────────────────────────────────────────────┐
│ CD Pipeline: Deploy to Production │
│ │
│ Trigger: Merge to main branch │
│ Commit: a3f7b2c "fix: 修复登录超时问题" │
│ │
│ [09:00] ① 构建 Production 镜像 │
│ └── docker build -t app:v1.2.3 │
│ └── 耗时: 1m 45s ✅ │
│ │
│ [09:02] ② 推送到镜像仓库 │
│ └── docker push registry.company.com/app:v1.2.3 │
│ └── 耗时: 32s ✅ │
│ │
│ [09:03] ③ 部署到测试环境 │
│ └── kubectl apply -f k8s/deployment-test.yaml │
│ └── 耗时: 12s ✅ │
│ │
│ [09:04] ④ 运行验收测试 │
│ └── 测试登录功能 │
│ └── 测试订单功能 │
│ └── 测试支付功能 │
│ └── 12/12 tests passed ✅ │
│ │
│ [09:06] ⑤ 灰度发布到生产环境 │
│ ├── 5% 流量 → 监控 5 分钟 ✅ │
│ ├── 20% 流量 → 监控 5 分钟 ✅ │
│ ├── 50% 流量 → 监控 10 分钟 ✅ │
│ └── 100% 流量 → 全量发布 ✅ │
│ │
│ [09:27] ⑥ 发送通知 │
│ └── 飞书通知: "v1.2.3 已成功发布 ✅" │
│ └── 钉钉通知: "登录超时修复已上线" │
│ │
│ 部署完成!总耗时: 27 分钟 │
└──────────────────────────────────────────────────────────────┘
结果:
用户在 09:30 开始使用修复后的登录功能 监控显示登录超时率从 15% 降低到 0.2% 问题得到解决
开发者实际操作:
编写代码(30 分钟) 创建 PR(2 分钟) 等待审查和合并(1 天) 点击 Merge(1 秒)
自动化完成的工作:
CI 检查(3 分钟) CD 部署(27 分钟) 全程无需人工介入部署流程
七、CI/CD 的整体价值
对比有无 CI/CD 的开发效率和质量差异。
价值对比
| 发布速度 | ||
| 质量保障 | ||
| 回归风险 | ||
| 发布频率 | ||
| 人力成本 | ||
| 错误发现 | ||
| 部署一致性 |
效率提升数据
发布效率提升:
传统手动发布流程:
├── 开发完成 ← 1 天
├── 手动测试 ← 2 小时
├── 找运维协调发布时间 ← 半天
├── 手动构建打包 ← 30 分钟
├── 上传到服务器 ← 15 分钟
├── 手动部署 ← 30 分钟
├── 重启服务 ← 10 分钟
└── 验证功能 ← 30 分钟
总计: 约 2 天
使用 CI/CD:
├── 开发完成 ← 1 天
├── 创建 PR ← 2 分钟
├── CI 自动测试 ← 3 分钟
├── 人工审查 ← 1 小时
├── 点击 Merge ← 1 秒
└── CD 自动部署 ← 27 分钟
总计: 约 1 天
效率提升:50% 的时间节省。
质量提升:
人工测试覆盖率: 约 30-40%
自动化测试覆盖率: 可达 80-90%
人工发现的 Bug 数量: 较少
CI 自动发现的问题: 更多更早
八、主流 CI/CD 工具选型
根据团队规模和技术栈选择合适的 CI/CD 工具。
工具对比
| GitHub Actions | |||
| GitLab CI | |||
| Jenkins | |||
| CircleCI | |||
| Travis CI | |||
| ArgoCD |
选型建议
选择 GitHub Actions:
代码托管在 GitHub 中小型团队 需要快速上手
选择 GitLab CI:
使用 GitLab 作为代码仓库 需要完整的 DevOps 平台 私有部署需求
选择 Jenkins:
已有 Jenkins 基础设施 需要高度自定义 传统企业环境
选择 ArgoCD:
使用 Kubernetes 采用 GitOps 理念 需要声明式部署
九、最佳实践与常见问题
总结 PR 和 CI/CD 配合使用的最佳实践。
最佳实践
1. PR 提交规范
PR 标题规范:
- feat: 新功能
- fix: Bug 修复
- docs: 文档更新
- refactor: 代码重构
- test: 测试相关
- chore: 构建/工具链更新
PR 描述模板:
## 改动内容
简要描述本次改动
## 改动原因
说明为什么需要这个改动
## 测试方法
如何验证这个改动
## 关联 Issue
Closes #123
2. CI 检查配置
必须包含的检查项:
✅ 代码规范检查(强制)
✅ 单元测试(强制)
✅ 构建验证(强制)
⚠️ 测试覆盖率(警告)
⚠️ 性能测试(警告)
3. Code Review 标准
审查清单:
□ 代码逻辑是否正确
□ 是否有更优的实现方案
□ 是否符合团队规范
□ 测试用例是否充分
□ 文档是否更新
□ 是否有安全隐患
4. CD 发布策略
推荐的发布流程:
1. 部署到测试环境
2. 运行自动化验收测试
3. 灰度发布到生产(5% → 20% → 50% → 100%)
4. 监控关键指标
5. 出现问题立即回滚
常见问题与解决方案
问题 1:CI 检查时间过长
问题: CI 运行需要 30 分钟,影响开发效率
解决方案:
- 并行运行测试
- 使用缓存加速依赖安装
- 分离快速检查和慢速检查
- 只在 PR 中运行核心测试,合并后运行完整测试
问题 2:频繁的 CI 失败
问题: 测试不稳定,经常失败
解决方案:
- 修复不稳定的测试用例
- 增加测试重试机制
- 隔离外部依赖(使用 Mock)
- 定期维护测试代码
问题 3:PR 审查效率低
问题: PR 长时间无人审查
解决方案:
- 设置自动分配审查者
- 限制 PR 大小(建议不超过 400 行)
- 设置审查时效要求
- 使用 PR 模板规范描述
问题 4:部署失败后难以回滚
问题: 新版本有问题,回滚困难
解决方案:
- 采用蓝绿部署或金丝雀发布
- 保留最近 N 个版本的镜像
- 实现一键回滚脚本
- 在 CD 流水线中添加回滚步骤
最后
核心结论:
PR 和 CI/CD 是现代软件工程的核心自动化流水线。PR 提供人工审查的决策点,CI/CD 提供机器自动化的执行层。两者配合形成"提交代码 → 机器验证 → 人工审批 → 自动发布"的完整闭环。
技术本质:
PR (Pull Request)
├── 角色:代码变更的审查关卡
├── 执行者:人(开发团队)
└── 价值:质量把关 + 知识共享 + 主分支保护
CI (Continuous Integration)
├── 角色:自动化质量检查
├── 执行者:机器(自动化流水线)
└── 价值:早期发现问题 + PR 门禁
CD (Continuous Delivery/Deployment)
├── 角色:自动化部署发布
├── 执行者:机器(自动化流水线)
└── 价值:快速上线 + 降低人工成本
协作流程:
开发者改代码
↓
创建 PR
↓
CI 自动检查(测试、构建、扫描)
↓
CI 全部通过 → Merge 按钮点亮
↓
团队成员 Code Review
↓
审查通过点击 Merge
↓
代码合并到 main
↓
CD 自动触发(构建、部署、发布)
↓
用户使用新功能
价值总结:
适用场景:
现代软件开发中,PR + CI/CD 已成为标准配置,适用于:
Web 应用开发 移动应用开发 后端服务开发 云原生应用 开源项目协作
关键认知:
PR 和 CI/CD 的配合体现了 DevOps 的核心理念:通过自动化流水线提升开发效率,通过人机协作保障代码质量。机器做重复性工作(测试、构建、部署),人专注于创造性工作(设计、审查、决策)。
这就是现代软件工程的自动化本质。
延伸阅读:
这套"PR + CI/CD"的流水线是 DevOps 思想的具体落地。更先进的玩法是 GitOps——用 Git 仓库作为唯一真相源,集群状态和 Git 严格一致,任何变更都通过 PR 驱动。这是云原生时代将基础设施和部署全部用 Git 管理的最新实践。
本文系统阐述了 PR 与 CI/CD 的配合机制,希望对你理解现代开发流程有所帮助。
夜雨聆风