{{< details >}}

  • Tier: 基础版, 专业版, 旗舰版
  • Offering: JihuLab.com, 私有化部署

{{< /details >}}

你可以使用 include 在你的 CI/CD 作业中包含外部 YAML 文件。

包含单个配置文件

要包含单个配置文件,可以使用 include 关键字,并通过以下任一语法选项指定单个文件:

  • 在同一行上:

    include: 'my-config.yml'
    
  • 作为数组中的单个项:

    include:
      - 'my-config.yml'
    

如果文件是本地文件,其行为与 include:local 相同。如果文件是远程文件,则与 include:remote 相同。

包含配置文件数组

你可以包含一个配置文件数组:

  • 如果未指定 include 类型,则每个数组项默认使用 include:localinclude:remote,根据需要选择:

    include:
      - 'https://jihulab.com/awesome-project/raw/main/.before-script-template.yml'
      - 'templates/.after-script-template.yml'
    
  • 你可以定义单个项数组:

    include:
      - remote: 'https://jihulab.com/awesome-project/raw/main/.before-script-template.yml'
    
  • 你可以定义一个数组,并显式指定多个 include 类型:

    include:
      - remote: 'https://jihulab.com/awesome-project/raw/main/.before-script-template.yml'
      - local: 'templates/.after-script-template.yml'
      - template: Auto-DevOps.gitlab-ci.yml
    
  • 你可以定义一个数组,该数组结合了默认和特定的 include 类型:

    include:
      - 'https://jihulab.com/awesome-project/raw/main/.before-script-template.yml'
      - 'templates/.after-script-template.yml'
      - template: Auto-DevOps.gitlab-ci.yml
      - project: 'my-group/my-project'
        ref: main
        file: 'templates/.gitlab-ci-template.yml'
    

使用包含配置文件中的 default 配置

你可以在配置文件中定义一个 default 部分。当你在 include 关键字中使用 default 部分时,默认值将应用于流水线中的所有作业。

例如,你可以在 before_script 中使用 default 部分。

名为 /templates/.before-script-template.yml 的自定义配置文件的内容:

default:
  before_script:
    - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
    - gem install bundler --no-document
    - bundle install --jobs $(nproc)  "${FLAGS[@]}"

.gitlab-ci.yml 的内容:

include: 'templates/.before-script-template.yml'

rspec1:
  script:
    - bundle exec rspec

rspec2:
  script:
    - bundle exec rspec

默认的 before_script 命令在两个 rspec 作业中执行,在 script 命令之前。

覆盖包含的配置值

当你使用 include 关键字时,你可以覆盖包含的配置值,以便根据你的流水线要求进行调整。

以下示例显示了一个在 .gitlab-ci.yml 文件中自定义的 include 文件。特定的 YAML 定义变量和 production 作业的详细信息被覆盖。

名为 autodevops-template.yml 的自定义配置文件的内容:

variables:
  POSTGRES_USER: user
  POSTGRES_PASSWORD: testing_password
  POSTGRES_DB: $CI_ENVIRONMENT_SLUG

production:
  stage: production
  script:
    - install_dependencies
    - deploy
  environment:
    name: production
    url: https://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

.gitlab-ci.yml 的内容:

include: 'https://company.com/autodevops-template.yml'

default:
  image: alpine:latest

variables:
  POSTGRES_USER: root
  POSTGRES_PASSWORD: secure_password

stages:
  - build
  - test
  - production

production:
  environment:
    url: https://domain.com

.gitlab-ci.yml 文件中定义的 POSTGRES_USERPOSTGRES_PASSWORD 变量以及 production 作业的 environment:url 覆盖了 autodevops-template.yml 文件中定义的值。其他关键字不变。这种方法称为合并

include 的合并方法

include 配置通过以下过程与主配置文件合并:

  • 按配置文件中定义的顺序读取包含的文件,并按相同顺序合并包含的配置。
  • 如果包含的文件也使用 include,则首先递归合并嵌套的 include 配置。
  • 如果参数重叠,最后包含的文件在合并包含的文件配置时优先。
  • 在所有通过 include 添加的配置合并在一起后,主配置与包含的配置合并。

这种合并方法是一个 深度合并,其中任何深度的哈希映射在配置中合并。为了合并哈希映射“A”(包含到目前为止合并的配置)和“B”(下一个配置片段),键和值按以下方式处理:

  • 当键仅存在于 A 中时,使用 A 中的键和值。
  • 当键存在于 A 和 B 中,并且它们的值都是哈希映射时,合并这些哈希映射。
  • 当键存在于 A 和 B 中,并且其中一个值不是哈希映射时,使用 B 中的值。
  • 否则,使用 B 中的键和值。

例如,配置由两个文件组成:

  • .gitlab-ci.yml 文件:

    include: 'common.yml'
    
    variables:
      POSTGRES_USER: username
    
    test:
      rules:
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
          when: manual
      artifacts:
        reports:
          junit: rspec.xml
    
  • common.yml 文件:

    variables:
      POSTGRES_USER: common_username
      POSTGRES_PASSWORD: testing_password
    
    test:
      rules:
        - when: never
      script:
        - echo LOGIN=${POSTGRES_USER} > deploy.env
        - rake spec
      artifacts:
        reports:
          dotenv: deploy.env
    

合并的结果是:

variables:
  POSTGRES_USER: username
  POSTGRES_PASSWORD: testing_password

test:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: manual
  script:
    - echo LOGIN=${POSTGRES_USER} > deploy.env
    - rake spec
  artifacts:
    reports:
      junit: rspec.xml
      dotenv: deploy.env

在此示例中:

  • 变量仅在所有文件合并后才会被评估。包含文件中的作业可能会使用在不同文件中定义的变量值。
  • rules 是一个数组,因此无法合并。顶级文件优先。
  • artifacts 是一个哈希映射,因此可以进行深度合并。

覆盖包含的配置数组

你可以使用合并来扩展和覆盖包含模板中的配置,但无法添加或修改数组中的单个项。例如,要在扩展的 production 作业的 script 数组中添加额外的 notify_owner 命令:

autodevops-template.yml 的内容:

production:
  stage: production
  script:
    - install_dependencies
    - deploy

.gitlab-ci.yml 的内容:

include: 'autodevops-template.yml'

stages:
  - production

production:
  script:
    - install_dependencies
    - deploy
    - notify_owner

如果 install_dependenciesdeploy 未在 .gitlab-ci.yml 文件中重复,则 production 作业的脚本中将只有 notify_owner

使用嵌套包含

你可以在配置文件中嵌套 include 部分,然后在另一个配置中包含。例如,对于嵌套三层的 include 关键字:

.gitlab-ci.yml 的内容:

include:
  - local: /.gitlab-ci/another-config.yml

/.gitlab-ci/another-config.yml 的内容:

include:
  - local: /.gitlab-ci/config-defaults.yml

/.gitlab-ci/config-defaults.yml 的内容:

default:
  after_script:
    - echo "Job complete."

使用重复 include 条目的嵌套包含

你可以在主配置文件和嵌套包含中多次包含相同的配置文件。

如果任何文件使用 覆盖 更改包含的配置,则 include 条目的顺序可能会影响最终配置。最后一次包含的配置会覆盖之前任何时候包含的文件。例如:

  • defaults.gitlab-ci.yml 文件的内容:

    default:
      before_script: echo "Default before script"
    
  • unit-tests.gitlab-ci.yml 文件的内容:

    include:
      - template: defaults.gitlab-ci.yml
    
    default:  # 覆盖包含的默认
      before_script: echo "Unit test default override"
    
    unit-test-job:
      script: unit-test.sh
    
  • smoke-tests.gitlab-ci.yml 文件的内容:

    include:
      - template: defaults.gitlab-ci.yml
    
    default:  # 覆盖包含的默认
      before_script: echo "Smoke test default override"
    
    smoke-test-job:
      script: smoke-test.sh
    

