Mastering GitLab CI/CD: End-to-End Pipeline Ready & Multi-Project Deployment
This chapter covers the creation and orchestration of an end-to-end (E2E) production-ready GitLab CI/CD pipeline. Building upon standalone deployment pipelines for Spring Boot applications, this lesson demonstrates how to trigger child deployment pipelines from the project pipeline, manage multi-environment promotion strategies (dev, qa, stage, and prod), dynamically pass artifacts and version numbers between jobs, and enforce branch-based safety rules.
1. Why Do We Need Multi-Project and Child Pipelines?
In basic standalone pipelines, building, testing, and deploying all happen within a single linear configuration file and execution context. However, enterprise software delivery requires strict separation of concerns, environment-specific security controls, and conditional execution:
- Scalability: Decoupling the main application build and test lifecycle from downstream environment deployments prevents monolithic pipeline configurations.
- Environment Isolation: Non-production environments (
dev,qa) can run automatically on feature branches or merge requests, whereas production environments (prod) require strict branch restrictions and manual interventions. - Controlled Promotion: Software must pass sequentially through lower environments before manual approval enables production deployment.
2. Core Mental Model: The Delivery Conveyor Belt
Think of the CI/CD pipeline as an automated factory conveyor belt:
- The Workshop (Build & Test): Code is assembled, compiled, and verified.
- The Staging Area (Artifact Generation): Successful builds generate a versioned package (artifact or Maven release).
- The Quality Gates & Loading Docks (Non-Prod & Prod Deployments): Trigger jobs act as dispatchers, sending the versioned package to specific destination environments (
dev,qa,stage,prod) using dedicated deployment agents.
Note: Just like a physical factory where a forklift operator cannot ship products to the final retail shelf without passing quality checks, our pipeline uses strict rules and manual triggers to prevent unverified code from reaching production.
3. Designing the Stage Structure and Deployment Jobs
The pipeline is structured around two primary deployment stages: nonprod and prod. Within these stages, individual environment jobs (dev, qa, stage, and prod) are configured as trigger jobs that call child deployment pipelines.
Here is the conceptual breakdown of the deployment jobs and their associated target environments:
4. Passing Dynamic Artifact Versions Between Jobs
To ensure traceability, every deployment must know the exact version number generated during the build and release phase. GitLab allows passing variables between jobs using generated environment files (.env).
Capturing and Storing Version Variables
In the build/release jobs, the project version is extracted from pom.xml and written to a report file, which GitLab recognizes as a dotenv artifact:
# Conceptual snippet showing artifact version extraction and reporting
maven_deploy:
stage: deploy
script:
- VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
- echo "ARTIFACT_VERSION=$VERSION" >> build.env
artifacts:
reports:
dotenv: build.env
When downstream trigger jobs run, they reference $ARTIFACT_VERSION to provision the exact release payload to the target environment runner.
5. Implementing Non-Production vs. Production Environment Rules
To maintain strict security and prevent accidental deployments, rules are applied to control where and when jobs appear in the GitLab UI.
Non-Production Configuration (Dev, QA, Stage)
Non-production deployment jobs run automatically for lower environments and manually for staging. They are configured to bypass merge-event pipelines while remaining visible across feature branches:
deploy_dev:
stage: nonprod
variables:
DEPLOY_ENV: "dev"
AGENT_TAG: "nonprod-agent"
ARTIFACT_VERSION: "$ARTIFACT_VERSION"
trigger:
include:
- local: '/ci/child-deployment-pipeline.yml'
strategy: depend
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- when: on_success
Production Configuration (prod)
Production deployment has strict security boundaries. It must only be visible and executable on the default (main) branch, and it requires a manual click to execute:
deploy_prod:
stage: prod
variables:
DEPLOY_ENV: "prod"
AGENT_TAG: "prod-agent"
ARTIFACT_VERSION: "$ARTIFACT_VERSION"
trigger:
include:
- local: '/ci/child-deployment-pipeline.yml'
strategy: depend
rules:
- if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
when: manual
- when: never
6. Step-by-Step Flow Walkthrough: Feature Branch vs. Main Branch
Scenario A: Committing to a Feature Branch (feat-pipeline)
When developers push code to a non-default branch, production and release jobs are entirely hidden by design rules.
Scenario B: Merging into Main Branch (main)
Once feature changes are approved and merged into the default branch, the pipeline unlocks full release and production capabilities.
7. Real-World Debugging & Verification Best Practices
When executing multi-environment pipelines in production-grade systems, engineers often encounter synchronization lags or UI state discrepancies:
- Real-Time UI Delay: GitLab can occasionally take 30 to 60 seconds to reflect real-time status updates after child pipeline triggers complete. Best Practice: Manually refresh the pipeline view if manual trigger buttons (like
prodorstage) do not appear immediately after prerequisite stages turn green. - Health Check Validation: Never promote a build to production blindly. Always click through to the deployed endpoints (
dev,qa,stage) to verify database connectivity and backend response validity before hitting the production play button. - Agent Tag Mismatches: Ensure runner tags (
AGENT_TAG: "nonprod-agent"vsAGENT_TAG: "prod-agent") precisely match the registered GitLab runner executor tags on your infrastructure servers. A mismatch will cause jobs to remain indefinitely stuck in apendingstate.
Summary and Key Takeaways
- End-to-End Orchestration: Successfully combined build, test, snapshot publishing, artifact version propagation, and multi-environment deployment into a cohesive GitLab CI/CD workflow.
- Child Pipeline Architecture: Used
trigger:keywords andstrategy: dependto invoke modular deployment sub-pipelines cleanly. - Dynamic Variable Passing: Transported version metadata between independent pipeline jobs using
.envreport artifacts. - Environment Promotion Hierarchy: Structured deployments sequentially from automatic lower environments (
dev,qa) to manual staging (stage) and production (prod). - Strict Branch Governance: Implemented environment isolation rules ensuring that production and release jobs are strictly bound to the default (
main) branch and hidden from feature branches. - Manual Safety Gates: Configured manual play triggers for critical production environments to guarantee human-in-the-loop validation after successful health checks on lower environments.