{{< details >}}

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

{{< /details >}}

极狐GitLab下游流水线是任何由其他流水线触发的极狐GitLab CI/CD流水线。下游流水线独立并与触发它们的上游流水线并行运行。

  • 父子流水线是在与第一个流水线相同的项目中触发的下游流水线。
  • 多项目流水线是在与第一个流水线不同的项目中触发的下游流水线。

您有时可以将父子流水线和多项目流水线用于类似的目的,但它们有关键区别

流水线层级默认最多可包含 1000 个下游流水线。有关此限制及如何更改的信息,请参阅限制流水线层级大小

父子流水线

父流水线是在同一项目中触发下游流水线的流水线。下游流水线被称为子流水线。

子流水线:

  • 在与父流水线相同的项目、引用和提交 SHA 下运行。
  • 不直接影响流水线运行时所针对引用的整体状态。例如,如果主分支的流水线失败,通常会说“主分支坏了”。只有当子流水线使用 strategy:depend 触发时,子流水线的状态才会影响引用的状态。
  • 如果流水线配置了 interruptible,当为相同引用创建新流水线时,会自动取消。
  • 不会在项目的流水线列表中显示。您只能在其父流水线的详情页面上查看子流水线。

嵌套子流水线

父子流水线最多可以有两级子流水线。

父流水线可以触发多个子流水线,这些子流水线可以触发它们自己的子流水线。您不能触发另一个级别的子流水线。

多项目流水线

一个项目中的流水线可以触发其他项目中的下游流水线,称为多项目流水线。触发上游流水线的用户必须能够在下游项目中启动流水线,否则下游流水线无法启动

多项目流水线:

  • 从其他项目的流水线触发,但上游(触发)流水线对下游(触发)流水线没有太多控制。然而,它可以选择下游流水线的引用,并将 CI/CD 变量传递给它。
  • 影响其运行项目的引用的整体状态,但不会影响触发流水线引用的状态,除非它是使用 strategy:depend 触发的。
  • 当使用 interruptible 时,如果上游流水线中为相同引用运行新流水线,下游项目中的流水线不会自动取消。如果在下游项目中为相同引用触发新流水线,它们可以自动取消。
  • 在下游项目的流水线列表中可见。
  • 是独立的,因此没有嵌套限制。

如果您使用公共项目触发私有项目中的下游流水线,请确保没有保密问题。上游项目的流水线页面始终显示:

  • 下游项目的名称。
  • 流水线的状态。

.gitlab-ci.yml 文件中的作业触发下游流水线

在您的 .gitlab-ci.yml 文件中使用 trigger 关键字创建一个触发下游流水线的作业。此作业称为触发作业。

例如:

{{< tabs >}}

{{< tab title=”Parent-child pipeline” >}}

trigger_job:
  trigger:
    include:
      - local: path/to/child-pipeline.yml

{{< /tab >}}

{{< tab title=”Multi-project pipeline” >}}

trigger_job:
  trigger:
    project: project-group/my-downstream-project

{{< /tab >}}

{{< /tabs >}}

触发作业开始后,作业的初始状态为 pending,同时极狐GitLab尝试创建下游流水线。如果下游流水线创建成功,触发作业显示为 passed,否则显示为 failed。或者,您可以设置触发作业以显示下游流水线的状态

使用 rules 控制下游流水线作业

使用 CI/CD 变量或 rules 关键字以控制下游流水线中的作业行为

当您使用 trigger 关键字触发下游流水线时,所有作业的 $CI_PIPELINE_SOURCE 预定义变量 的值为:

  • 多项目流水线的 pipeline
  • 父子流水线的 parent_pipeline

例如,要在一个同时运行合并请求流水线的项目中控制多项目流水线中的作业:

job1:
  rules:
    - if: $CI_PIPELINE_SOURCE == "pipeline"
  script: echo "此作业仅在多项目流水线中运行"

job2:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script: echo "此作业仅在合并请求流水线中运行"