使用这三个文件,包含的顺序会更改最终配置。 如果:

  • unit-tests 首先包含,.gitlab-ci.yml 文件的内容是:

    include:
      - local: unit-tests.gitlab-ci.yml
      - local: smoke-tests.gitlab-ci.yml
    

    最终配置将是:

    unit-test-job:
     before_script: echo "Smoke test default override"
     script: unit-test.sh
    
    smoke-test-job:
     before_script: echo "Smoke test default override"
     script: smoke-test.sh
    
  • unit-tests 最后包含,.gitlab-ci.yml 文件的内容是:

    include:
      - local: smoke-tests.gitlab-ci.yml
      - local: unit-tests.gitlab-ci.yml
    
  • 最终配置将是:

    unit-test-job:
     before_script: echo "Unit test default override"
     script: unit-test.sh
    
    smoke-test-job:
     before_script: echo "Unit test default override"
     script: smoke-test.sh
    

如果没有文件覆盖包含的配置,则 include 条目的顺序不会影响最终配置。

include 中使用变量

.gitlab-ci.yml 文件的 include 部分中,你可以使用:

例如:

include:
  project: '$CI_PROJECT_PATH'
  file: '.compliance-gitlab-ci.yml'

你不能在作业中定义的变量或在全局 variables 部分中定义的变量中使用 include。在作业之前评估包含,因此这些变量不能与 include 一起使用。

你不能在动态子流水线的配置中的 include 部分中使用 CI/CD 变量。

使用 rulesinclude

{{< history >}}

  • needs 作业依赖项支持引入于极狐GitLab 15.11。

{{< /history >}}

你可以使用 rulesinclude 有条件地包含其他配置文件。

你只能使用 某些变量 和以下关键字与 rules 配合使用:

使用 rules:ifinclude

{{< history >}}

  • when: neverwhen:always 的支持引入于极狐GitLab 16.1,使用名为 ci_support_include_rules_when_never功能标志 。默认禁用。
  • when: neverwhen:always 的支持在极狐GitLab 16.2 中 GA。功能标志 ci_support_include_rules_when_never 已删除。

{{< /history >}}

使用 rules:if 基于 CI/CD 变量的状态有条件地包含其他配置文件。例如:

include:
  - local: builds.yml
    rules:
      - if: $DONT_INCLUDE_BUILDS == "true"
        when: never
  - local: builds.yml
    rules:
      - if: $ALWAYS_INCLUDE_BUILDS == "true"
        when: always
  - local: builds.yml
    rules:
      - if: $INCLUDE_BUILDS == "true"
  - local: deploys.yml
    rules:
      - if: $CI_COMMIT_BRANCH == "main"

test:
  stage: test
  script: exit 0

使用 rules:existsinclude

{{< history >}}

  • when: neverwhen:always 的支持引入于极狐GitLab 16.1,使用名为 ci_support_include_rules_when_never功能标志 。默认禁用。
  • when: neverwhen:always 的支持在极狐GitLab 16.2 中 GA。功能标志 ci_support_include_rules_when_never 已删除。

{{< /history >}}

使用 rules:exists 基于文件的存在有条件地包含其他配置文件。例如:

include:
  - local: builds.yml
    rules:
      - exists:
          - exception-file.md
        when: never
  - local: builds.yml
    rules:
      - exists:
          - important-file.md
        when: always
  - local: builds.yml
    rules:
      - exists:
          - file.md

test:
  stage: test
  script: exit 0

在此示例中,极狐GitLab 检查当前项目中是否存在 file.md

如果你在来自不同项目的包含文件中使用 includerules:exists,请仔细检查你的配置。极狐GitLab 检查 其他 项目中是否存在该文件。例如:

# my-group/my-project 中的流水线配置
include:
  - project: my-group/other-project
    ref: other_branch
    file: other-file.yml

test:
  script: exit 0

