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

使用其他文件中的 CI/CD 配置

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

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

包含单个配置文件

要包含单个配置文件,请单独使用 include 并选择以下任一语法选项:

  • 在同一行:

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

    include:
      - 'my-config.yml'

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

包含配置文件数组

您可以包含配置文件数组:

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

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

    include:
      - remote: 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
  • 您可以定义数组并明确指定多个 include 类型:

    include:
      - remote: 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
      - local: 'templates/.after-script-template.yml'
      - template: Auto-DevOps.gitlab-ci.yml
  • 您可以定义一个同时包含默认和特定 include 类型的数组:

    include:
      - 'https://gitlab.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 部分。当您将 default 部分与 include 关键字一起使用时,默认值将应用于管道中的所有作业。

例如,您可以将 default 部分与 before_script 一起使用。

名为 /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 作业的 script 中将只有 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 一起使用。

有关如何包含预定义变量及其对 CI/CD 作业影响的示例,请参阅此 CI/CD 变量演示

您不能在动态子管道配置的 include 部分中使用 CI/CD 变量。问题 378717 提议修复此问题。

include 中使用 rules

您可以将 rulesinclude 一起使用,以有条件地包含其他配置文件。

您只能将 rules某些变量以及以下关键字一起使用:

includerules:if

使用 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

includerules:exists

使用 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 中 ref other_branch 上的 other-file.yml
include:
  - project: my-group/my-project
    ref: main
    file: my-file.yml
    rules:
      - exists:
          - file.md

在此示例中,GitLab 在运行管道的项目/引用中搜索 file.md 的存在性,而不是在 my-group/other-project 的 commit ref other_branch 中。

要更改搜索上下文,您可以将 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

includerules:changes

使用 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'

故障排除

Maximum of 150 nested includes are allowed! 错误

管道的嵌套包含文件最大数量为 150。如果您在管道中收到 Maximum 150 includes are allowed 错误消息,可能是由于:

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

为帮助降低此风险,请使用管道编辑器编辑管道配置文件,该编辑器会验证是否达到限制。您可以一次删除一个包含文件,以尝试缩小导致循环或过多包含文件的配置文件范围。

GitLab 16.0 及更高版本中,GitLab Self-Managed 的用户可以更改最大包含数值。

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

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

SSL_connect SYSCALL returned=5 errno=0 state=SSLv3/TLS write client hello 错误发生在 GitLab 无法建立与远程主机的 HTTPS 连接时。如果远程主机有速率限制以防止服务器因请求过载,则可能导致此问题。

例如,GitLab.com 的 GitLab Pages 服务器受到速率限制。重复尝试获取托管在 GitLab Pages 上的 CI/CD 配置文件可能导致达到速率限制并引发错误。您应避免在 GitLab Pages 站点上托管 CI/CD 配置文件。

在可能的情况下,使用 include:project 从 GitLab 实例内的其他项目获取配置文件,而无需进行外部 HTTP(S) 请求。