DevOpsLesson
DevOpsLesson

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Stay Updated

Get notified about new tutorials and features.

Tutorials

  • What is DevOps?
  • Docker Tutorial
  • Terraform Tutorial
  • CI/CD Pipeline
  • All Tutorials

Roadmaps

  • DevOps Engineer
  • Cloud Engineer
  • SRE Path
  • All Roadmaps

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 DevOpsLesson. All rights reserved.

DOCKERKUBERNETESTERRAFORMAWSCI/CDLINUXGITDEVOPS ROADMAPCLOUD ROADMAPSRE ROADMAPGIT CHEATSHEETDOCKER CHEATSHEETK8S CHEATSHEETTF CHEATSHEETLINUX CHEATSHEETDOCKERFILE LINTERYAML VALIDATORCRON PARSERREGEX TESTER

Cicd Tutorial

Introduction to CI/CD
Getting Started with GitLab CI/CD
Stages, Jobs, Artifacts & Cache
Variables, Secrets and Environments in GitLab CI
GitLab Runners
GitLab CI Pipeline Rules
GitLab CI Environments
GitLab CI Docker Workflows
GitLab CI Testing
GitLab CI Security Scanning
GitLab CI Deploy to AWS
GitLab CI Multi-Project Pipelines
GitLab CI Best Practices

GitLab CI Multi-Project Pipelines

PreviousPrev
Next

Learn GitLab multi-project pipelines, downstream triggers, child pipelines, include strategies, trigger API usage, dynamic child pipelines, and cross-project dependencies in GitLab CI/CD.

As GitLab CI/CD usage grows, a single .gitlab-ci.yml file often stops being enough. Teams split systems into multiple repositories, create shared pipeline libraries, isolate deployment logic, or manage monorepos with many independently deployable parts. That is where GitLab multi-project pipelines and child pipelines become essential.

Instead of putting every job into one giant pipeline, GitLab lets one pipeline trigger another. This makes it possible to compose delivery flows across projects, share pipeline logic cleanly, and keep CI configuration maintainable even as your platform grows.

The key idea is simple: an upstream pipeline can trigger a downstream pipeline. That downstream pipeline might live in the same project as a child pipeline or in a different repository as a multi-project pipeline.

What Are Multi-Project Pipelines and Why Use Them?

A multi-project pipeline is a pipeline in one GitLab project that triggers a pipeline in another project. This is useful when delivery spans multiple repositories.

Common reasons to use GitLab multi-project pipelines include:

  • microservices where each service has its own repository and pipeline
  • a frontend project that triggers a backend integration or deployment pipeline
  • a shared platform or deployment repository used by many apps
  • centralized compliance or security pipeline logic
  • teams that want repository ownership boundaries without giving up orchestration

There is also a related concept: parent-child pipelines. These live in the same project and are often used to break a large pipeline into smaller, focused pieces.

In practice:

  • use child pipelines to split one repository’s CI configuration
  • use multi-project pipelines when orchestration crosses repository boundaries

Triggering a Downstream Pipeline with the trigger Keyword

The core feature is the trigger keyword.

A simple multi-project trigger looks like this:

deploy_platform:
  stage: deploy
  trigger:
    project: my-group/platform-deploy
    branch: main

When this job runs, GitLab starts a downstream pipeline in my-group/platform-deploy on the specified branch.

A parent-child trigger in the same project looks like this:

service_a_child:
  stage: test
  trigger:
    include:
      - local: .gitlab/child-service-a.yml

This is ideal when the root pipeline should stay small while service-specific logic lives in separate files.

Passing Variables to Downstream Pipelines

Real pipeline orchestration almost always needs context. The upstream pipeline may need to tell the downstream pipeline which image tag to deploy, which environment to use, or which feature flag to enable.

GitLab allows you to pass variables with the trigger job:

deploy_backend:
  stage: deploy
  trigger:
    project: my-group/backend-deploy
    branch: main
  variables:
    APP_VERSION: $CI_COMMIT_SHA
    TARGET_ENV: staging
    UPSTREAM_PROJECT: $CI_PROJECT_PATH

This pattern is powerful because it keeps downstream pipelines reusable. Instead of hardcoding behavior, the downstream project receives inputs and acts on them.

Typical passed variables include:

  • image tag or commit SHA
  • environment name
  • service name
  • region or cluster identifier
  • feature flags
  • release metadata

strategy: depend vs strategy: mirror

By default, a trigger job mainly confirms that the downstream pipeline was created successfully. In many real workflows, that is not enough. You often want the upstream pipeline to reflect the downstream outcome too.

That is where trigger strategy matters.

strategy: depend

Use strategy: depend when the upstream trigger job should wait for the downstream pipeline result and treat that result as meaningful for the current pipeline.

deploy_backend:
  stage: deploy
  trigger:
    project: my-group/backend-deploy
    branch: main
    strategy: depend

This is a common choice when the upstream pipeline should not report success unless the downstream deployment or test pipeline also succeeds.

