info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
For an overview, see [Nested Dynamic Pipelines](https://youtu.be/C5j3ju9je2M).
## Multi-project pipelines
A pipeline in one project can trigger downstream pipelines in another project,
called multi-project pipelines. The user triggering the upstream pipeline must be able to
start pipelines in the downstream project, otherwise [the downstream pipeline fails to start](#trigger-job-fails-and-does-not-create-multi-project-pipeline).
For example, you might deploy your web application from three different GitLab projects.
With multi-project pipelines you can trigger a pipeline in each project, where each
has its own build, test, and deploy process. You can visualize the connected pipelines
in one place, including all cross-project interdependencies.
> - Retry from graph view [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/354974) in GitLab 15.0 [with a flag](../../administration/feature_flags.md) named `downstream_retry_action`. Disabled by default.
> - Retry from graph view [generally available and feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/357406) in GitLab 15.1.
To retry a completed downstream pipeline, select **Retry** (**{retry}**):
- From the downstream pipeline's details page.
- On the pipeline's card in the [pipeline graph view](index.md#view-full-pipeline-graph).
### Cancel a downstream pipeline
> - Retry from graph view [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/354974) in GitLab 15.0 [with a flag](../../administration/feature_flags.md) named `downstream_retry_action`. Disabled by default.
> - Retry from graph view [generally available and feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/357406) in GitLab 15.1.
To cancel a downstream pipeline that is still running, select **Cancel** (**{cancel}**):
- From the downstream pipeline's details page.
- On the pipeline's card in the [pipeline graph view](index.md#view-full-pipeline-graph).
### Mirror the status of a downstream pipeline in the trigger job
You can mirror the pipeline status from the triggered pipeline to the source trigger job
by using [`strategy: depend`](../yaml/index.md#triggerstrategy):
::Tabs
:::TabTitle Multi-project pipeline
```yaml
trigger_job:
trigger:
project: my/project
strategy: depend
```
:::TabTitle Parent-child pipeline
```yaml
trigger_job:
trigger:
include:
- local: path/to/child-pipeline.yml
strategy: depend
```
::EndTabs
### View multi-project pipelines in pipeline graphs **(PREMIUM)**
When you trigger a multi-project pipeline, the downstream pipeline displays
to the right of the [pipeline graph](index.md#visualize-pipelines).
In [pipeline mini graphs](index.md#pipeline-mini-graphs), the downstream pipeline
displays to the right of the mini graph.
![Multi-project pipeline mini graph](img/pipeline_mini_graph_v15_0.png)
## Pass artifacts to a downstream pipeline
You can pass artifacts to a downstream pipeline by using [`needs:project`](../yaml/index.md#needsproject).
1. In a job in the upstream pipeline, save the artifacts using the [`artifacts`](../yaml/index.md#artifacts) keyword.
1. Trigger the downstream pipeline with a trigger job:
```yaml
build_artifacts:
stage: build
script:
- echo "This is a test artifact!" >> artifact.txt
artifacts:
paths:
- artifact.txt
deploy:
stage: deploy
trigger: my/downstream_project
```
1. In a job in the downstream pipeline, fetch the artifacts from the upstream pipeline
by using `needs:project`. Set `job` to the job in the upstream pipeline to fetch artifacts from,
`ref` to the branch, and `artifacts: true`.
```yaml
test:
stage: test
script:
- cat artifact.txt
needs:
- project: my/upstream_project
job: build_artifacts
ref: main
artifacts: true
```
### Pass artifacts from a Merge Request pipeline
When you use `needs:project` to [pass artifacts to a downstream pipeline](#pass-artifacts-to-a-downstream-pipeline),
the `ref` value is usually a branch name, like `main` or `development`.
For merge request pipelines, the `ref` value is in the form of `refs/merge-requests/<id>/head`,
where `id` is the merge request ID. You can retrieve this ref with the [`CI_MERGE_REQUEST_REF_PATH`](../variables/predefined_variables.md#predefined-variables-for-merge-request-pipelines)
CI/CD variable. Do not use a branch name as the `ref` with merge request pipelines,
because the downstream pipeline attempts to fetch artifacts from the latest branch pipeline.
To fetch the artifacts from the upstream `merge request` pipeline instead of the `branch` pipeline,
pass this variable to the downstream pipeline using variable inheritance:
1. In a job in the upstream pipeline, save the artifacts using the [`artifacts`](../yaml/index.md#artifacts) keyword.
1. In the job that triggers the downstream pipeline, pass the `$CI_MERGE_REQUEST_REF_PATH` variable by using
You can stop global variables from reaching the downstream pipeline by using the [`inherit:variables` keyword](../yaml/index.md#inheritvariables).
For example, in a [multi-project pipeline](#multi-project-pipelines):
```yaml
variables:
MY_GLOBAL_VAR: value
trigger-downstream:
inherit:
variables: false
variables:
MY_LOCAL_VAR: value
trigger: my/project
```
In this example, the `MY_GLOBAL_VAR` variable is not available in the triggered pipeline.
### Pass a predefined variable
You might want to pass some information about the upstream pipeline using predefined variables.
To do that, you can use interpolation to pass any variable. For example,
in a [multi-project pipeline](#multi-project-pipelines):
```yaml
downstream-job:
variables:
UPSTREAM_BRANCH: $CI_COMMIT_REF_NAME
trigger: my/project
```
In this scenario, the `UPSTREAM_BRANCH` variable with the value of the upstream pipeline's
`$CI_COMMIT_REF_NAME` is passed to `downstream-job`. It is available in the
context of all downstream builds.
You cannot use this method to forward [job-level persisted variables](../variables/where_variables_can_be_used.md#persisted-variables)
to a downstream pipeline, as they are not available in trigger jobs.
Upstream pipelines take precedence over downstream ones. If there are two
variables with the same name defined in both upstream and downstream projects,
the ones defined in the upstream project take precedence.
### Pass dotenv variables created in a job **(PREMIUM)**
You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](../variables/index.md#pass-an-environment-variable-to-another-job)
and [`needs:project`](../yaml/index.md#needsproject).
For example, in a [multi-project pipeline](#multi-project-pipelines):
1. Save the variables in a `.env` file.
1. Save the `.env` file as a `dotenv` report.
1. Trigger the downstream pipeline.
```yaml
build_vars:
stage: build
script:
- echo "BUILD_VERSION=hello" >> build.env
artifacts:
reports:
dotenv: build.env
deploy:
stage: deploy
trigger: my/downstream_project
```
1. Set the `test` job in the downstream pipeline to inherit the variables from the `build_vars`
job in the upstream project with `needs`. The `test` job inherits the variables in the
`dotenv` report and it can access `BUILD_VERSION` in the script: