Help us learn about your current experience with the documentation. Take the survey.

GitLab 项目的流水线

gitlab-org/gitlab 项目(以及 dev 实例)的流水线配置在通常的 .gitlab-ci.yml 中,该文件本身包含 .gitlab/ci/ 下的文件以方便维护。

我们正努力尽可能多地“自用”(dogfood)GitLab 的 CI/CD 功能和最佳实践

不要在 gitlab-org/gitlab 的流水线中使用 CI/CD 组件,除非它们在 dev.gitlab.com 实例上被镜像。CI/CD 组件在不同实例间无法工作,若未存在于该实例上,会导致 dev.gitlab.com 镜像上的流水线失败(参考 导致流水线失败的案例)。

流水线层级

处于积极开发中:更多信息请参见 epic 58

合并请求通常会运行多个 CI/CD 流水线。根据合并请求在审批流程中的位置,我们会触发不同类型的流水线。我们将这类流水线称为 流水线层级

目前我们有三个层级:

  1. pipeline::tier-1:合并请求无审批
  2. pipeline::tier-2:合并请求至少有一个审批,但仍需更多审批
  3. pipeline::tier-3:合并请求已获得所有必需的审批

通常,流水线层级越低,流水线应越快;层级越高,流水线通过运行更多测试来提供更高置信度的能力应越强。

有关实现的更多信息,请参见 合并请求流水线中引入“层级” epic。

合并请求批准前的预测性测试作业

为降低流水线成本并缩短作业时长,在合并请求批准前,流水线将运行一组可能因合并请求变更而失败的 RSpec 和 Jest 测试。

合并请求获批后,流水线将包含完整的 RSpec 和 Jest 测试。这将确保在合并请求合并前所有测试均已运行。

GitLab 项目测试依赖关系概述

要理解预测性测试作业如何执行,需了解 GitLab 代码(前端和后端)与对应测试(Jest 和 RSpec)之间的依赖关系。这种依赖可通过以下图表可视化:

flowchart LR
    subgraph frontend
    fe["前端代码"]--由-->jest
    end
    subgraph backend
    be["后端代码"]--由-->rspec
    end

    be--生成-->fixtures["前端 fixture"]
    fixtures--用于-->jest

总结来说:

  • RSpec 测试依赖于后端代码。
  • Jest 测试同时依赖于前端和后端代码(后者通过前端 fixture)。

预测性测试仪表板

detect-tests CI 作业

大多数 gitlab-org/gitlab 的 CI/CD 流水线会在 prepare 阶段运行一个 detect-tests CI 作业,以检测给定 MR 变更的文件为基础,确定应运行哪些后端/前端测试。

detect-tests 作业会创建许多文件,其中包含应运行的测试。这些文件将在流水线的后续作业中被读取,仅执行这些测试。

RSpec 预测性作业

确定合并请求中的预测性 RSpec 测试文件

为识别合并请求中可能失败的 RSpec 测试,我们使用 动态映射静态映射

动态映射

首先,我们使用了 test_file_finder gem,其动态映射策略来自 Crystalball gem查看使用位置,以及我们在Crystalball中使用的映射策略)。

除了 test_file_finder 外,我们还添加了多个高级映射来检测更多需运行的测试:

静态映射

我们使用 test_file_finder gem,并通过 tests.yml 文件 维护静态映射,用于无法通过动态映射处理的特殊情况(查看使用位置)。

test映射 包含源文件到测试文件的映射表,具体取决于源文件。

特殊情况