strategy: mirror

strategy: mirror is used when you want the trigger job to closely reflect downstream pipeline status behavior in the GitLab UI, which can make complex orchestration easier to read. Teams often choose between depend and mirror based on how strictly they want upstream status to gate the broader workflow and on the exact behavior supported by their GitLab version.

orchestrate_release:
  stage: deploy
  trigger:
    project: my-group/release-pipeline
    branch: main
    strategy: mirror

A practical rule of thumb is:

  • choose depend for strict gating
  • choose mirror when you want the trigger job to act more like a direct status reflection of the downstream pipeline in the UI

Child Pipelines with include

A child pipeline is a downstream pipeline that runs in the same project, on the same ref and commit SHA as the parent pipeline. Child pipelines are excellent for large monorepos and large CI definitions.

Example:

frontend_pipeline:
  stage: test
  trigger:
    include:
      - local: .gitlab/frontend.yml

backend_pipeline:
  stage: test
  trigger:
    include:
      - local: .gitlab/backend.yml

This lets you split a large root file into smaller logical units while keeping everything in one repository.

Benefits of child pipelines:

  • smaller root CI file
  • clearer ownership boundaries
  • easier reuse of patterns
  • better readability for monorepos

The include Keyword: Local, Remote, Template, Project

The include keyword is broader than child pipelines. It is one of the most important GitLab CI composition tools.

GitLab supports several include sources.

local

Use a file from the same repository.

include:
  - local: .gitlab/common.yml

remote

Use a YAML file from a remote URL.

include:
  - remote: https://example.com/gitlab/common-pipeline.yml

template

Use a built-in GitLab template.

include:
  - template: Security/SAST.gitlab-ci.yml

project

Use a file from another GitLab project.

include:
  - project: my-group/pipeline-library
    ref: main
    file: /templates/node.yml

This is a strong pattern for platform teams that want to publish reusable CI templates to many application repositories.

Dynamic Child Pipelines

Static pipeline files are useful, but sometimes the pipeline should be generated at runtime. This is where dynamic child pipelines come in.

A dynamic child pipeline is created from a YAML file produced by an earlier job. This is especially useful when:

  • only changed services should run
  • you want to generate a test matrix dynamically
  • the pipeline structure depends on repository content
  • monorepo services are discovered automatically

Example:

generate_child_config:
  stage: build
  script:
    - python scripts/generate_pipeline.py > generated-child.yml
  artifacts:
    paths:
      - generated-child.yml

run_generated_pipeline:
  stage: test
  trigger:
    include:
      - artifact: generated-child.yml
        job: generate_child_config

This pattern makes GitLab CI much more flexible. Instead of maintaining a giant handwritten matrix, you can let the repository state drive the child pipeline definition.

Cross-Project Pipeline Dependencies with needs:project

Sometimes a pipeline does not need to trigger another one. It just needs to consume an artifact produced in another project. That is where needs:project becomes useful.

Example:

integration_tests:
  stage: test
  needs:
    - project: my-group/shared-library
      job: build_package
      ref: main
      artifacts: true
  script:
    - ls -la
    - ./run-integration-tests.sh

This allows a job to fetch artifacts from a different project’s pipeline. It is helpful when:

  • a shared library publishes build outputs
  • a central pipeline produces a deployable bundle
  • one repository depends on generated files from another

This is more efficient than copying files manually or rebuilding the same artifact everywhere.

Triggering Pipelines with the Trigger API

GitLab also lets you start pipelines over HTTP using the pipeline trigger API. This is useful for external orchestration, scheduled systems, or scripted integration from another CI job.

A basic curl example looks like this:

curl --request POST   --form token=$CI_JOB_TOKEN   --form ref=main   --url "https://gitlab.example.com/api/v4/projects/42/trigger/pipeline"

You can also pass variables:

curl --request POST   --form token=$CI_JOB_TOKEN   --form ref=main   --form "variables[IMAGE_TAG]=$CI_COMMIT_SHA"   --form "variables[TARGET_ENV]=staging"   --url "https://gitlab.example.com/api/v4/projects/42/trigger/pipeline"

This is useful when a job needs to trigger a downstream pipeline conditionally or when orchestration logic exists outside the normal GitLab trigger keyword flow.

When to Use Multi-Project Pipelines vs Monorepo Pipelines

A common architectural decision is whether to use one repository with child pipelines or multiple repositories with multi-project pipelines.

Choose multi-project pipelines when:

  • services are owned by different teams
  • repositories have independent release cycles
  • permissions must be separated cleanly
  • deployment logic belongs in a central infrastructure repo
  • reuse across many projects matters more than one-repo simplicity

Choose monorepo or child pipelines when:

  • many components change together often
  • a single repository is already the team’s preferred workflow
  • shared commits across components are common
  • ref and commit consistency in one pipeline is valuable
  • repository sprawl would add too much overhead

There is no universal winner. The best choice depends on ownership, deployment independence, and how often components change together.