job3:
  rules:
    - if: $CI_PIPELINE_SOURCE == "pipeline"
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script: echo "此作业在多项目和合并请求流水线中均运行"

在不同项目中使用子流水线配置文件

您可以在触发作业中使用 include:project 以使用不同项目中的配置文件触发子流水线:

microservice_a:
  trigger:
    include:
      - project: 'my-group/my-pipeline-library'
        ref: 'main'
        file: '/path/to/child-pipeline.yml'

合并多个子流水线配置文件

在定义子流水线时,您最多可以包含三个配置文件。子流水线的配置由所有合并在一起的配置文件组成:

microservice_a:
  trigger:
    include:
      - local: path/to/microservice_a.yml
      - template: Jobs/SAST.gitlab-ci.yml
      - project: 'my-group/my-pipeline-library'
        ref: 'main'
        file: '/path/to/child-pipeline.yml'

动态子流水线

您可以从作业中生成的 YAML 文件触发子流水线,而不是保存在项目中的静态文件。此技术对于生成针对更改内容的流水线或构建目标和架构的矩阵非常强大。

包含生成的 YAML 文件的产物必须在实例限制内。

触发动态子流水线

要从动态生成的配置文件触发子流水线:

  1. 在作业中生成配置文件并将其保存为产物

    generate-config:
      stage: build
      script: generate-ci-config > generated-config.yml
      artifacts:
        paths:
          - generated-config.yml
    
  2. 配置触发作业以在生成配置文件的作业后运行。将 include: artifact 设置为生成的产物,并将 include: job 设置为创建产物的作业:

    child-pipeline:
      stage: test
      trigger:
        include:
          - artifact: generated-config.yml
            job: generate-config
    

在此示例中,极狐GitLab检索 generated-config.yml 并使用该文件中的 CI/CD 配置触发子流水线。

产物路径由极狐GitLab解析,而不是 runner,因此路径必须与运行极狐GitLab的操作系统的语法匹配。如果极狐GitLab运行在 Linux 上,但使用 Windows runner 进行测试,则触发作业的路径分隔符为 /。其他使用 Windows runner 的作业的 CI/CD 配置,例如脚本,使用 \

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

使用合并请求流水线运行子流水线

流水线,包括子流水线,默认作为分支流水线运行,当不使用 rulesworkflow:rules 时。要配置子流水线在合并请求(父)流水线触发时运行,请使用 rulesworkflow:rules。例如,使用 rules

  1. 设置父流水线的触发作业在合并请求时运行:

    trigger-child-pipeline-job:
      trigger:
        include: path/to/child-pipeline-configuration.yml
      rules:
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    
  2. 使用 rules 配置子流水线作业以在父流水线触发时运行:

    job1:
      script: echo "此子流水线作业在任何时候父流水线触发时运行。"
      rules:
        - if: $CI_PIPELINE_SOURCE == "parent_pipeline"
    
    job2:
      script: echo "此子流水线作业仅在父流水线是合并请求流水线时运行"
      rules:
        - if: $CI_MERGE_REQUEST_ID
    

在子流水线中,$CI_PIPELINE_SOURCE 始终有一个值为 parent_pipeline,因此:

  • 您可以使用 if: $CI_PIPELINE_SOURCE == "parent_pipeline" 确保子流水线作业始终运行。
  • 您_不能_使用 if: $CI_PIPELINE_SOURCE == "merge_request_event" 配置子流水线作业以在合并请求流水线中运行。相反,使用 if: $CI_MERGE_REQUEST_ID 设置子流水线作业仅在父流水线是合并请求流水线时运行。父流水线的 CI_MERGE_REQUEST_* 预定义变量 被传递给子流水线作业。

为多项目流水线指定分支

您可以指定触发多项目流水线时使用的分支。极狐GitLab使用分支头部的提交来创建下游流水线。例如:

staging:
  stage: deploy
  trigger:
    project: my/deployment
    branch: stable-11-2

使用:

  • project 关键字指定下游项目的完整路径。在极狐GitLab 15.3 及更高版本中,您可以使用变量扩展
  • branch 关键字指定项目中 project 指定的分支或标签的名称。您可以使用变量扩展。