# my-group/other-project 中 other_branch 引用的 other-file.yml
include:
  - project: my-group/my-project
    ref: main
    file: my-file.yml
    rules:
      - exists:
          - file.md

在此示例中,极狐GitLab 在 my-group/other-project 中搜索 file.md 的存在,而不是流水线运行的项目/引用。

要更改搜索上下文,你可以使用 rules:exists:pathsrules:exists:project。例如:

include:
  - project: my-group/my-project
    ref: main
    file: my-file.yml
    rules:
      - exists:
          paths:
            - file.md
          project: my-group/my-project
          ref: main

使用 rules:changesinclude

{{< history >}}

  • 在极狐GitLab 16.4 引入。

{{< /history >}}

使用 rules:changes 基于更改的文件有条件地包含其他配置文件。例如:

include:
  - local: builds1.yml
    rules:
      - changes:
        - Dockerfile
  - local: builds2.yml
    rules:
      - changes:
          paths:
            - Dockerfile
          compare_to: 'refs/heads/branch1'
        when: always
  - local: builds3.yml
    rules:
      - if: $CI_PIPELINE_SOURCE == "merge_request_event"
        changes:
          paths:
            - Dockerfile

test:
  stage: test
  script: exit 0

在此示例中:

  • Dockerfile 发生更改时,包含 builds1.yml
  • Dockerfile 相对于 refs/heads/branch1 发生更改时,包含 builds2.yml
  • Dockerfile 发生更改且流水线源是合并请求事件时,包含 builds3.ymlbuilds3.yml 中的作业还必须配置为运行 合并请求流水线

使用 include:local 和通配符文件路径

你可以使用 include:local 的通配符路径 (***)。

示例:

include: 'configs/*.yml'

当流水线运行时,极狐GitLab:

  • configs 目录中的所有 .yml 文件添加到流水线配置中。
  • 不会添加 configs 目录子文件夹中的 .yml 文件。要允许此操作,请添加以下配置:

    # 这匹配 `configs` 及其子文件夹中的所有 `.yml` 文件。
    include: 'configs/**.yml'
    
    # 这仅匹配 `configs` 的子文件夹中的所有 `.yml` 文件。
    include: 'configs/**/*.yml'
    

疑难解答

最多允许 150 个嵌套的 includes! 错误

流水线的 嵌套包含文件 最大数量为 150。如果你在流水线中收到 最多允许 150 个 includes 错误消息,可能是因为:

  • 某些嵌套配置包含过多的额外嵌套 include 配置。
  • 嵌套包含中存在意外循环。例如,include1.yml 包含 include2.yml,而 include2.yml 包含 include1.yml,从而创建了递归循环。

为了帮助减少这种情况的发生,使用 流水线编辑器 编辑流水线配置文件,该编辑器会验证是否达到限制。你可以一次删除一个包含的文件,尝试缩小循环或过多包含文件的配置文件的来源。

在极狐GitLab 16.0 及更高版本中,极狐GitLab 私有化部署用户可以更改 最大包含数 值。

最大包含数

SSL_connect SYSCALL returned=5 errno=0 state=SSLv3/TLS write client hello 和其他网络故障

使用 include:remote 时,极狐GitLab 通过 HTTP(S) 尝试获取远程文件。由于各种连接问题,此过程可能会失败。

当极狐GitLab 无法建立到远程主机的 HTTPS 连接时,会发生 SSL_connect SYSCALL returned=5 errno=0 state=SSLv3/TLS write client hello 错误。此问题可能是由于远程主机具有速率限制以防止服务器因请求过多而过载。

例如,极狐GitLab.com 的 GitLab Pages 服务器是速率限制的。多次尝试从 GitLab Pages 托管的 CI/CD 配置文件中获取可能会导致达到速率限制并导致错误。你应该避免在 GitLab Pages 站点上托管 CI/CD 配置文件。

如果可能,使用 include:project 从极狐GitLab 实例中的其他项目中获取配置文件,而不进行外部 HTTP(S) 请求。