此外,在以下几种情况下我们会始终运行完整的RSpec测试:

  • 当合并请求设置了 pipeline:run-all-rspec 标签时。此标签将触发所有RSpec测试,包括在 as-if-foss 作业中运行的测试。
  • 当合并请求设置了 pipeline:mr-approved 标签,且代码变更满足 backend-patterns 规则时。请注意,此标签由审核自动化在合并请求被任意审核人批准时分配,不建议手动应用此标签。
  • 当合并请求由自动化创建时(例如Gitaly更新或针对稳定分支的MR)
  • 当合并请求创建于安全镜像仓库中
  • 当任何CI配置文件被修改时(例如 .gitlab-ci.yml.gitlab/ci/**/*

您是否遇到过后端预测测试的问题?

如果是这样,请查看开发分析 RUNBOOK 关于预测测试,了解如何处理预测测试问题。此外,如果您发现了任何测试选择缺口,请告知 @gl-dx/development-analytics,以便我们采取必要步骤优化测试选择。

Jest 预测任务

确定合并请求中的预测性 Jest 测试文件

为了识别在合并请求中可能失败的 jest 测试,我们将所有更改文件的列表传递给 jest,使用 --findRelatedTests 选项。 在此模式下,jest 会解析与更改文件相关的所有依赖项,包括在依赖链中包含这些文件的测试文件。

异常情况

此外,在某些情况下我们会始终运行完整的 Jest 测试:

  • 当合并请求上设置了 pipeline:run-all-jest 标签时
  • 当合并请求由自动化创建时(例如 Gitaly 更新或针对稳定分支的 MR)
  • 当合并请求在安全镜像中创建时
  • 当相关 CI 配置文件被修改时(.gitlab/ci/rules.gitlab-ci.yml.gitlab/ci/frontend.gitlab-ci.yml
  • 当任何前端依赖文件被修改时(例如 package.jsonyarn.lockconfig/webpack.config.jsconfig/helpers/**/*.js
  • 当任何 vendor 的 JavaScript 文件被修改时(例如 vendor/assets/javascripts/**/*

完整 Jest 测试的 rules 定义位于 .frontend:rules:jest 中,详情见 rules.gitlab-ci.yml

您是否遇到过前端预测测试的问题?

如果是这样,请查看开发分析 RUNBOOK 关于预测测试,了解如何处理预测测试问题。

Fork 管道

对于 fork 管道,我们仅运行预测性的 RSpec 和 Jest 作业,除非 MR 上设置了 pipeline:run-all-rspec 标签。目标是减少 fork 管道消耗的计算配额。

详见实验问题

合并请求管道中的快速失败作业

为了在合并请求破坏现有测试时提供更快的反馈,我们实现了快速失败机制。

在合并请求管道中,会并行添加一个 rspec fail-fast 作业到所有其他 rspec 作业中。该作业运行与合并请求变更直接相关的测试。

如果这些测试中有任何一个失败,rspec fail-fast 作业会失败,触发 fail-pipeline-early 作业运行。fail-pipeline-early 作业会:

  • 取消当前正在运行的管道及所有进行中的作业。
  • 将管道状态设置为 failed

例如:

graph LR
    subgraph "准备阶段";
        A["detect-tests"]
    end

    subgraph "测试阶段";
        B["jest"];
        C["rspec migration"];
        D["rspec unit"];
        E["rspec integration"];
        F["rspec system"];
        G["rspec fail-fast"];
    end

    subgraph "测试后阶段";
        Z["fail-pipeline-early"];
    end

    A --"工件:测试文件列表"--> G
    G --"失败时"--> Z

如果与合并请求相关的测试文件超过 10 个,rspec fail-fast 将不会执行操作。这可以防止 rspec fail-fast 的持续时间超过平均 rspec 作业时长,从而违背其初衷。

此数字可通过设置名为 RSPEC_FAIL_FAST_TEST_FILE_COUNT_THRESHOLD 的 CI/CD 变量来覆盖。

在合并请求管道中重新运行之前失败的测试

为了缩短解决合并请求失败测试后的反馈时间,rspec rspec-pg16-rerun-previous-failed-testsrspec rspec-ee-pg16-rerun-previous-failed-tests 作业会运行前一次 MR 管道中失败的测试。

该功能于 2021 年 8 月 25 日引入,详见 https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69053

如何重新运行失败的测试

  1. detect-previous-failed-tests 作业(prepare 阶段)会检测与上一个 MR 管道中失败的 RSpec 作业相关的测试文件。
  2. rspec rspec-pg16-rerun-previous-failed-testsrspec rspec-ee-pg16-rerun-previous-failed-tests 作业将运行由 detect-previous-failed-tests 作业收集的测试文件。
graph LR
    subgraph "prepare 阶段";
        A["detect-previous-failed-tests"]
    end

    subgraph "测试阶段";
        B["rspec rspec-pg16-rerun-previous-failed-tests"];
        C["rspec rspec-ee-pg16-rerun-previous-failed-tests"];
    end

    A --"工件:测试文件列表"--> B & C

合并列车

当前使用情况

我们于 2024 年 6 月开始使用合并列车

目前,合并列车管道不会运行任何测试:它们仅执行在合并列车启用前就已存在的 “合并合并请求” 指南,但我们此前难以强制执行这些规则。

合并列车管道会运行单个 pre-merge-checks 作业,确保合并前的最新管道满足:

  1. 是一个合并结果管道
  2. 是一个tier-3 管道(完整管道,而非预测型)
  3. 创建时间不超过 8 小时前(稳定分支为 72 小时)

我们开启了一个反馈问题 来迭代此方案。

下一步迭代

我们开启了一个专门的问题来讨论合并列车的下一步迭代,以便实际在合并列车管道中运行测试。

启用合并列车运行“完整”测试管道的挑战

为什么需要“稳定”的默认分支?

如果默认分支不稳定(例如,默认分支的 CI/CD 管道频繁失败),那么在故障合并请求管道之后添加的所有合并请求管道都必须被取消重新加入列车,这会导致合并列车很长时产生大量延迟。

默认分支需要有多稳定?

我们没有具体数字,但需要有更好的关于 flaky 测试失败和基础设施失败的数据(参见主分支故障事件 RCA 仪表板)。

某些合并请求的更快反馈

修复损坏的主分支

当你需要修复损坏的主分支,你可以给合并请求添加 pipeline::expedited 标签以加速运行在该合并请求上的管道。

注意,合并请求还需要设置 master:brokenmaster:foss-broken 标签。

回滚 MR

为了使你的回滚 MR 更快,请在创建合并请求之前使用回滚 MR 模板。它会应用 pipeline::expedited 标签和其他会加速该合并请求上运行的管道的标签。

pipeline::expedited 标签

当此标签被分配时,CI/CD 管道的以下步骤将被跳过:

  • e2e:test-on-omnibus-ee 作业。
  • rspec:undercoverage 作业。
  • 整个评审应用流程

将标签应用到合并请求,并为 MR 运行新的管道。

测试作业

我们有针对每个测试级别的专用作业,每个作业根据你在合并请求中做出的更改来运行。
如果你想强制运行所有 RSpec 作业而不管你的更改,可以向合并请求添加 pipeline:run-all-rspec 标签。

强制在仅与文档相关的 MR 上运行所有作业会导致缺少前置作业并引发错误

端到端作业

有关更多信息,请参阅端到端测试管道

可观测性端到端作业

GitLab 可观测性后端 拥有专门的端到端测试,针对 GitLab 实例运行。这些测试旨在确保 GitLab 与可观测性后端的集成正常工作。

GitLab 流水线有专门的作业(参见 observability-backend.gitlab-ci.yml),可以从 GitLab 合并请求(MR)执行。这些作业将触发 GitLab 可观测性后端流水线上的端到端测试,针对从 GitLab MR 分支构建的 GitLab 实例。这些作业有助于确保正在审查的 GitLab 变更不会破坏 GitLab 可观测性后端流水线上的端到端测试。

有两个可观测性端到端作业:

  • e2e:observability-backend-main-branch:针对 GitLab 可观测性后端的主分支执行测试。
  • e2e:observability-backend:针对与 MR 分支同名的 GitLab 可观测性后端分支执行测试。

可观测性 E2E 作业仅自动触发于涉及相关文件的合并请求,例如 lib/gitlab/observability/ 目录中的文件或与可观测性功能相关的特定配置文件。

要手动运行这些作业,您可以在合并请求中添加 pipeline:run-observability-e2e-tests-main-branchpipeline:run-observability-e2e-tests-current-branch 标签。

在以下示例工作流中,开发者创建一个涉及可观测性代码的 MR 并使用可观测性端到端作业:

  1. 开发者创建一个涉及可观测性代码的 GitLab MR。该 MR 自动执行 e2e:observability-backend-main-branch 作业。
  2. 如果 e2e:observability-backend-main-branch 失败,则意味着要么 MR 破坏了某些东西(需要修复),要么 MR 的变更导致需要更新端到端测试。
  3. 要更新端到端测试,开发者应:
    1. 在 GitLab 可观测性后端仓库 中创建一个分支,其名称与包含破坏性变更的 GitLab 分支相同。
    2. 修复e2e 测试
    3. 创建带有变更的合并请求。
  4. 开发者应在 GitLab MR 上添加 pipeline:run-observability-e2e-tests-current-branch 标签,并等待 e2e:observability-backend 作业成功。
  5. 如果 e2e:observability-backend 成功,开发者可以合并这两个 MR。

此外,开发者可以手动添加 pipeline:run-observability-e2e-tests-main-branch 以强制 MR 运行 e2e:observability-backend-main-branch 作业。这在变更未被视为与可观测性相关的文件时很有用。

在某些情况下,开发者可能需要跳过这些测试。要跳过测试:

  • 对于 MR,应用 pipeline:skip-observability-e2e-tests 标签。
  • 对于整个项目,设置 CI 变量 SKIP_GITLAB_OBSERVABILITY_BACKEND_TRIGGER

评审应用作业

start-review-app-pipeline 子流水线会部署评审应用,并根据变更自动运行端到端测试,在其他情况下则是手动的。有关具体规则列表,请参阅 rules.gitlab-ci.yml 中的 .review:rules:start-review-app-pipeline

如果您想强制部署评审应用而不考虑您的变更,可以向合并请求添加 pipeline:run-review-app 标签。

有关更多信息,请参阅评审应用专用页面。

模拟开源(FOSS)作业与跨项目下游流水线

为确保相关变更在开源项目中正常工作,在某些情况下我们还会运行:

  • 同一流水线中的 * as-if-foss 作业
  • 跨项目下游开源流水线

* as-if-foss 作业会以“模拟开源”的方式运行 GitLab 测试套件,即仿佛这些作业会在 gitlab-org/gitlab-foss 的上下文中运行。另一方面,跨项目下游开源流水线实际上在开源项目中运行,这应该更接近真实的开源环境。

我们在以下情况运行它们:

  • 当合并请求上设置了 pipeline:run-as-if-foss 标签时
  • 当合并请求创建于 gitlab-org/security/gitlab 项目时
  • 当 CI 配置文件发生变更时(例如 .gitlab-ci.yml.gitlab/ci/**/*

* as-if-foss 作业会额外运行,除了常规的 EE 上下文作业。它们会设置 FOSS_ONLY='1' 变量,并在测试开始前移除 ee/ 文件夹。

跨项目下游开源流水线则模拟将合并请求合并到开源项目的默认分支,同时删除一系列文件。该列表可在 .gitlab/ci/as-if-foss.gitlab-ci.ymlmerge-train/bin/merge-train 中找到。

其目的是确保变更不会在 gitlab-org/gitlab 同步到 gitlab-org/gitlab-foss 后引发故障。

项目变量中设置的令牌

  • AS_IF_FOSS_TOKEN:这是一个具有 developer 角色和 write_repository 权限的 GitLab 开源(FOSS) 项目令牌,用于推送生成的 as-if-foss/* 分支。
    • 注意:安全项目使用相同名称时应使用另一个来自安全开源项目的令牌,这样我们就永远不会将安全变更推送到公共项目。

模拟极狐(JH)跨项目下游流水线

是什么

此流水线也称为 极狐验证流水线,目前允许失败。若发生失败,请遵循 验证流水线失败时该如何处理

如何运行

start-as-if-jh 作业会触发一个跨项目下游流水线,该流水线以“模拟极狐”的方式运行 GitLab 测试套件,即仿佛流水线会在 GitLab 极狐(JH) 的上下文中运行。这些作业仅在以下情况创建:

  • 当对功能标志进行变更时
  • 当合并请求上设置了 pipeline:run-as-if-jh 标签时

此流水线在 GitLab 极狐验证 项目的生成分支上下文中运行,该项目是 GitLab 极狐镜像 的镜像。

生成分支名称以 as-if-jh/ 为前缀,并包含合并请求中的分支名称。该生成分支基于合并请求分支,此外还添加了从 对应极狐分支 下载的变更,从而使整个流水线模拟极狐环境。

其目的是确保变更不会在 GitLab 同步到 GitLab 极狐(JH) 后引发故障。

何时考虑应用 pipeline:run-as-if-jh 标签

如果一个 Ruby 文件被重命名,并且存在对应的 prepend_mod 行,那么很可能 GitLab 极狐依赖于此,需要相应地重命名它所前置的模块或类。

对应的 JH 分支

你可以在 GitLab JH 上通过在分支名称后附加 -jh 来创建对应的 JH 分支。如果找到了对应的 JH 分支,as-if-jh 流水线会从相应的分支获取文件,而不是从默认分支 main-jh

目前,CI 会尝试从 GitLab JH 镜像 获取分支,因此新 JH 分支传播到镜像可能需要一些时间。

虽然 GitLab JH 验证GitLab JH 镜像 的镜像,但它除了默认的 main-jh 外,不包含任何对应的 JH 分支。这就是为什么当我们想要获取对应的 JH 分支时,应该从主镜像而不是验证项目获取的原因。

如何配置 as-if-JH 流水线

整个过程如下所示:

我们仅在存在依赖项更改时运行 sync-as-if-jh-branch

flowchart TD
  subgraph "JiHuLab.com"
    JH["gitlab-cn/gitlab"]
  end

  subgraph "GitLab.com"
    Mirror["gitlab-org/gitlab-jh-mirrors/gitlab"]

    subgraph MR["gitlab-org/gitlab 合并请求"]
      Add["add-jh-files 任务"]
      Prepare["prepare-as-if-jh-branch 任务"]
      Add --"下载产物"--> Prepare
    end

    subgraph "gitlab-org-sandbox/gitlab-jh-validation"
      Sync["(*可选) 在 as-if-jh-code-sync 分支上的 sync-as-if-jh-branch 任务"]
      Start["在 as-if-jh/* 分支上的 start-as-if-jh 任务"]
      AsIfJH["as-if-jh 流水线"]
    end

    Mirror --"使用 master 和 main-jh 拉取镜像"--> gitlab-org-sandbox/gitlab-jh-validation
    Mirror --"使用 ADD_JH_FILES_TOKEN 下载极狐文件"--> Add
    Prepare --"使用 AS_IF_JH_TOKEN 推送 as-if-jh 分支"--> Sync
    Sync --"使用 AS_IF_JH_TOKEN 推送 as-if-jh 分支"--> Start
    Start --> AsIfJH
  end

  JH --"使用对应的 JH 分支拉取镜像"--> Mirror
项目变量中设置的令牌
  • ADD_JH_FILES_TOKEN:这是 GitLab JH 镜像 项目的令牌,具有 read_api 权限,以便能够下载极狐文件。
  • AS_IF_JH_TOKEN:这是 GitLab JH 验证 项目的令牌,具有 developer 角色和 write_repository 权限,以推送生成的 as-if-jh/* 分支。
我们如何生成 as-if-JH 分支

首先,add-jh-files 任务会从对应的 JH 分支下载所需的极狐文件,并将其保存为产物。接着,prepare-as-if-jh-branch 任务会从合并请求分支创建一个新分支,提交变更,最后将该分支推送到 验证项目

可选地,如果合并请求有依赖项的更改,我们会额外运行 sync-as-if-jh-branch 任务,以触发验证项目中 as-if-jh-code-sync 分支 的下游流水线。此任务将执行与 极狐代码同步 相同的过程,确保在运行验证流水线之前,依赖项的更改可以应用到 as-if-jh 分支。

如果没有依赖项更改,我们不运行此过程。

我们如何触发和运行 as-if-JH 流水线

在准备好 as-if-jh/* 分支(并可选地进行同步)之后,start-as-if-jh 任务会触发 验证项目 中的跨项目下游流水线来运行。

如何设置 GitLab JH 镜像项目

GitLab JH 镜像 项目是私有的,且 CI 已禁用。

它是一个拉取镜像,从 GitLab JH 拉取,镜像所有分支,覆盖分歧引用,当镜像更新时不触发流水线。

拉取用户是 @gitlab-jh-validation-bot,他是该项目的主要维护者。凭据可在 1password 工程保险库中找到。

由于 GitLab JH 是公开项目,镜像过程中不使用密码。

GitLab JH 验证项目的设置方式

这个 GitLab JH 验证 项目是公开的,且启用了CI,设置了临时项目变量。

它是一个拉取镜像,从 GitLab JH 镜像 拉取,镜像特定的分支:(master|main-jh),覆盖分歧引用(divergent refs),当镜像更新时不触发流水线。

拉取用户是 @gitlab-jh-validation-bot,他是该项目中的维护者,也是 GitLab JH 镜像 的维护者。凭证可在1password工程保险库中找到。

使用来自 @gitlab-jh-validation-bot 且具有 write_repository 权限的个人访问令牌作为密码,从 GitLab JH 镜像拉取更改。用户名设置为 gitlab-jh-validation-bot

还有一个 流水线调度 用于运行维护流水线,将变量 SCHEDULE_TYPE 设置为 maintenance,每天运行一次,更新缓存。

默认的CI/CD配置文件也设置在 jh/.gitlab-ci.yml 中,因此其运行方式与 GitLab JH 完全一致。

此外,还设置并保护了一个特殊分支 as-if-jh-code-sync。维护者可以推送此分支,开发者可以合并此分支。我们需要这样设置以便开发者能够合并,因为我们希望让开发者能为此分支触发流水线。这是在我们解决 开发级用户无法再在受保护的分支上运行流水线 问题之前的折衷方案。

它用于运行 sync-as-if-jh-branch 来同步依赖项,当合并请求改变了依赖项时。有关其实现细节,请参阅 我们如何生成 as-if-JH 分支

临时 GitLab JH 验证项目变量
为什么我们同时有镜像项目和验证项目?

我们分开设立这两个项目有几个原因。

  • 安全性:以前我们只有镜像项目。然而,为了完全缓解安全问题,我们必须将镜像项目设为私有。
  • 隔离性:我们希望在完全隔离且独立的项目中运行JH代码。我们不应该在gitlab-org组(即镜像项目所在位置)下运行它。验证项目是完全隔离的。
  • 成本效益:我们不希望每次合并请求都连接到极狐GitLab.com。更划算的方式是将代码从极狐GitLab.com镜像到GitLab.com的某个位置,让我们的合并请求从那里获取代码。这意味着验证项目可以从镜像获取代码,而不是直接从极狐GitLab.com。镜像项目会定期从极狐GitLab.com拉取代码。
  • 分支分离/安全性/效率:我们想要镜像所有分支,以便从极狐GitLab.com获取对应的JH分支。但是,我们不想覆盖验证项目中的as-if-jh-code-sync分支,因为我们用它来控制验证流水线,并且它拥有AS_IF_JH_TOKEN的访问权限。然而,我们不能只排除单个分支进行镜像。详见此问题了解详情。

鉴于这个问题,验证项目被设置为仅镜像mastermain-jh。从技术角度来说,我们甚至不需要这些分支,但我们确实希望仓库与所有默认分支保持同步,这样当我们从合并请求推送更改时,只需推送合并请求的变更即可,这会更高效。

  • 职责分离:
    • 验证项目仅有以下分支:
      • mastermain-jh以保持变更最新。
      • as-if-jh-code-sync用于依赖同步。我们绝不应镜像此分支。
      • 来自合并请求的as-if-jh/*分支。我们绝不应镜像这些分支。
    • 镜像项目的所有分支均来自极狐GitLab.com。我们从未向镜像项目推送任何内容,它也不会运行任何流水线。镜像项目已禁用CI/CD。

我们可以考虑合并这两个项目以简化设置和流程,但需要确保所有这些原因都不再成为问题。

rspec:undercoverage 作业

rspec:undercoverage 作业运行 undercover 来检测,若合并请求中引入的任何变更存在零覆盖率,则会失败。

rspec:undercoverage 作业从 rspec:coverage 作业获取覆盖率数据。

如果 rspec:undercoverage 作业检测到因EE覆盖CE方法而导致的缺失覆盖率,请给合并请求添加 pipeline:run-as-if-foss 标签并启动新的流水线。

在紧急情况下,或此作业出现误报时,请给合并请求添加 pipeline:skip-undercoverage 标签以允许此作业失败。

排查 rspec:undercoverage 失败问题

rspec:undercoverage 作业存在已知缺陷,可能导致误报失败。如果你正在更新过于古老的数据库迁移,也可能发生此类误报失败。你可以本地测试覆盖率,以确定是否可以安全地应用 pipeline:skip-undercoverage。例如,使用 <spec> 作为导致失败的测试名称:

  1. 运行 RUN_ALL_MIGRATION_TESTS=1 SIMPLECOV=1 bundle exec rspec <spec>
  2. 运行 scripts/undercoverage

如果这些命令返回 undercover: ✅ 最新变更无缺失覆盖率,则可以应用 pipeline:skip-undercoverage 以绕过流水线失败。

pajamas_adoption 作业

pajamas_adoption 作业在合并请求中运行 Pajamas Adoption Scanner,以防止对 Pajamas 设计系统 采用情况的回归。

如果扫描器检测到由合并请求引起的回归,作业将失败。如果回归无法在合并请求中修复,请给合并请求添加 pipeline:skip-pajamas-adoption 标签,然后重试该作业。

测试套件并行化

我们当前的 RSpec 测试并行化设置如下:

  1. prepare 阶段中的 retrieve-tests-metadata 作业确保我们有 knapsack/report-master.json 文件:
    • knapsack/report-master.json 文件从最新的运行 update-tests-metadatamain 流水线中获取(目前是每 2 小时一次的 maintenance 计划主流水线),如果不存在,我们会用 {} 初始化该文件。
  2. 每个 [rspec|rspec-ee] [migration|unit|integration|system|geo] n m 作业都使用 knapsack rspec 运行,并且应该有均匀分布的测试份额:
    • 这是因为作业可以访问 knapsack/report-master.json,因为"默认会传递所有先前阶段的产物"。
    • 作业将自己的报告路径设置为 "knapsack/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json"
    • 如果 knapsack 正常工作,运行的测试文件应列在 Report specs 下,而不是 Leftover specs 下。
  3. update-tests-metadata 作业(仅在计划流水线上为 官方项目 运行)以两种方式更新 knapsack/report-master.json
    1. 默认情况下,它获取所有的 knapsack/rspec*.json 文件并将它们合并成一个单一的 knapsack/report-master.json 文件,保存为产物。
    2. (实验性)当 AVERAGE_KNAPSACK_REPORT 环境变量设置为 true 时,该作业不会合并报告,而是计算 knapsack/report-master.jsonknapsack/rspec*.json 之间的测试持续时间平均值,以减少潜在随机因素(如规范排序、运行器硬件差异、不稳定测试等)对性能的影响。这种实验性方法旨在更好地预测每个规范文件的持续时间,以便更均匀地在并行作业之间分配负载,使作业能在大致相同的时间完成。

之后,下一个流水线使用最新的 knapsack/report-master.json 文件。

不稳定测试

不稳定测试的自动跳过

我们过去会跳过 已知不稳定的测试,但我们现在不再这样做,因为这实际上可能导致真正的 master 分支损坏。相反,我们引入了 快速隔离流程,主动隔离任何在 #master-broken 事件中报告的不稳定测试。

可以通过将 $FAST_QUARANTINE 变量设置为 false 来禁用此快速隔离流程。

失败测试在新进程中的自动重试

除非 $RETRY_FAILED_TESTS_IN_NEW_PROCESS 变量设置为 false(默认为 true),否则失败的 RSpec 测试会在单独的 RSpec 进程中自动重试一次。目标是消除之前测试可能导致的后续测试失败的大多数副作用。

我们通过 rspec:flaky-tests-report 作业保存为产物的 $RETRIED_TESTS_REPORT_FILE 文件跟踪已重试的测试。

请参阅 实验问题

兼容性测试

默认情况下,我们使用 GitLab.com 上运行的版本来运行所有测试。

其他版本(通常是一个向后兼容版本和一个向前兼容版本)应该在夜间计划流水线中运行。

对此一般准则的例外情况应有充分理由并记录在案。

Ruby 版本测试

我们在 GitLab.com 以及默认分支上运行 Ruby 3.2。为了准备下一个 Ruby 版本,我们对合并请求运行 Ruby 3.3。有关更多详情,请参阅 Ruby 3.3 史诗 路线图。

为确保所有支持的 Ruby 版本都能正常工作,我们还针对每个支持版本的专用每 2 小时计划流水线运行我们的测试套件。

对于合并请求,您可以添加以下标签来仅运行相应的 Ruby 版本:

  • pipeline:run-in-ruby3_3

PostgreSQL 版本测试

我们的测试套件针对 PostgreSQL 16 运行,因为 GitLab.com 运行在 PostgreSQL 16 上,且 Omnibus 新安装和升级默认为 PG14

我们在夜间计划流水线中对 PostgreSQL 14、15、16 和 17 运行测试套件。

注意:随着 PG17 的加入,我们接近了夜间作业的限制,每个流水线有 1946 个作业(共 2000 个)。添加新的作业族可能导致夜间流水线失败。

当前版本测试

位置? PostgreSQL 版本 Ruby 版本
合并请求(Merge requests) 16(默认版本) 3.2(默认版本)
## 日志记录

- 在 CI 中,默认禁用了对 `log/test.log` 的 Rails 日志记录(出于性能考虑)。若要覆盖此设置,请提供 `RAILS_ENABLE_TEST_LOG` 环境变量。

## CI 配置内部机制

请参阅专门的 [CI 配置内部机制页面](internals.md)。

## 性能

请参阅专门的 [CI 配置性能页面](performance.md)。

---

[返回开发文档](../_index.md)