使用 API 触发多项目流水线

您可以使用CI/CD 作业令牌 (CI_JOB_TOKEN)pipeline trigger API endpoint 从 CI/CD 作业内部触发多项目流水线。极狐GitLab将使用作业令牌触发的流水线设置为包含进行 API 调用的作业的流水线的下游流水线。

例如:

trigger_pipeline:
  stage: deploy
  script:
    - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
  rules:
    - if: $CI_COMMIT_TAG
  environment: production

查看下游流水线

流水线详情页面中,下游流水线显示为图表右侧的一组卡片。从此视图中,您可以:

  • 选择触发作业以查看触发的下游流水线的作业。
  • 在流水线卡片上选择 展开作业 {{< icon name=”chevron-lg-right” >}} 以展开视图,并显示下游流水线的作业。您一次可以查看一个下游流水线。
  • 将鼠标悬停在流水线卡片上,以突出显示触发下游流水线的作业。

重试下游流水线中失败和取消的作业

{{< history >}}

  • 从图形视图重试 在极狐GitLab 15.0 中引入,使用名为 downstream_retry_action功能标志。默认禁用。
  • 从图形视图重试 在极狐GitLab 15.1 中普遍可用并移除功能标志。

{{< /history >}}

要重试失败和取消的作业,请选择 重试 ({{< icon name=”retry” >}}):

  • 从下游流水线的详情页面。
  • 在流水线图形视图中的流水线卡片上。

重新创建下游流水线

{{< history >}}

  • 从图形视图重试触发作业 在极狐GitLab 15.10 中引入,使用名为 ci_recreate_downstream_pipeline功能标志。默认禁用。
  • 在极狐GitLab 15.11 中 GA。功能标志 ci_recreate_downstream_pipeline 被移除。

{{< /history >}}

您可以通过重试其对应的触发作业重新创建下游流水线。新创建的下游流水线将在流水线图中替换当前的下游流水线。

要重新创建下游流水线:

  • 在流水线图形视图中选择触发作业卡片上的 重新运行 ({{< icon name=”retry” >}})。

取消下游流水线

{{< history >}}

  • 从图形视图重试 在极狐GitLab 15.0 中引入,使用名为 downstream_retry_action功能标志。默认禁用。
  • 从图形视图重试 在极狐GitLab 15.1 中 GA 并移除功能标志 downstream_retry_action

{{< /history >}}

要取消仍在运行的下游流水线,请选择 取消 ({{< icon name=”cancel” >}}):

  • 从下游流水线的详情页面。
  • 在流水线图形视图中的流水线卡片上。

从下游流水线自动取消父流水线

您可以配置子流水线以自动取消,只要其作业之一失败。

只有在以下情况下,父流水线才会在子流水线中的作业失败时自动取消:

  • 父流水线也设置为在作业失败时自动取消。
  • 触发作业配置了 strategy: depend

例如:

  • .gitlab-ci.yml 的内容:

    workflow:
      auto_cancel:
        on_job_failure: all
    
    trigger_job:
      trigger:
        include: child-pipeline.yml
        strategy: depend
    
    job3:
      script:
        - sleep 120
    
  • child-pipeline.yml 的内容

    # child-pipeline.yml 的内容
    workflow:
      auto_cancel:
        on_job_failure: all
    
    job1:
      script: sleep 60
    
    job2:
      script:
        - sleep 30
        - exit 1
    

在此示例中:

  1. 父流水线同时触发子流水线和 job3
  2. 子流水线中的 job2 失败,子流水线被取消,停止 job1
  3. 子流水线已被取消,因此父流水线自动取消

在触发作业中镜像下游流水线的状态

您可以使用 strategy: depend 在触发作业中镜像下游流水线的状态:

{{< tabs >}}

{{< tab title=”Parent-child pipeline” >}}

trigger_job:
  trigger:
    include:
      - local: path/to/child-pipeline.yml
    strategy: depend

{{< /tab >}}

