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 触发更灵活,可查询、重试、取消流水线,适合平台化调度。

流水线触发源 → 事件 → 流水线类型 push 推送 分支 / 标签提交 merge request 创建 / 更新 / 重开 schedule 计划 Cron 定时 web trigger 界面手动运行 pipeline trigger 触发器令牌 API 触发 REST 创建流水线 CI_PIPELINE_SOURCE = push CI_PIPELINE_SOURCE = merge_request_event CI_PIPELINE_SOURCE = schedule CI_PIPELINE_SOURCE = web CI_PIPELINE_SOURCE = trigger CI_PIPELINE_SOURCE = api 分支流水线 快速反馈,rules 限制分支 合并请求流水线 目标分支上下文验证合并结果 计划流水线 夜间回归 / 安全扫描 手动流水线 发布确认 / 临时验证 外部触发流水线 Jenkins / 监控 / 制品库通知 平台调度流水线 API 创建、查询、重试、取消 用 workflow:rules 与 rules:if 按 CI_PIPELINE_SOURCE 分流,避免同一提交重复运行

二、用 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 不会自动继承,因此子配置里要自行声明触发条件。

实践建议:把“触发方式”与“流水线职责”对齐——push 跑快速检查,MR 跑合并验证,schedule 跑全量回归,web/trigger/API 跑发布与外部联动。多项目触发用于服务间依赖,父子流水线用于单项目内模块拆分,两者不要混用成难以追踪的网状结构。

五、排障要点

  • MR 流水线不出现:检查 workflow:rules 是否把 merge_request_event 排除,或项目设置中是否关闭了“合并请求流水线”。
  • 同一提交跑两次:通常是分支流水线与 MR 流水线同时命中,用 workflow:rules 互斥。
  • trigger token 调用返回 401/403:确认 token 未过期、ref 存在、调用方有权限。
  • 子流水线不执行:检查 include 路径是否正确、子 YAML 是否合法、子流水线的 rules 是否命中当前 CI_PIPELINE_SOURCE。

掌握这些触发方式后,流水线就从“被动响应推送”升级为“按业务节奏被精确唤醒”,为后续的测试编排与发布策略打下基础。