GitLab Merge Trains:把排队中的合并请求一起验证

两个合并请求单独测试成功,并不保证一起合入后仍然成功。如果 A 和 B 都只与目标分支组合测试,它们之间的冲突可能直到合并后才显现。GitLab 的 Merge Trains(合并列车)把排在前面的合并请求也纳入测试,按队列顺序合并通过检查的变更。

该功能面向 Premium 和 Ultimate,适用于 GitLab.com、GitLab Self-Managed 和 GitLab Dedicated。以下选项以当前官方文档为准;部署版本、管理员设置和项目权限会影响可用性。

原文特别列举三种适合使用列车的项目情形:经常向默认分支合并变更、同时有多个合并请求准备就绪,以及要求默认分支的流水线持续保持成功。

第一张示意图描述普通独立测试:A、B 都通过,二者合入后目标分支仍可能损坏。图中的英文标签保留官方源代码,含义如上。

%%{init: { "fontFamily": "GitLab Sans" }}%%
graph LR
accTitle: Two merge requests that pass individually but conflict together
accDescr: Merge request A and merge request B each pass a pipeline that tests their changes combined with the target branch alone. When both merge, the combined changes break the target branch.

  subgraph Without merge trains
    target[Target branch] --> pipeline_a[Pipeline for A: passes]
    target --> pipeline_b[Pipeline for B: passes]
    pipeline_a --> merge_both[Both merge]
    pipeline_b --> merge_both
    merge_both -.-> broken[Target branch breaks]
  end

合并列车如何工作

Merged results pipeline 测试的是“目标分支与一个合并请求”的临时组合。合并列车进一步包含列车中排在该请求前面的变更;只有对应流水线通过,且前面的请求已合并,当前请求才会合入。

例如,目标分支上依次加入 A、B、C:

  • A 的流水线测试目标分支加 A。
  • B 的流水线测试目标分支加 A 加 B。
  • C 的流水线测试目标分支加 A 加 B 加 C。

这些流水线并行执行,合并仍按顺序进行。如果 A 的流水线成功,A 合入目标分支,B 成为队首;B 成功后再合并 B,之后轮到 C。并行测试缩短等待,却不会让后面的请求越过前面的请求合并。

每个临时 merged-result commit 的作者是发起合并的用户。这是用于验证组合变更的内部提交,不应把它误认为原始源分支提交的作者信息。

%%{init: { "fontFamily": "GitLab Sans" }}%%
graph LR
accTitle: Merge train pipelines test combined changes
accDescr: Pipeline 1 tests merge request A against the target branch. Pipeline 2 tests merge request A and B together against the target branch. Pipeline 3 tests merge request A, B, and C together against the target branch. The three pipelines run in parallel.

  subgraph Merge train
    target[Target branch] --> pipeline_1[Pipeline 1: A]
    target --> pipeline_2[Pipeline 2: A + B]
    target --> pipeline_3[Pipeline 3: A + B + C]
  end

如果 B 失败,GitLab 将 B 移出列车,并为 C 创建不含 B 的新流水线。旧的 C 流水线测试的组合已失效,会被取消;A 的测试组合不受影响,可以继续。失败的 B 修复后可以重新加入列车。

自动取消过时流水线

当某个合并请求的列车流水线失败、用户跳过列车立即合并,或用户移除列车中的请求时,后续请求需要重新测试新的组合。GitLab 取消不再有效的流水线,并在需要时重建后续请求的流水线。

不要将取消解释为代码一定存在错误:被取消的流水线可能只是针对一个已经不再准备合并的组合。排查时先看队列变化和系统备注,再看测试失败日志。

在项目中启用

启用前需要满足四项条件:你至少具有项目 Maintainer 角色;项目使用 GitLab 原生仓库;已配置合并请求流水线;已启用 merged results pipelines。

进入 Settings → Merge requests → Merge options,启用 merged results pipelines,然后启用 merge trains,保存修改。只配置普通分支流水线不能替代合并请求流水线;可参照合并请求流水线文档检查配置。