{{< tab title=”Multi-project pipeline” >}}

trigger_job:
  trigger:
    project: my/project
    strategy: depend

{{< /tab >}}

{{< /tabs >}}

在流水线图中查看多项目流水线

{{< history >}}

  • 在极狐GitLab 16.8 中,从专业版移至基础版。

{{< /history >}}

触发多项目流水线后,下游流水线显示在流水线图的右侧。

流水线迷你图中,下游流水线显示在迷你图的右侧。

从上游流水线获取产物

{{< details >}}

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

{{< /details >}}

{{< tabs >}}

{{< tab title=”Parent-child pipeline” >}}

使用 needs:pipeline:job 从上游流水线获取产物:

  1. 在上游流水线中,使用 artifacts 关键字在作业中保存产物,然后使用触发作业触发下游流水线:

    build_artifacts:
      stage: build
      script:
        - echo "这是一个测试产物!" >> artifact.txt
      artifacts:
        paths:
          - artifact.txt
    
    deploy:
      stage: deploy
      trigger:
        include:
          - local: path/to/child-pipeline.yml
      variables:
        PARENT_PIPELINE_ID: $CI_PIPELINE_ID
    
  2. 在下游流水线中的作业中使用 needs:pipeline:job 获取产物。

    test:
      stage: test
      script:
        - cat artifact.txt
      needs:
        - pipeline: $PARENT_PIPELINE_ID
          job: build_artifacts
    

    job 设置为上游流水线中创建产物的作业。

{{< /tab >}}

{{< tab title=”Multi-project pipeline” >}}

使用 needs:project 从上游流水线获取产物:

  1. 在极狐GitLab 15.9 及更高版本中,将下游项目添加到上游项目的作业令牌作用域白名单
  2. 在上游流水线中,使用 artifacts 关键字在作业中保存产物,然后使用触发作业触发下游流水线:

    build_artifacts:
      stage: build
      script:
        - echo "这是一个测试产物!" >> artifact.txt
      artifacts:
        paths:
          - artifact.txt
    
    deploy:
      stage: deploy
      trigger: my/downstream_project   # 触发流水线的项目路径
    
  3. 在下游流水线中的作业中使用 needs:project 获取产物。

    test:
      stage: test
      script:
        - cat artifact.txt
      needs:
        - project: my/upstream_project
          job: build_artifacts
          ref: main
          artifacts: true
    

    设置:

    • job 为上游流水线中创建产物的作业。
    • ref 为分支。
    • artifactstrue

{{< /tab >}}

{{< /tabs >}}

从上游合并请求流水线获取产物

当您使用 needs:project 将产物传递给下游流水线时,ref 值通常是分支名称,例如 maindevelopment

对于合并请求流水线ref 值的形式为 refs/merge-requests/<id>/head,其中 <id> 是合并请求 ID。您可以使用 CI_MERGE_REQUEST_REF_PATH CI/CD 变量检索此引用。不要在合并请求流水线中使用分支名称作为 ref,因为下游流水线会尝试从最新的分支流水线中获取产物。

要从上游 merge request 流水线而不是 branch 流水线获取产物,请使用变量继承CI_MERGE_REQUEST_REF_PATH 传递给下游流水线:

  1. 在极狐GitLab 15.9 及更高版本中,将下游项目添加到上游项目的作业令牌作用域白名单
  2. 在上游流水线中的作业中,使用 artifacts 关键字保存产物。
  3. 在触发下游流水线的作业中,传递 $CI_MERGE_REQUEST_REF_PATH 变量:

    build_artifacts:
      rules:
        - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
      stage: build
      script:
        - echo "这是一个测试产物!" >> artifact.txt
      artifacts:
        paths:
          - artifact.txt
    
    upstream_job:
      rules:
        - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
      variables:
        UPSTREAM_REF: $CI_MERGE_REQUEST_REF_PATH
      trigger:
        project: my/downstream_project
        branch: my-branch
    
  4. 在下游流水线中的作业中,使用 needs:project 和传递的变量作为 ref 从上游流水线获取产物:

    test:
      stage: test
      script:
        - cat artifact.txt
      needs:
        - project: my/upstream_project
          job: build_artifacts
          ref: $UPSTREAM_REF
          artifacts: true
    