Complete Example: Frontend, Backend, and a Deploy Trigger

Imagine a system with three repositories:

  • my-group/frontend
  • my-group/backend
  • my-group/deployments

The frontend repository builds the UI, the backend repository builds the API, and the deployments repository owns environment rollout logic.

Frontend pipeline

stages:
  - test
  - deploy

frontend_tests:
  stage: test
  script:
    - npm ci
    - npm test

trigger_deploy:
  stage: deploy
  trigger:
    project: my-group/deployments
    branch: main
    strategy: depend
  variables:
    COMPONENT: frontend
    IMAGE_TAG: $CI_COMMIT_SHA
    TARGET_ENV: staging

Backend pipeline

stages:
  - test
  - deploy

backend_tests:
  stage: test
  script:
    - npm ci
    - npm test

trigger_deploy:
  stage: deploy
  trigger:
    project: my-group/deployments
    branch: main
    strategy: depend
  variables:
    COMPONENT: backend
    IMAGE_TAG: $CI_COMMIT_SHA
    TARGET_ENV: staging

Deployments pipeline

stages:
  - deploy

run_deploy:
  stage: deploy
  script:
    - echo "Deploying $COMPONENT with image tag $IMAGE_TAG to $TARGET_ENV"
    - ./deploy.sh "$COMPONENT" "$IMAGE_TAG" "$TARGET_ENV"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "pipeline"'

This is a good example of GitLab downstream pipeline design. The application repos keep their own tests and build logic, while the deployment repo centralizes rollout logic. The result is cleaner ownership and easier reuse.

Best Practices for Multi-Project and Child Pipelines

As pipelines become more distributed, discipline matters.

Useful best practices include:

  • pass explicit variables instead of relying on hidden assumptions
  • use strategy: depend when downstream success must gate upstream completion
  • keep shared include files versioned and stable
  • document which project owns deployment logic
  • avoid circular trigger chains
  • use child pipelines to simplify monorepos, not to hide unnecessary complexity
  • keep downstream pipeline names descriptive so pipeline graphs stay readable

The goal is not just to make the pipeline work. The goal is to make it understandable to the next engineer who has to debug it.

Final Takeaway

GitLab multi-project pipelines and child pipelines let you scale CI/CD beyond a single flat YAML file. The trigger keyword starts downstream pipelines, variables pass context, include helps share or split configuration, dynamic child pipelines generate YAML on the fly, and needs:project can consume artifacts across repositories. Together, these features make GitLab CI/CD flexible enough for microservices, monorepos, shared deployment repos, and platform-scale orchestration.

If your pipeline is becoming too large or too tightly coupled, multi-project and child pipeline patterns are usually the next step.


Knowledge Check

Exercise

Question 1: Pipeline Type

What is the main difference between a child pipeline and a multi-project pipeline in GitLab CI/CD?

Exercise

Question 2: Trigger Keyword

What does the trigger keyword do in a GitLab CI job?

Exercise

Question 3: Dynamic Child Pipelines

Why would a team use a dynamic child pipeline in GitLab?

PreviousPrev
Next

Continue Learning

GitLab CI Testing

Learn GitLab CI testing, unit tests, JUnit reports, code coverage, coverage badges, cobertura visualization, parallel test execution, CI test variables, and a complete Jest pipeline example.

12 min read·Easy

GitLab CI Security Scanning

Learn GitLab CI security scanning with SAST, DAST, secret detection, dependency scanning, container scanning, security reports, and DevSecOps best practices for secure pipelines.

12 min read·Medium

GitLab CI Deploy to AWS

Learn GitLab CI deploy AWS patterns including CI/CD variables, AWS OIDC, S3 deployments, EC2 SSH deploys, ECR image pushes, ECS service updates, and Terraform automation.

14 min read·Medium

Explore Related Topics

Do

Docker Tutorials

Build and push Docker images in your pipelines

Gi

Git Tutorials

Trigger CI/CD pipelines from Git events

Try the Tool

YAML Validator

Validate GitHub Actions and CI/CD pipeline YAML files.

Cron Parser

Build and understand scheduled workflow cron expressions.

On This Page

What Are Multi-Project Pipelines and Why Use Them?Triggering a Downstream Pipeline with the `trigger` KeywordPassing Variables to Downstream Pipelines`strategy: depend` vs `strategy: mirror``strategy: depend``strategy: mirror`Child Pipelines with `include`The `include` Keyword: Local, Remote, Template, Project`local``remote``template``project`Dynamic Child PipelinesCross-Project Pipeline Dependencies with `needs:project`Triggering Pipelines with the Trigger APIWhen to Use Multi-Project Pipelines vs Monorepo PipelinesChoose multi-project pipelines when:Choose monorepo or child pipelines when:Complete Example: Frontend, Backend, and a Deploy TriggerFrontend pipelineBackend pipelineDeployments pipelineBest Practices for Multi-Project and Child PipelinesFinal TakeawayKnowledge Check