4. 流水线未触发或未创建

在 GitLab CI/CD 中,最令人困惑的故障之一不是流水线失败,而是流水线根本没有被创建。提交代码后,Pipelines 页面空空如也,或者只显示“No pipeline”,既没有报错日志,也没有可重试的作业。这类问题的根源几乎都集中在“触发条件”这一层:GitLab 在创建流水线之前,会先判断当前事件是否满足 .gitlab-ci.yml 中定义的各种规则。只要规则判定为“不创建”,就不会有任何流水线记录,自然也无从调试。

要系统排查,需要理解 GitLab 决定是否创建流水线的判断顺序。它大致遵循这样一条链路:先看是否存在可用的 CI 配置,再看 workflow:rules 是否允许该事件创建流水线,然后针对每个作业评估 rules 或 only/except,最后还要确认事件类型本身是否属于会触发流水线的事件。下面这张图展示了从代码事件到流水线创建之间的判断链路,以及各环节“被拦截”时的典型表现。

流水线创建判断链路与拦截点 代码事件发生 push / MR / tag / schedule ① 存在 .gitlab-ci.yml? 含 include 解析成功 ② workflow:rules 允许? 全局闸门,最先拦截 无配置 / YAML 语法错误 表现:无流水线,CI Lint 报错 workflow 判定为 never 表现:整条流水线不创建 ③ 逐作业评估 rules / only / except 决定每个 job 是否加入流水线 ④ 事件类型是否触发流水线 MR 事件需源分支有 CI 配置 流水线创建成功 至少一个 job 被纳入 所有 job 均被规则排除 表现:无流水线或空流水线 事件不触发流水线 如 MR 源分支无配置 排查顺序:CI Lint 校验配置 → 检查 workflow:rules → 用 rules 模拟器验证条件 → 确认事件类型与源分支 关键原则:rules 与 only/except 不可在同一作业混用,否则配置无效

一、先确认配置本身是否可用

流水线未创建时,第一步不是怀疑规则,而是确认 GitLab 是否成功解析了 CI 配置。进入项目的 CI/CD → Editor(CI Lint),粘贴当前分支的 .gitlab-ci.yml 内容进行校验。如果存在 YAML 缩进错误、include 指向的文件不存在、或引用了未定义的变量,GitLab 会直接判定“无有效配置”,此时任何事件都不会创建流水线。常见错误包括:include:local 路径写错、extends 的模板名拼写错误、以及 rules 与 only 同时出现在一个作业中导致配置非法。

需要特别注意的是,rules 和 only/except 是互斥的。如果某个作业同时写了 rules 和 only,GitLab 会报配置错误,整个流水线无法创建。排查时可以用下面的命令在本地快速检查是否存在混用:

# 在仓库根目录检查是否存在 rules 与 only/except 混用
grep -nE "^\s*(rules|only|except):" .gitlab-ci.yml

# 若同一 job 下同时出现 rules 和 only,即为冲突
# 正确做法:统一使用 rules,删除 only/except

二、workflow:rules 是全局总闸门

workflow:rules 决定“哪些事件可以创建流水线”,它比作业级规则更早生效。如果 workflow 中没有匹配当前事件的 when: always 或 when: never 分支,GitLab 默认允许创建;但一旦显式写了 when: never 且命中,整条流水线就不会出现。典型误配如下:

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: always
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: always
    - when: never   # 其他所有情况都不创建流水线

这段配置意味着:只有合并请求事件和 main 分支推送会创建流水线。如果你在 dev 分支推送代码,即使作业规则允许,流水线也不会出现。排查时应先打印当前事件类型,确认 CI_PIPELINE_SOURCE 的实际取值,再对照 workflow 分支逐一比对。

三、合并请求事件的特殊性

合并请求(MR)事件不创建流水线,最常见的原因是源分支上不存在 .gitlab-ci.yml,或者 MR 的源分支与目标分支配置不一致。GitLab 在 MR 事件中默认使用“合并后的结果”或“源分支”的配置,具体取决于项目设置中的 Merge request pipelines 选项。如果源分支没有 CI 配置,MR 流水线就不会创建。此外,如果 MR 是从 fork 发起的,且项目未开启“允许来自 fork 的合并请求流水线”,同样不会触发。

另一个高频陷阱是 rules 中使用了 $CI_MERGE_REQUEST_ID 等变量,但该变量只在 MR 事件中存在。若在普通 push 事件中引用它,条件恒为假,作业被排除。正确写法是显式区分事件:

build:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: on_success
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: on_success
    - when: never

四、only/except 与 rules 的冲突排查

老项目常使用 only/except,新项目推荐 rules。两者语义不同:only 是白名单,except 是黑名单,且不支持复杂条件组合;rules 支持 if、changes、exists 和 when,表达力更强。当同一作业混用时,GitLab 会直接拒绝该配置。排查清单如下:

  • 检查每个 job 是否同时出现 rules 与 only/except,有则删除旧写法。
  • 检查 rules 中是否存在多个 when: never 且全部命中,导致作业被完全排除。
  • 检查 changes 规则是否因文件路径不匹配而恒为假,例如只监听 src/** 但本次提交只改了 README.md。
  • 检查 exists 规则指向的文件是否真的存在于当前分支。
  • 使用 GitLab 的 CI/CD → Pipeline editor → Validate 和 Simulate pipeline 功能,输入事件类型和分支,观察每个作业的判定结果。
排查流水线未创建时,优先使用 CI Lint 的“模拟流水线”功能。它可以指定 CI_PIPELINE_SOURCE、分支名和变量,直接显示每个作业是否被纳入,比反复推送代码高效得多。

五、一个可复用的排查决策表

把上述判断整理成一张决策表,可以在实际排障时逐行核对,避免遗漏。表中“现象”指 Pipelines 页面的表现,“优先检查”指最可能的原因。

现象 优先检查 典型修复
完全无流水线记录 workflow:rules 是否命中 when: never 补充匹配当前事件的分支,或删除兜底 never
MR 页面无流水线 源分支是否有 CI 配置、MR pipelines 是否开启 在源分支添加配置,开启 MR pipeline 选项
push 后无流水线 作业 rules 是否全部排除、changes 路径是否匹配 调整 if 条件或 changes 路径
CI Lint 报配置错误 rules 与 only/except 是否混用 统一改为 rules,删除 only/except
流水线存在但无作业 所有 job 的 rules 是否都判定为 never 至少保留一个无条件或匹配当前事件的 job

最后需要强调一个原则:流水线未创建不是运行时错误,而是配置判定结果。它不会出现在作业日志里,只能通过规则模拟和事件变量比对来定位。养成在修改 rules 或 workflow 后立即用 CI Lint 模拟验证的习惯,可以避免绝大多数“提交了却没反应”的问题。当规则复杂时,建议在作业中临时加入 echo $CI_PIPELINE_SOURCE 和 echo $CI_COMMIT_BRANCH,先确认事件上下文,再回头审视规则条件,往往能快速锁定被拦截的那一环。