阶段是干什么的
流水线阶段(Stages)把交付过程拆成构建、测试、打包、部署等有序环节:默认阶段之间串行,前一阶段全部成功才进入下一阶段;阶段内部作业并行。它同时表达两层含义:流程约束(先测后发、先打包再部署)与时长结构(串行段构成关键路径,决定整体反馈时间)。GitLab CI 用 stages 关键字显式声明,未声明时按 build、test、deploy 兜底;GitHub Actions 没有阶段概念,用 jobs 之间的 needs 组成有向无环图;Jenkins 用 stage 块表达同类语义。阶段划分的颗粒度是设计取舍:拆得太粗起不到门禁作用,拆得太细每次多一轮全量等待。判断一个阶段该不该独立,看它是否代表一个清晰的通过标准:有明确通过标准的检查值得独立成阶段,例如测试通过、镜像产出、部署完成。
基本信息
| 典型顺序 | checkout → build → test → package → deploy |
|---|---|
| 执行语义 | 前一阶段成功才进入下一阶段(allow_failure 的作业除外) |
| 并行规则 | 同阶段作业默认并行,跨阶段默认等待前一阶段整体完成 |
| 常见命名 | build / test / package / deploy / release |
| 平台差异 | GitLab 显式 stages;GitHub Actions 用 needs 组 DAG;Jenkins 用 stage 块 |
| 默认兜底 | GitLab 未声明 stages 时使用 build、test、deploy 三个阶段 |
典型使用场景
- 需要硬顺序的场景:测试不过禁止打包,把 test 放在 package 前,失败即止不浪费后续算力。
- 独立检查并行:同阶段内 lint、单测、安全扫描同时执行,减少等待。
- 多团队共库:按职责命名阶段,流水线图上直接看出卡在哪一环,便于定位责任。
- 渐进提速:先统计各阶段耗时,再用 needs 换成 DAG 压缩关键路径。
- 发布治理:deploy 阶段配手动门与审批,把何时上生产从脚本搬到流程里。
- 多环境晋级:阶段与环境名结合,形成 test 到 staging 再到 prod 的晋级链。
- 审计与度量:按阶段统计耗时与失败率,找出拖慢反馈或最常失败的门禁环节。
- 成本控制:把全量回归、压测这类昂贵检查从每次提交剥离到主干或定时阶段。
最小结构 GitLab
最小结构 GitLab
stages: [build, test, deploy]
build-job:
stage: build
script: make build # 上传 artifacts 供后续阶段使用
lint-job:
stage: test
needs: [] # 无依赖,流水线开始即可跑
script: make lint
test-job:
stage: test
needs: [build-job] # 只等构建,不等整个阶段
script: make test最小结构 GitHub
最小结构 GitHub
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make build # 编译并上传制品
test:
needs: build # 作业级依赖即 DAG 边
runs-on: ubuntu-latest
steps: [{run: make test}]阶段划分示例
| 阶段 | 典型作业 | 门禁意义 |
|---|---|---|
| build | 编译、装依赖 | 拦语法与依赖错误 |
| test | 单测、静态检查 | 拦逻辑回归 |
| package | 打包、推镜像 | 产出唯一制品 |
| deploy | 部署到环境 | 控发布时机 |
| release | 打标签、发公告 | 留发布记录 |
阶段多而作业少时整体偏串行;用 DAG(needs)或并行作业压缩关键路径。阶段不是越多越好:每增一个阶段意味着一次全量等待。
阶段间传递验证过的同一份制品,别在下游阶段重新构建:重编会让测试结论与发布内容错位。
GitHub Actions 中未声明 needs 的作业全部并行启动;要顺序只能靠 needs 显式声明,不存在 GitLab 式的隐式阶段串行。重跑单个失败作业时,它使用的仍是本次运行中上游已产出的制品,若要完整复验应重跑整条流水线。