You can trigger downstream GitLab pipelines across projects, but it’s not a direct, built-in feature of GitLab CI/CD itself. Instead, it’s achieved by leveraging GitLab’s API to initiate a new pipeline run in a different project.
Let’s see this in action. Imagine you have a "build" project that, upon successful completion, needs to trigger a "deploy" pipeline in a separate "production" project.
Here’s a simplified .gitlab-ci.yml in the "build" project that does this:
stages:
- build
- trigger_deploy
build_app:
stage: build
script:
- echo "Building the application..."
# Actual build commands here
- echo "Build complete."
trigger_production_deploy:
stage: trigger_deploy
script:
- |
curl --request POST "https://gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/ref/${CI_COMMIT_REF_NAME}/trigger/pipeline" \
--header "PRIVATE-TOKEN: ${GITLAB_TRIGGER_TOKEN}" \
--form "variables[DEPLOY_ENV]=production" \
--form "variables[BUILD_ARTIFACT_URL]=http://your-artifact-repo.com/build-${CI_COMMIT_SHA}.tar.gz"
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: on_success
In this example:
build_appis a standard job that performs the build.trigger_production_deployis the job that initiates the downstream pipeline.- It uses
curlto make aPOSTrequest to the GitLab API’s pipeline trigger endpoint. CI_PROJECT_IDandCI_COMMIT_REF_NAMEare predefined CI/CD variables that refer to the current project and branch.GITLAB_TRIGGER_TOKENis a project-level CI/CD variable that holds a personal access token or a project access token withapiscope. This is crucial for authentication.variables[DEPLOY_ENV]=productionandvariables[BUILD_ARTIFACT_URL]are examples of how you can pass variables to the downstream pipeline. These would then be accessible in the.gitlab-ci.ymlof the "production" project.- The
rulesensure this job only runs on themainbranch and only if the precedingbuild_appjob succeeds.
The "production" project’s .gitlab-ci.yml would look something like this:
stages:
- deploy
deploy_to_production:
stage: deploy
script:
- echo "Deploying to production environment..."
- echo "Using deployment environment: $DEPLOY_ENV"
- echo "Artifact URL: $BUILD_ARTIFACT_URL"
# Actual deployment commands here
- echo "Deployment complete."
rules:
- if: '$CI_PIPELINE_SOURCE == "trigger"' # This job runs when triggered by the API
The key here is CI_PIPELINE_SOURCE == "trigger". This rule ensures that the deploy_to_production job only runs when the pipeline is initiated via an API trigger, preventing it from running on regular pushes.
The problem this solves is creating robust, multi-project CI/CD workflows where distinct stages of your development lifecycle (e.g., building, testing, deploying to staging, deploying to production) can reside in separate, independently managed GitLab projects. This promotes modularity, better access control, and clearer ownership of different pipeline stages.
The GitLab API endpoint projects/:id/trigger/pipeline is designed for this. It takes a reference (like a branch name) and optional variables. When you call it, GitLab spins up a new pipeline in the target project, associated with the specified ref, and passes along any variables you defined. The PRIVATE-TOKEN or CI_JOB_TOKEN (if the projects are within the same GitLab instance and you’re using a CI job token with appropriate permissions) is the credential that grants permission to perform this action.
What most people don’t realize is that you can trigger pipelines in any project you have API access to, not just within the same GitLab instance. If you have a personal access token with api scope, you can trigger pipelines across different GitLab.com accounts or even between a self-hosted GitLab and GitLab.com, provided the token is valid. This opens up possibilities for complex, distributed CI/CD setups.
Once you have this working, the next logical step is to manage the bidirectional flow of information, such as reporting the success or failure of the downstream pipeline back to the upstream one.