您可以使用此方法从上游合并请求流水线获取产物,但不能从合并结果流水线获取。

将输入传递给下游流水线

您可以使用 inputs 关键字将输入值传递给下游流水线。与变量相比,输入提供了优势,包括类型检查、通过选项进行验证、描述和默认值。

首先,使用 spec:inputs 在目标配置文件中定义输入参数:

# 目标流水线配置
spec:
  inputs:
    environment:
      description: "部署环境"
      options: [staging, production]
    version:
      type: string
      description: "应用版本"

然后在触发流水线时提供值:

{{< tabs >}}

{{< tab title=”Parent-child pipeline” >}}

staging:
  trigger:
    include:
      - local: path/to/child-pipeline.yml
        inputs:
          environment: staging
          version: "1.0.0"

{{< /tab >}}

{{< tab title=”Multi-project pipeline” >}}

staging:
  trigger:
    project: my-group/my-deployment-project
    inputs:
      environment: staging
      version: "1.0.0"

{{< /tab >}}

{{< /tabs >}}

将 CI/CD 变量传递给下游流水线

您可以根据变量的创建或定义位置使用几种不同的方法将 CI/CD 变量 传递给下游流水线。

传递 YAML 定义的 CI/CD 变量

注意:建议在流水线配置中使用输入而不是变量,因为它们提供了更好的安全性和灵活性。

您可以使用 variables 关键字将 CI/CD 变量传递给下游流水线。这些变量是用于变量优先级的流水线变量。

例如:

{{< tabs >}}

{{< tab title=”Parent-child pipeline” >}}

variables:
  VERSION: "1.0.0"

staging:
  variables:
    ENVIRONMENT: staging
  stage: deploy
  trigger:
    include:
      - local: path/to/child-pipeline.yml

{{< /tab >}}

{{< tab title=”Multi-project pipeline” >}}

variables:
  VERSION: "1.0.0"

staging:
  variables:
    ENVIRONMENT: staging
  stage: deploy
  trigger: my-group/my-deployment-project

{{< /tab >}}

{{< /tabs >}}

ENVIRONMENT 变量在下游流水线中定义的每个作业中可用。

默认变量 VERSION 也在下游流水线中可用,因为流水线中的所有作业,包括触发作业,都继承默认 variables

防止默认变量被传递

您可以使用 inherit:variables 阻止默认 CI/CD 变量到达下游流水线。您可以列出要继承的特定变量,或阻止所有默认变量。

例如:

{{< tabs >}}

{{< tab title=”Parent-child pipeline” >}}

variables:
  DEFAULT_VAR: value

trigger-job:
  inherit:
    variables: false
  variables:
    JOB_VAR: value
  trigger:
    include:
      - local: path/to/child-pipeline.yml

{{< /tab >}}

{{< tab title=”Multi-project pipeline” >}}

variables:
  DEFAULT_VAR: value

trigger-job:
  inherit:
    variables: false
  variables:
    JOB_VAR: value
  trigger: my-group/my-project

{{< /tab >}}

{{< /tabs >}}

DEFAULT_VAR 变量在触发的流水线中不可用,但 JOB_VAR 是可用的。

传递预定义变量

要使用预定义 CI/CD 变量传递有关上游流水线的信息,请使用插值。在触发作业中将预定义变量保存为新的作业变量,该变量将传递给下游流水线。例如:

{{< tabs >}}

{{< tab title=”Parent-child pipeline” >}}

trigger-job:
  variables:
    PARENT_BRANCH: $CI_COMMIT_REF_NAME
  trigger:
    include:
      - local: path/to/child-pipeline.yml

{{< /tab >}}

{{< tab title=”Multi-project pipeline” >}}

trigger-job:
  variables:
    UPSTREAM_BRANCH: $CI_COMMIT_REF_NAME
  trigger: my-group/my-project