启动合并列车

操作者需要对目标分支具有相应合并或推送权限。打开准备合并的请求:如果当前没有运行中的流水线,选择 Merge;如果流水线仍在运行,选择 Set to auto-merge。满足条件后,请求进入合并列车。第一个请求建立队列,后续请求加入同一目标分支的列车。

合并请求页面会显示列车状态和所在位置,例如“2 of 3”表示当前请求在三项队列中排第二。状态提示可以链接到列车详情。

查看合并列车

列车详情页从 GitLab 17.3 起提供。进入 Code → Merge requests → Merge trains,可以按目标分支筛选,也可以从合并请求的流水线组件、系统备注或流水线详情页进入。

详情页既展示当前列车中的请求,也展示曾通过列车而已经合并的请求及相关流水线;具备相应权限时,可以从该页移除当前请求。检查“当前列车顺序”和“实际测试的组合”,比只看单个请求的绿色状态更能说明它是否准备好合并。

向现有列车加入请求

使用自动合并将请求加入已有队列。这个操作在 17.2 以功能标志引入,17.4 默认启用,17.7 正式可用并移除了该标志。仍按页面状态选择 Merge 或 Set to auto-merge,之后查看请求的队列位置。

默认情况下,每条列车最多同时运行 20 条流水线。队列可以继续接收更多合并请求;超过并行容量的请求先等待,有空位时再启动流水线。较新版本允许项目调整并行限制,见下文。

请求加入列车后,新出现的讨论线程不会自动将它移出列车,也不会阻止该次合并,即便项目启用了“所有讨论必须解决”。这是官方文档列出的限制,相关问题见 GitLab issue 220916。因此,评审人员应在入列车前完成必要讨论,并按团队流程处理入列车后的意见。

从列车移除请求

在合并请求页面取消自动合并,或在列车详情页选择移除,都会把该请求移出列车。其后的请求不再包含它,需要重新启动流水线;旧组合的流水线会被取消。被移除的请求之后仍可重新加入。

这一操作会增加后续测试开销。移除前应区分真实失败、过时流水线和需要重新排队的变更。

紧急请求:跳过列车立即合并

紧急修复可以跳过队列立即合并,但会使其他请求的测试组合发生变化。GitLab 取消其他列车流水线,并基于包含紧急修复的新目标分支重新创建它们。这样会消耗额外 CI 时间,也会延后原队列中的请求。

使用 fast-forward 合并时,如果源分支落后于目标分支,这个选项可能不可用,见相关限制。

立即合并但不重启列车流水线

GitLab 另有 Merge immediately without restarting the merge train 实验功能。它在 16.5 以 merge_trains_skip_train 功能标志引入,16.10 作为实验功能启用。官方文档将其列为实验功能,未来可能调整或移除。GitLab.com 和 Dedicated 提供该功能;Self-Managed 默认可用,但管理员可以通过功能标志隐藏它。

该方式不会把立即合并的请求与列车中的其他请求一起测试,也不会重启已有列车流水线。其他流水线即使成功,包含所有变更的目标分支仍有可能失败。它不适用于 fast-forward 或 semi-linear 合并,见 issue 429009。

至少具有 Maintainer 角色且已启用列车时,在 Settings → Merge requests → Merge options 中启用 merged results pipelines、merge trains 和 Merge immediately without restarting the merge train,再保存。

通过合并请求 API合并时设置 skip_merge_train=true。现有列车流水线不会因此取消或重启。这个参数表示特定实验行为,不能当作所有版本通用的紧急合并参数。

调整并行流水线数量

项目级并行限制从 GitLab 19.0 起提供。默认值为 20,最小值为 1;设置为 1 时,列车流水线依次执行。

进入 Settings → Merge requests → Merge options,修改 Maximum parallel pipelines per merge train 并保存。项目值不能超过实例级上限。也可以通过 Projects API 或 GraphQL API调整,具体字段以所用版本文档为准。

