流水线在做什么
代码 → Lint/Format → Test → Build → 安全扫描 → 推工件 → 部署 → 验证
有的项目还多 / 少一两步,但这个骨架是公共的。每一步都有它存在的理由——少一步就少一道防线。
5 条经得起考验的原则
1. 阶段划分:失败即停
jobs:
lint:
...
test:
needs: lint # lint 过了才跑 test
build:
needs: test
scan:
needs: build
deploy:
needs: scan
if: github.ref == 'refs/heads/main'
阶段间显式依赖——前面失败立刻停,节约时间和资源。
2. 缓存:能复用就复用
依赖装好的不变 → 缓存(npm / pip / cargo):
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm # 自动缓存 node_modules
镜像层缓存:
- uses: docker/build-push-action@v6
with:
cache-from: type=gha
cache-to: type=gha,mode=max
缓存不命中也要跑得过——缓存是优化,不是依赖。
3. 工件追溯:每次 build 唯一 tag
ghcr.io/me/webapp:1.4.2-abc1234 ← 版本号 + git SHA
用唯一 tag 而不是 :latest:
- 部署到 prod 的镜像可以精确回到当时的代码
- 滚回 = 重新 deploy 旧 tag,不需要重 build
- 故障排查时能问"这个 SHA 包含了哪些 commit"
CI 里通常打多个 tag:
docker tag webapp ghcr.io/me/webapp:${GIT_SHA}
docker tag webapp ghcr.io/me/webapp:${VERSION}
docker tag webapp ghcr.io/me/webapp:latest # 仅 main 分支
4. 拒绝在 CI 里做这些
- 跑生产数据迁移:CI 跑迁移 = 部署没做之前数据已经改了,回滚极难
- 把 secret 写日志:所有 CI 都自动 mask 已声明的 secret,但
echo $TOKEN还是危险 - 跑外部不可重复的副作用:
curl prod-api/cleanup这种,CI 失败会留半个状态 - 把 main 分支的部署放在没保护的 job 里:要门控
5. 加保护门
deploy-prod:
environment:
name: production # GitHub Environment:可加 required reviewers
needs: deploy-staging
if: github.ref == 'refs/heads/main'
GitHub / GitLab 的 Environment 功能:可加审批人、限制时段、记录部署历史。
几个常见反模式
| 反模式 | 该改成 |
|---|---|
| build 在 push 时跑、test 在 PR 时跑 | 都在 PR 跑,main 上只 build + deploy |
| CI 配置 200 行单文件 | 拆 reusable workflow / template |
| 测试 5 分钟、整条流水线 30 分钟 | profile 一遍,瓶颈通常在装依赖 |
| main 部署需要 1 个人手点 5 次 | 自动到 staging,prod 可加单次审批 |
| 缓存把 lockfile 都缓存了 | 缓存 key 一定要含 lockfile 哈希 |
DORA 视角的衡量
DORA 用 4 个指标看 CI/CD 健康度(不要把数字当 KPI 折磨自己,当方向用):
- 部署频率(Deployment Frequency)
- 变更前置时间(Lead Time for Changes:commit → 上线)
- 变更失败率(Change Failure Rate)
- 服务恢复时间(Time to Restore Service)
高表现团队这 4 项都好。只看部署频率会被骗——没测试没监控的高频部署就是定时炸弹。
推荐阅读
- Continuous Delivery (Jez Humble) — 持续交付概念出处
- DORA: Capabilities — 24 个能力维度
- Google SRE Workbook: Canarying Releases — 渐进发布的工程方法
- GitHub Actions Best Practices — 安全侧的硬约束
- The Twelve-Factor App: Build, Release, Run — 三段式分离的源头
下一篇:具体工具怎么选——Actions / GitLab CI / Jenkins / Tekton。