1. 为什么要“收束触发”?
每次 push 都跑全套集成,就像每踩一脚油门都拉满十二节车厢:短期看似省事,长期会拖垮队列、放大噪声、让“红构建”被习惯性忽略。 专业做法是把触发拆成三层:是否创建 pipeline(workflow)、哪些 job 进入 DAG(job rules)、 哪些路径变更才值得跑重任务(changes 等)。三者叠加,才能把分钟数与心智成本花在刀刃上。
2. rules:现代默认,可读又可组合
rules 是一个有序列表:从上到下匹配,命中第一条即停止。每条可含 if、changes、exists 等条件,并用 when 指定 on_success、manual、delayed、never 等。 与旧式 only/except 相比,rules 更容易表达“MR 上自动跑、主分支上手动批准”这类分支组合逻辑。
mr_checks:
stage: test
script:
- npm ci
- npm test
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy_prod:
stage: deploy
script:
- ./deploy.sh production
rules:
- if: $CI_COMMIT_TAG
when: manual
3. workflow: rules:挡在 DAG 之前的闸机
放在顶层 workflow: 下的 rules 决定是否创建 pipeline。 典型用途:只允许 main、MR、或带 tag 的提交创建流水线;其它情况直接不生成 pipeline,连“空跑”都不出现。
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG
- when: never
最后一条 when: never 作为兜底拒绝:上面都不匹配时,GitLab 不会创建 pipeline(文档中常称 “skip pipeline creation”)。 这与 job 级 rules: - when: never 的语义层级不同:一个管“有没有 pipeline”,一个管“图里有没有该 job”。
4. Merge Request pipeline:不是“多跑一遍”,而是“换语境”
当 CI_PIPELINE_SOURCE 为 merge_request_event 时,GitLab 为 MR 创建专用流水线。 你会看到与“普通分支 push”不同的变量(如 CI_MERGE_REQUEST_IID、CI_MERGE_REQUEST_TARGET_BRANCH_NAME), 并可用 only: - merge_requests 或等价的 rules 把代码评审与合并门禁绑在一起。 MR pipeline 让你能在合并前验证“合进去之后会不会炸”,而不是只验证源分支孤立状态。
5. rules:changes:按路径过滤重任务
对集成测试、镜像构建、文档站发布等“昂贵 job”,可用 changes 限制:仅当某些 glob 变更时才自动运行,否则 when: never 或交给 manual。 注意 changes 在部分 pipeline 类型(如某些 schedule / push 组合)行为会受文档约束,上线前用真实 MR 验证。
heavy_e2e:
stage: test
script:
- npm run e2e
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- src/**/*
- package.json
- when: never
6. only / except:遗产语法,建议迁移
仍能在老仓库见到 only: - branches、except: - main。 官方长期推荐迁移到 rules:表达能力更强,语义更接近“条件列表”,也减少与 workflow 组合时的意外。 读旧 YAML 时记住:only/except 与 rules 不要混在同一 job 上(应统一风格)。
| 维度 | only / except | rules |
|---|---|---|
| 匹配模型 | 黑白名单分支/标签/MR | 有序 if + when,可组合变量 |
| 手动/延迟 | 需额外关键字配合 | 同一结构内 when: manual |
| 维护性 | 复杂场景易绕 | 适合平台统一模板 |
7. 常用 CI_PIPELINE_SOURCE 心智表
规则条件里最常引用的是 $CI_PIPELINE_SOURCE(以及分支名、tag、MR 变量)。下面是一张简表,便于写 if 时快速对齐。
| Source (示例) | 典型场景 |
|---|---|
| push | 分支或 tag 推送 |
| merge_request_event | MR 创建/更新触发的 MR pipeline |
| schedule | 定时流水线 |
| web | UI 手动 “Run pipeline” |
| api / trigger | 外部系统或 pipeline 触发 |
8. 与 GitHub Actions 的对照(触发维度)
Actions 用 on: 绑定事件;GitLab 用 workflow + rules + 内置变量表达相近意图。 概念上可把 workflow:rules 类比为“是否启动 workflow”,把 job rules 类比为 job 级 if:(GitHub 也在 job 层支持条件)。
9. 本章清单
- 为仓库加顶层 workflow:rules,拒绝无关分支的 pipeline 创建。
- 把所有 only/except 逐步迁移到 rules,统一团队模板。
- 区分 MR pipeline 与 push pipeline,合并门禁绑定 merge_request_event。
- 对昂贵 job 使用 changes 或 manual,并监控 Runner 使用曲线。
- 梳理 fork / 外部贡献场景下的流水线信任模型与变量暴露面。