较高并行数可以提早验证队列后方的组合,但会增加资源占用;较低值减少同时运行的任务,却可能延长等待。不能仅凭默认数值推断某个项目的最优设置。

强制通过合并列车

强制列车在 19.2 以 merge_train_enforcement 功能标志引入,19.3 正式可用并移除标志。默认仍允许绕过。开启强制模式后,界面隐藏立即合并以及“立即合并而不重启列车”的入口;REST 和 GraphQL 直接合并调用也会拒绝绕过,自动合并则将请求送入列车。

可选择的级别为:

  • Allow bypass:允许绕过列车。
  • Enforce for all users:对所有人强制,包括 Owner 和管理员。
  • Enforce with Owner override:强制使用列车,但 Owner 和管理员可对单个请求例外处理。

至少具有 Maintainer 角色且已启用列车时,进入 Settings → Merge requests → Merge options,选择强制级别并保存。旧版本可能没有此设置,不能通过隐藏页面元素替代服务器端强制规则。

排查请求被移出列车

流水线失败、请求被改为 Draft、请求关闭、源分支更新、冲突、不能与前序请求组合、超时或内部异常,都可能导致请求离开列车。

先在合并请求 Overview 的活动记录中找“某用户从合并列车移除了此请求”一类系统备注,读取随附原因。官方列出的常见情况如下:

系统备注或现象 含义与处理
合并未完成,请求不可合并;附有 Explanation: pipeline must succeed Explanation 后的内容才是具体原因。检查流水线及请求的实际合并条件,修复后重新入列车。
无法为 source_sha 与 target_sha 创建合并提交 通常存在合并冲突。重新变基或解决冲突后再加入。
冲突文件列表 备注最多列出 10 个文件,超过时另列数量。处理全部冲突,而非只处理展示的文件。
意外错误并附 Correlation ID 保留该 ID,交由实例管理员或支持人员排查;之后再尝试入列车。
合并长时间未完成 可能有卡住或失败的后台任务。重新入列车;持续出现时联系管理员。

无法使用自动合并

项目启用了合并列车时,自动合并不会绕过列车。旧名称 Merge when pipeline succeeds 也遵守这一行为,见 issue 12267。

无法重试列车流水线

请求因失败被移出后,旧流水线针对的临时合并提交已经过时,不能简单重试整条列车流水线。应把请求重新加入列车,让 GitLab 创建新的组合和流水线。

对于间歇性作业失败,可配置作业的 retry。如果重试在流水线最终失败之前成功,请求便不会因这次临时失败被移出。

无法把请求加入列车

如果启用了 Pipelines must succeed,最近一次流水线失败时,Merge 或 Set to auto-merge 可能不可用。可以重试失败作业并确保全部成功,使用 Run pipeline 重新运行流水线,或推送修复提交触发新流水线。不要仅重试一个与当前源分支无关的旧测试来满足条件。

自动化工具返回 405

开启强制列车后,自动化工具通过合并 API 直接合并,而没有设置 auto_merge=true,可能收到 405 Method Not Allowed。将调用改为自动合并,让请求按规则进入列车。使用 Renovate 时可检查 platformAutomerge 配置;实际参数和可用版本仍应以工具与 GitLab 文档为准。

实施前的检查

先确认项目实际 GitLab 版本与上述功能引入版本对应,再检查合并请求流水线、merged results pipelines 和目标分支权限。用非生产分支上的多个小请求观察队列次序、组合提交、失败移除与重建行为。本文没有执行项目设置、合并请求或 API 调用,也没有实测 CI 吞吐量。


来源:GitLab 官方文档:Merge trains,GitLab 文档贡献者,© 2011–present GitLab Inc.。中文整理覆盖原文各功能及排障章节,保留两段官方 Mermaid 图代码,补充版本核对提示。文档目录依官方仓库许可采用 CC BY-SA 4.0,本文改编亦按该许可提供;分享改编须保留署名、许可链接和修改说明,并遵守相同方式共享条款。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容