- 父子流水线
- 多项目流水线
-
从
.gitlab-ci.yml
文件中的作业触发下游流水线 - 查看下游流水线
- 从上游流水线获取产物 (PREMIUM ALL)
- 将 CI/CD 变量传递到下游流水线
- 部署的下游流水线
- 故障排除
下游流水线 (BASIC ALL)
下游流水线是由另一个流水线触发的任何极狐GitLab CI/CD 流水线。 下游流水线独立运行,并且与触发它们的上游流水线同时运行。
父子流水线和多项目流水线有时可用于类似目的,但存在一些关键差异。
父子流水线
父流水线是在同一项目中触发下游流水线的流水线。 下游流水线称为子流水线。
子流水线:
- 在与父流水线相同的项目、ref 和提交 SHA 下运行。
- 不直接影响流水线运行相关的 ref 的整体状态。例如,
如果主分支的流水线出现故障,通常会说“主分支已损坏”。
如果子流水线由
strategy:depend
触发,子流水线的状态只影响 ref 的状态。 - 当为同一 ref 创建新流水线时,如果使用
interruptible
配置流水线,则自动取消。 - 不显示在项目的流水线列表中。您只能在其父流水线的详情页面查看子流水线。
嵌套子流水线
- 引入于极狐GitLab 13.4。
- 功能标志移除于极狐GitLab 13.5。
父子流水线的最大深度为两级子流水线。
一个父流水线可以触发多个子流水线,这些子流水线又可以触发自己的子流水线。您不能触发另一级别的子流水线。
多项目流水线
一个项目中的流水线可以触发另一个项目中的下游流水线,称为多项目流水线。触发上游流水线的用户必须能够启动下游项目中的流水线,否则下游流水线无法启动。
多项目流水线:
- 从另一个流水线触发,但上游(触发)流水线对下游(被触发)流水线没有太多控制。但是,它可以选择下游流水线的 ref,并将 CI/CD 变量传递给它。
- 影响它运行的项目的 ref 的整体状态,但不影响触发流水线的 ref 的状态,除非用
strategy:depend
。 - 如果在上游流水线中为相同的 ref 运行新流水线,则在使用
interruptible
时不会在下游项目中自动取消。如果为下游项目上的相同 ref 触发了新流水线,它们可以自动取消。 - 在下游项目的流水线列表中可见。
- 是独立的,因此没有嵌套限制。
如果您使用公共项目来触发私有项目中的下游流水线,请确保不存在保密问题。上游项目的流水线页面始终显示:
- 下游项目的名称。
- 流水线的状态。
从 .gitlab-ci.yml
文件中的作业触发下游流水线
在 .gitlab-ci.yml
文件中使用 trigger
关键字来创建触发下游流水线的作业。该作业称为触发作业。
例如:
::Tabs
:::TabTitle 父子流水线
trigger_job:
trigger:
include:
- local: path/to/child-pipeline.yml
:::TabTitle 多项目流水线
trigger_job:
trigger:
project: project-group/my-downstream-project
::EndTabs
触发作业启动后,当极狐GitLab 尝试创建下游流水线时,作业的初始状态为 pending
。如果下游流水线创建成功,则触发器作业显示 passed
,否则显示 failed
。或者,您可以设置触发作业显示下游流水线的状态。
使用 rules
控制下游流水线作业
在下游流水线中使用 CI/CD 变量或 rules
关键字来控制作业行为。
当您使用 trigger
关键字触发下游流水线时,适用于所有作业的 $CI_PIPELINE_SOURCE
预定义变量的值是:
- 多项目流水线:
pipeline
。 - 父子流水线:
parent_pipeline
。
例如,要在同时运行合并请求流水线的项目中,控制多项目流水线中的作业:
job1:
rules:
- if: $CI_PIPELINE_SOURCE == "pipeline"
script: echo "This job runs in multi-project pipelines only"
job2:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script: echo "This job runs in merge request pipelines only"
job3:
rules:
- if: $CI_PIPELINE_SOURCE == "pipeline"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script: echo "This job runs in both multi-project and merge request pipelines"
在不同的项目中使用子流水线配置文件
引入于极狐GitLab 13.5。
您可以在触发器作业中,使用 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: Security/SAST.gitlab-ci.yml
- project: 'my-group/my-pipeline-library'
ref: 'main'
file: '/path/to/child-pipeline.yml'
动态子流水线
您可以从作业中生成的 YAML 文件而不是项目中保存的静态文件触发子流水线。这种技术对于生成针对已更改内容的流水线或构建目标和体系结构矩阵非常强大。
包含生成的 YAML 文件的产物不得大于 5MB。
有关生成动态子流水线的项目示例,请参阅使用 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 配置,如脚本,使用 \
。
使用合并请求流水线运行子流水线
当不使用 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 "This child pipeline job runs any time the parent pipeline triggers it." rules: - if: $CI_PIPELINE_SOURCE == "parent_pipeline" job2: script: echo "This child pipeline job runs only when the parent pipeline is a merge request pipeline" 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
使用:
使用 API 触发多项目流水线
您可以将 CI/CD 作业令牌(CI_JOB_TOKEN
)与流水线触发器 API 端点,从 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
查看下游流水线
在流水线图视图中,下游流水线显示为图表右侧的卡片列表。在此视图中,您可以:
- 选择一个触发作业,查看触发的下游流水线的作业。
- 在流水线选项卡上选择 展开作业 ,展开包含下游流水线作业的视图。您一次可以查看一个下游流水线。
- 将鼠标悬停在流水线选项卡上,突出显示触发下游流水线的作业。
重试下游流水线中失败和取消的作业
- 从图表视图重试功能引入于 15.0 版本,功能标志为
downstream_retry_action
。默认禁用。- 从图表视图重试功能一般可用于 15.1 版本。功能标志删除。
要重试失败的和取消的作业,请选择 重试 ():
- 从下游流水线的详细信息页面。
- 在流水线图视图中的流水线选项卡上。
重新创建下游流水线
- 从流水线图视图重试触发作业功能引入于 15.10 版本,功能标志为
ci_recreate_downstream_pipeline
。默认禁用。- 一般可用于 15.11 版本,删除功能标志
ci_recreate_downstream_pipeline
。
您可以通过重试相应的触发作业来重新创建下游流水线。新创建的下游流水线将替换流水线图中当前的下游流水线。
要重新创建下游流水线:
- 在流水线图视图中的触发作业卡上选择 再次运行 ()。
取消下游流水线
- 从图表视图重试引入于极狐GitLab 15.0,功能标志为
downstream_retry_action
。默认禁用。- 从图表视图重试普遍可用并移除功能标志于极狐GitLab 15.1。
要取消仍在运行的下游流水线,请选择 取消 ():
- 从下游流水线的详细信息页面。
- 在流水线图视图中的流水线卡上。
在触发器作业中镜像下游流水线的状态
您可以使用 strategy: depend
在触发器作业中镜像下游流水线的状态:
::Tabs
:::TabTitle 父子流水线
trigger_job:
trigger:
include:
- local: path/to/child-pipeline.yml
strategy: depend
:::TabTitle 多项目流水线
trigger_job:
trigger:
project: my/project
strategy: depend
::EndTabs
在流水线图中查看多项目流水线 (PREMIUM ALL)
当您触发多项目流水线时,下游流水线会显示在流水线图的右侧。
在流水线迷你图中,下游流水线显示在迷你图的右侧。
从上游流水线获取产物 (PREMIUM ALL)
::Tabs
:::TabTitle 父子流水线
使用 needs:project
从上游流水线获取产物:
-
在上游流水线中,使用
artifacts
关键字将产物保存在作业中,然后使用触发器作业触发下游流水线:build_artifacts: stage: build script: - echo "This is a test artifact!" >> 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:project
来获取产物。test: stage: test script: - cat artifact.txt needs: - pipeline: $PARENT_PIPELINE_ID job: build_artifacts
将
job
设置为创建产物的上游流水线中的作业。
:::TabTitle 多项目流水线
使用 needs:project
从上游流水线获取产物:
- 在 15.9 及更高版本中,将下游项目添加到上游项目的作业令牌范围许可列表中。
-
在上游流水线中,将产物保存到带有
artifacts
关键字的作业中,然后触发带有触发作业的下游流水线:build_artifacts: stage: build script: - echo "This is a test artifact!" >> artifact.txt artifacts: paths: - artifact.txt deploy: stage: deploy trigger: my/downstream_project # Path to the project to trigger a pipeline in
-
使用下游流水线中的作业中的
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
。
- 将
::EndTabs
从上游合并请求流水线中获取产物
当您使用 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
传递给下游流水线:
- 在 15.9 及更高版本中,将下游项目添加到上游项目的作业令牌范围许可列表中 。
- 在上游流水线的作业中,使用
artifacts
关键字保存产物。 -
在触发下游流水线的作业中,传递
$CI_MERGE_REQUEST_REF_PATH
变量:build_artifacts: rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' stage: build script: - echo "This is a test artifact!" >> 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
您可以使用此方法从上游合并请求流水线中获取产物,但不能从合并结果流水线中获取产物。
将 CI/CD 变量传递到下游流水线
您可以根据创建或定义变量的位置,使用几种不同的方法将 CI/CD 变量传递到下游流水线。
传递 YAML 定义的 CI/CD 变量
您可以使用 variables
关键字将 CI/CD 变量传递到下游流水线。这些变量是变量优先级的”触发变量”。
例如:
::Tabs
:::TabTitle 父子流水线
variables:
VERSION: "1.0.0"
staging:
variables:
ENVIRONMENT: staging
stage: deploy
trigger:
include:
- local: path/to/child-pipeline.yml
:::TabTitle 多项目流水线
variables:
VERSION: "1.0.0"
staging:
variables:
ENVIRONMENT: staging
stage: deploy
trigger: my-group/my-deployment-project
::EndTabs
ENVIRONMENT
变量在下游流水线中定义的每个作业中都可用。
VERSION
全局变量在下游流水线中也可用,因为流水线中的所有作业(包括触发器作业)都会继承全局 variables
。
防止全局变量被传递
您可以使用 inherit:variables:false
阻止全局 CI/CD 变量到达下游流水线。
例如:
::Tabs
:::TabTitle 父子流水线
variables:
GLOBAL_VAR: value
trigger-job:
inherit:
variables: false
variables:
JOB_VAR: value
trigger:
include:
- local: path/to/child-pipeline.yml
:::TabTitle 多项目流水线
variables:
GLOBAL_VAR: value
trigger-job:
inherit:
variables: false
variables:
JOB_VAR: value
trigger: my-group/my-project
::EndTabs
在此示例中,GLOBAL_VAR
变量在触发流水线中不可用,但 JOB_VAR
可用。
传递一个预定义的变量
使用预定义的 CI/CD 变量传递有关上游流水线的信息,使用插值。将预定义变量保存为触发作业中的新作业变量,传递给下游流水线。
::Tabs
:::TabTitle 父子流水线
trigger-job:
variables:
PARENT_BRANCH: $CI_COMMIT_REF_NAME
trigger:
include:
- local: path/to/child-pipeline.yml
:::TabTitle 多项目流水线
trigger-job:
variables:
UPSTREAM_BRANCH: $CI_COMMIT_REF_NAME
trigger: my-group/my-project
::EndTabs
包含上游流水线的 $CI_COMMIT_REF_NAME
预定义 CI/CD 变量值的 UPSTREAM_BRANCH
变量在下游流水线中可用。
不要使用此方法将隐藏的变量传递到多项目流水线。CI/CD 隐藏配置不会传递到下游流水线,变量可能会在下游项目的作业日志中被取消隐藏。
您不能使用此方法将作业级持久变量转发到下游流水线,因为它们在触发器作业中不可用。
上游流水线优先于下游流水线。如果在上游和下游项目中定义了两个同名变量,则上游项目中定义的变量优先。
传递作业中创建的 dotenv 变量 (PREMIUM ALL)
您可以使用 dotenv
变量继承 和 needs:project
将变量传递到下游的作业。这些变量仅在作业脚本中可用,不能用于配置它,例如使用 rules
或 artifact:paths
。
例如,在多项目流水线中:
- 将变量保存在
.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
关键字指定要转发到下游流水线的变量类型。转发的变量被视为触发流水线,具有最高优先级。
部署的下游流水线
引入于极狐GitLab 16.4。
您可以将 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: 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"
故障排除
触发作业失败并且不创建多项目流水线
对于多项目流水线,如果出现以下情况,触发器作业将失败并且不会创建下游流水线:
- 未找到下游项目。
- 创建上游流水线的用户没有在下游项目中创建流水线的权限。
- 下游流水线以受保护分支为目标,并且用户无权针对受保护分支运行流水线。有关更多信息,请参阅受保护分支的流水线安全性。
流水线运行时不创建子流水线中的作业
如果父流水线是合并请求流水线,则子流水线必须使用 workflow:rules
或 rules
以确保作业运行。
如果由于 rules
配置缺失或不正确,子流水线中的作业无法运行:
- 子流水线无法启动。
- 父流水线的触发器作业失败并显示
downstream pipeline can not be created, Pipeline will not run for the selected trigger. The rules configuration prevented any jobs from being added to the pipeline.
。
Ref is ambiguous
当存在同名分支时,您无法使用标签触发多项目流水线。下游流水线无法创建,并出现错误 downstream pipeline can not be created, Ref is ambiguous
。
仅触发标签名称与分支名称不匹配的多项目流水线。
从上游流水线下载作业产物时出现 403 Forbidden
错误
在 15.9 及更高版本中,CI/CD 作业令牌的范围仅限于执行流水线的项目。因此,下游流水线中的作业令牌默认无法访问上游项目。
要解决此问题,将下游项目添加到作业令牌范围许可列表。