📅 原文发布:2018-2019 | 本次更新:2025-06 | 更新等级:🔴全面重写增强 📌 v2 结构化升级:2026-08 | 升级范围:补齐 6 节标准骨架、Mermaid 图加标题、术语英文对照、参考资料融入进阶延展
在前面几期文章中,笔者分别详细介绍了持续交付体系基础层面的建设,主要是多环境和配置管理。这些是持续交付自动化体系的基础,是与实际的业务场景和特点强相关的,希望读者一定要重视基础的建设。
本期文章是持续交付系列的第 6 篇文章,从本期开始,进入到 交付流水线体系(Delivery Pipeline System) 相关的内容介绍中。
从一个应用的代码提交开始,到发布线上的主要环节,整个流程串起来就是一个简化的流水线模式。
笔者前面介绍了持续交付的多环境以及配置管理,而流水线模式的整个过程正是在这个基础上执行。功能测试在线下环境完成,非功能验收(性能、安全等)在线上预发或 Beta 环境完成。
原版的核心思路:要求业务架构师在做需求分析和功能设计时,要针对一个需求进行拆分,最终拆分成一个个的功能点,这些功能点最终落实到一个个对应的应用中,对应的逻辑体现就是应用代码的一个 feature 分支。
这样做的好处:从一开始的需求管理维度,就确定了最终多个应用联调、测试以及最终发布的计划和协作方式。
现代工具链支持:
原版引用了亚马逊 CEO 杰夫·贝佐斯(Jeff Bezos)提出的 "两个披萨原则"(Two-Pizza Rule) —— 团队规模应该保持在两个披萨能喂饱的程度(6-8 人),这样沟通成本低、效率高。
这个原则在 2025 年依然有效,但有了新的诠释:
| 维度 | 2019 年理解 | 2025 年扩展 |
|---|---|---|
| 团队规模 | 6-8 人/团队 | 产品团队 ≤ 10 人,通过 IDP 赋能 |
| 流水线归属 | 每团队一条 | Golden Paths — 预配置模板 |
| 协作方式 | 同一物理位置 | 分布式 + 异步协作(Git + PR) |
| 自治程度 | 全栈自治 | 端到端拥有权(build → run → fix) |
| 模式 | 特点 | 原版评价 |
|---|---|---|
| 主干开发(Trunk-Based) | 所有代码直接提交 master,确保随时可发布 | 对质量和 CI 要求极高 |
| GitFlow | master + develop 分支,release 分支发布 | 分支管理代价高 |
| 分支开发(简化版) | feature/release 分支从 master 签出,简洁清晰 | 推荐 |
Trunk-Based 的关键实践:
# .github/workflows/ci.yml (示例)
name: CI Pipeline
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true
- name: Build
run: go build -o app ./...
- name: Test
run: go test -race -coverprofile=coverage.out ./...
- name: Upload coverage
uses: codecov/codecov-action@v4| 阶段 | 目标时间 | 优化手段 |
|---|---|---|
| Lint + Format | < 30 秒 | 本地 pre-commit hook |
| Unit Test | < 2 分钟 | 并行执行 + 缓存依赖 |
| Build | < 3 分钟 | 远程 BuildKit cache |
| SAST/SCA | < 2 分钟 | 增量扫描 |
| 总计 | < 5 分钟 | 并行化是关键 |
如果团队暂时不具备全面 Trunk-Based 的条件,GitHub Flow 是最推荐的过渡方案:
main 分支始终可部署main 创建 feature 分支main(需要 CI 通过 + Code Review)| 场景 | 推荐方案 | 替代方案 | 不推荐 |
|---|---|---|---|
| CI 引擎 | GitHub Actions | GitLab CI, Tekton | Jenkins freestyle (无 IaC) |
| CI 定义格式 | YAML (Actions/GitLab) | Jenkinsfile (Declarative) | Jenkins UI 配置 |
| 可复用模板 | Composite Actions / Reusable Workflows | Jenkins Shared Libraries | 复制粘贴相同配置 |
| 构建缓存 | Actions Cache / BuildKit cache | Nexus Repository Manager | 无缓存(每次全量构建) |
| 制品管理 | GitHub Packages / Harbor OCI | JFrog Artifactory, ECR | 本地文件系统 |
| 安全门禁 | Dependabot + CodeQL + Trivy | Snyk, SonarQube | 无安全扫描 |
流水线基础
- 是否选择了合适的 CI 引擎(推荐 GitHub Actions)
- 流水线定义是否为 YAML as Code(非 UI 配置)
- 是否有可复用的模板/共享 workflow
- 是否建立了 branch protection rules
速度与效率
- PR 触发到 CI 结果反馈是否 < 5 分钟
- 是否充分利用了并行执行
- 构建缓存是否生效(避免重复下载依赖)
- 是否有增量构建/增量扫描能力
质量保障
- 是否集成了自动化 lint/format 检查
- 单元测试覆盖率是否达标
- 是否有 SAST/SCA 安全扫描
- PR 是否有强制 Code Review 机制
制品管理
- 构建产物是否推送到制品仓库
- 是否生成了 SBOM
- 镜像是否经过签名(Sigstore/cosign)
- 是否有清理策略(避免仓库膨胀)
开发者体验
- 开发者是否能自助创建需要的流水线
- CI 失败信息是否清晰易懂
- 是否有本地预检能力(pre-commit hooks)
- 流水线状态是否在 PR 中清晰展示
❌ 陷阱1:"单体巨石流水线"
症状:一个pipeline跑完要30-60分钟
根因:所有步骤串行,没有并行化
后果:开发者等待时间长,反馈循环慢
解法:分析依赖图,最大化并行执行
❌ 陷阱2:"流水线即代码但没人维护"
症状:YAML文件几百行,没人敢改
根因:缺少抽象和复用
后果:技术债务积累,越来越难改
解法:提取Composite Actions / Reusable Workflows
❌ 陷阱3:"每次都全量构建"
症状:即使只改了一行代码也要重新编译所有内容
根因:没有利用缓存
后果:浪费大量计算资源和时间
解法:依赖缓存 + 增量构建 + 远程BuildKit cache
❌ 陷阱4:"安全扫描只在最后做"
症状:跑完所有测试才发现有高危漏洞
根因:安全左移没做好
后果:浪费前面所有步骤的计算资源
解法:SAST/SCA与Unit Test并行,尽早失败
❌ 陷阱5:"忽略CI性能监控"
症状:不知道流水线平均耗时多少
根因:没有度量意识
后果:无法识别瓶颈,无法优化
解法:建立CI Dashboard,追踪P50/P95/P99耗时| 中文 | 英文 |
|---|---|
| 交付流水线体系 | Delivery Pipeline System |
| 主干开发 | Trunk-Based Development |
| 两个披萨原则 | Two-Pizza Rule |
| 黄金路径 | Golden Path |
| 内部开发者平台 | Internal Developer Platform (IDP) |
| 可复用工作流 | Reusable Workflows |
| 矩阵构建 | Matrix Build |
| 快速反馈循环 | Fast Feedback Loop |
| 分支保护规则 | Branch Protection Rules |
| 代码所有者 | CODEOWNERS |
| 声明式定义 | Declarative Definition |
下一期文章将重点介绍 软件构建 的相关细节——构建过程中有哪些关键问题和注意事项?
读者所在团队的流水线目前是怎样的?遇到过哪些痛点?