4. 流水线触发机制
流水线不是“建好就会自己跑”的静态对象,它需要被某个事件唤醒。GitLab CI/CD 的触发机制决定了“谁在什么条件下启动哪条流水线、携带哪些变量、在哪个分支或标签上运行”。理解触发机制,才能把测试与发布从手工点击变成可预期、可追溯的自动化行为。本节先梳理六种常用触发方式,再进入多项目触发与父子流水线的组合场景。
一、六种触发方式及其适用边界
push 触发是最基础的机制:向仓库推送提交(包括分支推送、标签推送)时,GitLab 自动为包含 .gitlab-ci.yml 的项目创建流水线。它适合日常开发分支的快速反馈,但缺点是任何一次推送都会触发,容易在频繁提交时产生大量流水线。实践中常用 rules 限制分支,例如只在 main、develop 或 release/* 上运行完整流水线,其余分支只跑单元测试。
merge request 触发(合并请求事件)是代码评审阶段的核心。当 MR 被创建、更新(新提交推入源分支)、重新打开时,GitLab 会为源分支创建一条“合并请求流水线”。它的价值在于:在代码合入目标分支之前,用目标分支的上下文验证合并结果。需要注意 rules:if 中常用的变量:$CI_PIPELINE_SOURCE == "merge_request_event",以及 $CI_MERGE_REQUEST_TARGET_BRANCH_NAME、$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME。若同时存在分支流水线和 MR 流水线,可能对同一提交重复运行,通常用 workflow:rules 做互斥,避免“双跑”。
schedule 触发(计划流水线)由时间驱动,适合夜间回归、每日构建、定时安全扫描、依赖更新检查等。在项目 Build → Pipeline schedules 中配置 Cron 表达式、目标分支和时区,并可传入变量。例如每天 02:00 跑全量回归:0 2 * * *。计划流水线的 $CI_PIPELINE_SOURCE 为 schedule,因此可以在 rules 中只让耗时任务在计划流水线中执行。
web trigger 触发指在 GitLab 界面 Build → Pipelines → Run pipeline 手动创建流水线,可选择分支/标签并填写变量。它适合发布前的手工确认、临时验证某个分支、或需要人工输入版本号的场景。手动触发不是“随意点击”,而应配合受保护变量和审批,避免误发生产。
pipeline trigger 触发(触发器令牌)用于从外部系统调用 GitLab 的 trigger API。在 Settings → CI/CD → Pipeline triggers 添加触发器后会得到 token,外部系统用如下方式调用:
curl -X POST \
-F token=TRIGGER_TOKEN \
-F ref=main \
-F "variables[ENV]=staging" \
https://gitlab.example.com/api/v4/projects/123/trigger/pipeline
它适合 Jenkins、监控告警、制品库等外部系统“通知 GitLab 跑流水线”。$CI_PIPELINE_SOURCE 为 trigger。
API 触发范围更广:通过 POST /projects/:id/pipeline 直接创建流水线,可指定 ref 和变量数组,使用个人访问令牌或项目访问令牌鉴权。与 trigger token 相比,API 触发更灵活,可查询、重试、取消流水线,适合平台化调度。
二、用 workflow:rules 统一分流
六种触发方式如果各自为政,很容易出现“同一提交跑两条流水线”或“MR 流水线缺失”。推荐在 .gitlab-ci.yml 顶部用 workflow:rules 做全局分流:
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_PIPELINE_SOURCE == "schedule"'
- if: '$CI_PIPELINE_SOURCE == "web"'
- if: '$CI_PIPELINE_SOURCE == "trigger"'
- if: '$CI_PIPELINE_SOURCE == "api"'
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_TAG'
这段规则的含义是:MR、计划、手动、外部触发、API 一律允许;普通分支推送只允许 main;标签推送允许。其余分支推送不会创建流水线,从而把资源集中在关键路径上。注意 workflow:rules 只决定“是否创建流水线”,具体作业是否执行仍由各 job 的 rules 决定,两者要配合使用。
三、多项目触发:trigger 关键字
当项目 A 的流水线需要启动项目 B 的流水线时,使用 trigger 关键字。它有两种写法:
# 写法一:跨项目触发
notify-downstream:
stage: deploy
trigger:
project: group/service-b
branch: main
strategy: depend
# 写法二:同项目多配置
run-other-config:
trigger:
include: path/to/other/.gitlab-ci.yml
strategy: depend
strategy: depend 表示上游作业会等待下游流水线结束,并把下游结果作为自身状态;不写则上游触发后立即成功,适合“通知即走”的场景。跨项目触发要求触发方有权限访问目标项目,且目标项目允许被触发。变量可通过 variables 传递,例如把当前版本号 $CI_COMMIT_TAG 传给下游。
四、父子流水线:把大流水线拆成可复用单元
父子流水线(parent-child pipeline)是同一项目内的分层结构:父流水线通过 trigger:include 生成子流水线,子流水线拥有独立的作业图。它解决三个问题:一是把单体 .gitlab-ci.yml 拆成多个小文件,按模块维护;二是子流水线可动态生成(用 artifact 传递生成的 YAML);三是子流水线的作业并行度更高,不受父流水线阶段串行限制。
stages: [build, test, deploy]
build:
stage: build
script: ["./build.sh"]
test-backend:
stage: test
trigger:
include: ci/backend.yml
strategy: depend
test-frontend:
stage: test
trigger:
include: ci/frontend.yml
strategy: depend
deploy:
stage: deploy
script: ["./deploy.sh"]
needs: ["test-backend", "test-frontend"]
父流水线中 test-backend 与 test-frontend 会各自生成一条子流水线并并行执行,deploy 通过 needs 等待两者完成。判断结果时,父流水线页面会显示每个子流水线的状态;若子流水线失败,父作业也失败,从而阻断部署。需要特别注意的是:子流水线中的 rules 独立生效,父流水线的 workflow:rules 不会自动继承,因此子配置里要自行声明触发条件。
五、排障要点
- MR 流水线不出现:检查
workflow:rules是否把merge_request_event排除,或项目设置中是否关闭了“合并请求流水线”。 - 同一提交跑两次:通常是分支流水线与 MR 流水线同时命中,用
workflow:rules互斥。 - trigger token 调用返回 401/403:确认 token 未过期、
ref存在、调用方有权限。 - 子流水线不执行:检查
include路径是否正确、子 YAML 是否合法、子流水线的rules是否命中当前CI_PIPELINE_SOURCE。
掌握这些触发方式后,流水线就从“被动响应推送”升级为“按业务节奏被精确唤醒”,为后续的测试编排与发布策略打下基础。