{{< /tab >}}

{{< /tabs >}}

UPSTREAM_BRANCH 变量包含上游流水线的 $CI_COMMIT_REF_NAME 预定义 CI/CD 变量的值,在下游流水线中可用。

不要使用此方法将遮罩变量传递给多项目流水线。CI/CD 遮罩配置不会传递给下游流水线,变量可能在下游项目的作业日志中未遮罩。

您不能使用此方法将仅限作业变量转发到下游流水线,因为它们在触发作业中不可用。

上游流水线优先于下游流水线。如果在上游和下游项目中定义了两个具有相同名称的变量,上游项目中定义的变量优先。

传递在作业中创建的 dotenv 变量

{{< details >}}

  • Tier: 专业版,旗舰版
  • Offering: JihuLab.com,极狐GitLab私有化部署,极狐GitLab专属

{{< /details >}}

您可以使用 dotenv 变量继承 将变量传递给下游流水线。

例如,在多项目流水线中:

  1. 将变量保存在 .env 文件中。
  2. .env 文件保存为 dotenv 报告。
  3. 触发下游流水线。

    build_vars:
      stage: build
      script:
        - echo "BUILD_VERSION=hello" >> build.env
      artifacts:
        reports:
          dotenv: build.env
    
    deploy:
      stage: deploy
      trigger: my/downstream_project
    
  4. 在下游流水线中的 test 作业中,使用 needs 继承上游项目中 build_vars 作业的变量。test 作业继承 dotenv 报告中的变量,并可以在脚本中访问 BUILD_VERSION

    test:
      stage: test
      script:
        - echo $BUILD_VERSION
      needs:
        - project: my/upstream_project
          job: build_vars
          ref: master
          artifacts: true
    

控制要转发到下游流水线的变量类型

使用 trigger:forward 关键字 指定要转发到下游流水线的变量类型。转发的变量被视为触发变量,具有最高优先级

用于部署的下游流水线

{{< history >}}

  • 在极狐GitLab 16.4 中引入。

{{< /history >}}

您可以在 trigger 中使用 environment。 如果您的部署和应用项目是分别管理的,您可能想要使用触发作业中的 environment

deploy:
  trigger:
    project: project-group/my-downstream-project
  environment: production

下游流水线可以在指定环境中配置基础设施、部署,并将部署状态返回给上游项目。

您可以从上游项目查看环境和部署

高级示例

此示例配置具有以下行为:

  • 上游项目根据分支名称动态组成环境名称。
  • 上游项目使用 UPSTREAM_* 变量将部署的上下文传递给下游项目。

上游项目中的 .gitlab-ci.yml

stages:
  - deploy
  - cleanup

.downstream-deployment-pipeline:
  variables:
    UPSTREAM_PROJECT_ID: $CI_PROJECT_ID
    UPSTREAM_ENVIRONMENT_NAME: $CI_ENVIRONMENT_NAME
    UPSTREAM_ENVIRONMENT_ACTION: $CI_ENVIRONMENT_ACTION
  trigger:
    project: project-group/deployment-project
    branch: main
    strategy: depend

deploy-review:
  stage: deploy
  extends: .downstream-deployment-pipeline
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    on_stop: stop-review

stop-review:
  stage: cleanup
  extends: .downstream-deployment-pipeline
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    action: stop
  when: manual

下游项目中的 .gitlab-ci.yml

deploy:
  script: echo "Deploy to ${UPSTREAM_ENVIRONMENT_NAME} for ${UPSTREAM_PROJECT_ID}"
  rules:
    - if: $CI_PIPELINE_SOURCE == "pipeline" && $UPSTREAM_ENVIRONMENT_ACTION == "start"

stop:
  script: echo "Stop ${UPSTREAM_ENVIRONMENT_NAME} for ${UPSTREAM_PROJECT_ID}"
  rules:
    - if: $CI_PIPELINE_SOURCE == "pipeline" && $UPSTREAM_ENVIRONMENT_ACTION == "stop"