下游流水线
- Tier: Free, Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
下游流水线是指由另一个流水线触发的任何 GitLab CI/CD 流水线。 下游流水线与触发它们的上游流水线独立运行且并发执行。
有时你可以使用父子流水线或多项目流水线来实现类似的目的,但它们存在关键差异。
默认情况下,一个流水线层次结构最多可包含 1000 个下游流水线。 有关此限制及其更改方法的信息,请参阅限制流水线层次结构大小。
父子流水线
父流水线是在同一项目中触发下游流水线的流水线。 下游流水线称为子流水线。
子流水线:
- 在与父流水线相同的项目、ref 和 commit SHA 下运行
- 不会直接影响流水线所针对 ref 的整体状态。例如,如果流水线在主分支上失败,通常会说"主分支已损坏"。只有当子流水线使用
trigger:strategy触发时,其状态才会影响 ref 的状态 - 如果为同一 ref 创建了新的流水线,并且流水线配置了
interruptible,则子流水线会自动取消 - 不会显示在项目的流水线列表中。你只能在父流水线的详情页面查看子流水线
嵌套子流水线
父子流水线的子流水线最大深度为两级。
父流水线可以触发许多子流水线,这些子流水线又可以触发自己的子流水线。你不能触发更高级别的子流水线。
有关概述,请参阅嵌套动态流水线。
多项目流水线
一个项目中的流水线可以触发另一个项目中的下游流水线,称为多项目流水线。 触发上游流水线的用户必须能够在下游项目中启动流水线,否则下游流水线启动失败。
多项目流水线:
- 从另一个项目的流水线触发,但上游(触发)流水线对下游(被触发)流水线没有太多控制权。不过,可以选择下游流水线的 ref,并向其传递 CI/CD 变量
- 影响其运行项目的 ref 的整体状态,但不影响触发流水线的 ref 的状态,除非它使用
trigger:strategy触发 - 当上游项目为同一 ref 运行新流水线时,不会在下游项目中自动取消使用 [
interruptible](../yaml/_index.md#interruptible)。如果下游项目为同一 ref 触发了新流水线,则可以自动取消 - 在下游项目的流水线列表中可见
- 是独立的,因此没有嵌套限制
如果你使用公共项目来触发私有项目中的下游流水线,请确保没有保密问题。上游项目的流水线页面始终显示:
- 下游项目的名称
- 流水线的状态
从 .gitlab-ci.yml 文件中的作业触发下游流水线
在 .gitlab-ci.yml 文件中使用 trigger 关键字创建触发下游流水线的作业。此作业称为触发作业。
例如:
trigger_job:
trigger:
include:
- local: path/to/child-pipeline.ymltrigger_job:
trigger:
project: project-group/my-downstream-project触发作业启动后,GitLab 尝试创建下游流水线时,作业的初始状态为 pending。如果下游流水线创建成功,触发作业显示 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 文件的工件必须在实例限制范围内。
有关概述,请参阅使用动态生成的配置创建子流水线。
有关生成动态子流水线的示例项目,请参阅使用 Jsonnet 的动态子流水线。
该项目展示了如何在运行时使用数据模板语言生成 .gitlab-ci.yml。你可以对其他模板语言(如 Dhall 或 ytt)使用类似的过程。
触发动态子流水线
要从动态生成的配置文件触发子流水线:
-
在作业中生成配置文件并将其保存为工件:
generate-config: stage: build script: generate-ci-config > generated-config.yml artifacts: paths: - generated-config.yml -
配置触发作业在生成配置文件的作业之后运行。设置
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 变量。问题 378717 提议修复此问题。
使用合并请求流水线运行子流水线
默认情况下,当不使用 rules 或 workflow:rules 时,流水线(包括子流水线)作为分支流水线运行。要配置子流水线在从合并请求(父)流水线触发时运行,请使用 rules 或 workflow:rules。例如,使用 rules:
-
设置父流水线的触发作业在合并请求上运行:
trigger-child-pipeline-job: trigger: include: path/to/child-pipeline-configuration.yml rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" -
使用
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/CD 作业令牌 (CI_JOB_TOKEN) 和流水线触发 API 端点来触发多项目流水线。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查看下游流水线
在流水线详情页面,下游流水线显示为图表右侧的卡片列表。从此视图,你可以:
- 选择触发作业以查看触发的下游流水线的作业
- 在流水线卡片上选择展开作业 以展开视图显示下游流水线的作业。你可以一次查看一个下游流水线
- 将鼠标悬停在流水线卡片上以高亮显示触发下游流水线的作业
重试下游流水线中失败和已取消的作业
要重试失败和已取消的作业,选择重试( ):
- 从下游流水线的详情页面
- 在流水线图表视图中从流水线卡片
重新创建下游流水线
你可以通过重试其对应的触发作业来重新创建下游流水线。新创建的下游流水线会替换流水线图表中的当前下游流水线。
要重新创建下游流水线:
- 在流水线图表视图中从触发作业的卡片上选择再次运行( )
取消下游流水线
要取消仍在运行的下游流水线,选择取消( ):
- 从下游流水的详情页面
- 在流水线图表视图中从流水线卡片
从下游流水线自动取消父流水线
你可以配置子流水线在其中一个作业失败时立即自动取消。
只有当以下条件满足时,父流水线才会因子流水线中的作业失败而自动取消:
- 父流水线也设置为在作业失败时自动取消
- 触发作业配置了
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
在此示例中:
- 父流水线同时触发子流水线和
job3 - 子流水线中的
job2失败,子流水线被取消,同时停止job1 - 子流水线已被取消,因此父流水线自动取消
在触发作业中镜像下游流水线的状态
你可以通过使用 strategy: mirror 在触发作业中镜像下游流水的状态:
trigger_job:
trigger:
include:
- local: path/to/child-pipeline.yml
strategy: mirrortrigger_job:
trigger:
project: my/project
strategy: mirror在流水线图表中查看多项目流水线
触发多项目流水线后,下游流水线显示在流水线图表的右侧。
在流水线迷你图表中,下游流水线显示在迷你图表的右侧。
从上游流水线获取工件
- Tier: Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
使用 needs:pipeline:job 从上游流水线获取工件:
-
在上游流水线中,使用
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 -
在下游流水线的作业中使用
needs:pipeline:job获取工件。test: stage: test script: - cat artifact.txt needs: - pipeline: $PARENT_PIPELINE_ID job: build_artifacts将
job设置为在上游流水线中创建工件的作业。
使用 needs:project 从上游流水线获取工件:
-
在 GitLab 15.9 及更高版本中,将下游项目添加到上游项目的作业令牌范围允许列表。
-
在上游流水线中,使用
artifacts关键字在作业中保存工件,然后使用触发作业触发下游流水线:build_artifacts: stage: build script: - echo "这是一个测试工件!" >> artifact.txt artifacts: paths: - artifact.txt deploy: stage: deploy trigger: my/downstream_project # 触发流水线的项目路径 -
在下游流水线的作业中使用
needs:project获取工件。test: stage: test script: - cat artifact.txt needs: - project: my/upstream_project job: build_artifacts ref: main artifacts: true设置:
job为在上游流水线中创建工件的作业ref为分支名称artifacts为true
从上游合并请求流水线获取工件
当你使用 needs:project 将工件传递到下游流水线时,ref 值通常是分支名称,如 main 或 development。
对于合并请求流水线,ref 值的形式为 refs/merge-requests/<id>/head,其中 id 是合并请求 ID。你可以使用 CI_MERGE_REQUEST_REF_PATH CI/CD 变量检索此 ref。不要将分支名称用作合并请求流水线的 ref,因为下游流水线会尝试从最新的分支流水线获取工件。
要从上游 merge request 流水线而不是 branch 流水线获取工件,使用变量继承将 CI_MERGE_REQUEST_REF_PATH 传递到下游流水线:
-
在 GitLab 15.9 及更高版本中,将下游项目添加到上游项目的作业令牌范围允许列表。
-
在上游流水线的一个作业中,使用
artifacts关键字保存工件。 -
在触发下游流水的作业中,传递
$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 -
在下游流水的作业中,使用
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: "应用程序版本"然后在触发流水线时提供值:
staging:
trigger:
include:
- local: path/to/child-pipeline.yml
inputs:
environment: staging
version: "1.0.0"staging:
trigger:
project: my-group/my-deployment-project
inputs:
environment: staging
version: "1.0.0"向下游流水线传递 CI/CD 变量
你可以使用几种不同的方法将 CI/CD 变量 传递到下游流水线,具体取决于变量创建或定义的位置。
传递 YAML 定义的 CI/CD 变量
注意:建议使用输入而不是变量进行流水线配置,因为它们提供更好的安全性和灵活性。
你可以使用 variables 关键字将 CI/CD 变量传递到下游流水线。这些变量是变量优先级的流水线变量。
例如:
variables:
VERSION: "1.0.0"
staging:
variables:
ENVIRONMENT: staging
stage: deploy
trigger:
include:
- local: path/to/child-pipeline.ymlvariables:
VERSION: "1.0.0"
staging:
variables:
ENVIRONMENT: staging
stage: deploy
trigger: my-group/my-deployment-projectENVIRONMENT 变量在下游流水线中定义的每个作业中都可用。
VERSION 默认变量也可用于下游流水线,因为流水线中的所有作业(包括触发作业)都继承默认 variables。
阻止默认变量被传递
你可以使用 inherit:variables 阻止默认 CI/CD 变量到达下游流水线。你可以列出要继承的特定变量,或阻止所有默认变量。
例如:
variables:
DEFAULT_VAR: value
trigger-job:
inherit:
variables: false
variables:
JOB_VAR: value
trigger:
include:
- local: path/to/child-pipeline.ymlvariables:
DEFAULT_VAR: value
trigger-job:
inherit:
variables: false
variables:
JOB_VAR: value
trigger: my-group/my-projectDEFAULT_VAR 变量在触发的流水线中不可用,但 JOB_VAR 可用。
传递预定义变量
要使用预定义 CI/CD 变量传递关于上游流水线的信息,请使用插值。将预定义变量保存为触发作业中的新作业变量,该变量会传递到下游流水线。例如:
trigger-job:
variables:
PARENT_BRANCH: $CI_COMMIT_REF_NAME
trigger:
include:
- local: path/to/child-pipeline.ymltrigger-job:
variables:
UPSTREAM_BRANCH: $CI_COMMIT_REF_NAME
trigger: my-group/my-projectUPSTREAM_BRANCH 变量(包含上游流水线 $CI_COMMIT_REF_NAME 预定义 CI/CD 变量的值)在下游流水线中可用。
不要使用此方法将屏蔽变量传递到多项目流水线。CI/CD 屏蔽配置不会传递到下游流水线,并且变量可能在下游项目的作业日志中被取消屏蔽。
你不能使用此方法将仅作业变量转发到下游流水线,因为它们在触发作业中不可用。
上游流水线优先于下游流水线。如果在上游和下游项目中都定义了两个同名变量,则上游项目中定义的变量优先。
传递在作业中创建的 dotenv 变量
- Tier: Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
你可以使用 dotenv 变量继承将变量传递到下游流水线。
例如,在多项目流水线中:
-
将变量保存在
.env文件中 -
将
.env文件保存为dotenv报告 -
触发下游流水线
build_vars: stage: build script: - echo "BUILD_VERSION=hello" >> build.env artifacts: reports: dotenv: build.env deploy: stage: deploy trigger: my/downstream_project -
设置下游流水线中的
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 关键字指定转发到下游流水的变量类型。转发的变量被视为触发变量,具有最高优先级。
用于部署的下游流水线
你可以将 environment 关键字与 trigger 一起使用。如果你的部署和应用项目是单独管理的,你可能希望从触发作业使用 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: mirror
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 "为 ${UPSTREAM_PROJECT_ID} 部署到 ${UPSTREAM_ENVIRONMENT_NAME}"
rules:
- if: $CI_PIPELINE_SOURCE == "pipeline" && $UPSTREAM_ENVIRONMENT_ACTION == "start"
stop:
script: echo "为 ${UPSTREAM_PROJECT_ID} 停止 ${UPSTREAM_ENVIRONMENT_NAME}"
rules:
- if: $CI_PIPELINE_SOURCE == "pipeline" && $UPSTREAM_ENVIRONMENT_ACTION == "stop"