Working with Monorepo Pipelines
1. Using rules:changes for Selective Execution
| Rule | Description | Usage |
|---|---|---|
| rules:changes | Triggers job only if files matching the specified paths have changed in the commit. | rules: - changes: - src/** |
Example: Using rules:changes to run jobs only on relevant file changes
build:
script:
- echo "Building..."
rules:
- changes:
- src/**/*.js
- package.json
rules:changes is evaluated at job runtime and compares the current commit with the previous one.
changes is used with only or except, it will override the conditions.
2. Implementing Microservice Pipelines
| Aspect | Description | Notes |
|---|---|---|
| pipeline structure | include: directive to reference service-specific CI files |
Each microservice has its own .gitlab-ci.yml |
| shared jobs | extends: keyword to reuse job definitions |
Centralized job templates in .gitlab-ci.yml |
| dependency management | Use artifacts: to pass build outputs between stages |
Ensures services can depend on each other's builds |
Example: Pipeline Configuration for Microservice
include:
- local: "shared/jobs.yml"
services:
- name: postgres:13
alias: db
variables:
POSTGRES_DB: test_db
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_pass
stages:
- build
- test
- deploy
build_job:
stage: build
script:
- npm install
- npm run build
artifacts:
paths:
- dist/
test_job:
stage: test
script:
- npm run test
dependencies:
- build_job
deploy_job:
stage: deploy
script:
- echo "Deploying to production"
only:
- main
Example: Shared Job Template
default:
image: node:18
before_script:
- npm ci
build_job_template:
extends: .default
script:
- npm run build
artifacts:
paths:
- dist/
test_job_template:
extends: .default
script:
- npm run test
Key Considerations for Microservice Pipelines
- Each service has its own
.gitlab-ci.ymlfile - Use
include:to centralize shared configurations - Artifacts help pass data between stages or services
- Isolate pipelines to avoid cross-service interference
3. Using needs for Complex Dependencies
The needs keyword in GitLab CI/CD allows you to define dependencies between jobs, ensuring that a job runs only after its specified dependencies have completed successfully. This is particularly useful in monorepo setups where jobs might depend on artifacts or outputs from other jobs across different packages or services.
| Property | Description | Values |
|---|---|---|
| needs | Defines the jobs that this job depends on. | job, pipeline, or artifacts |
| job | Name of the job to depend on. | String |
| artifacts | Whether to inherit artifacts from the dependency job. | true, false |
Example: Using needs with job dependency
build:
stage: build
script:
- echo "Building..."
artifacts:
paths:
- dist/
test:
stage: test
needs:
- job: build
script:
- echo "Testing..."
Example: Using needs with artifacts
build:
stage: build
script:
- echo "Building..."
artifacts:
paths:
- dist/
deploy:
stage: deploy
needs:
- job: build
artifacts: true
script:
- echo "Deploying..."
needs, the job will not run until all dependencies have completed successfully. If any dependency fails, the job will be skipped.
4. Creating Component-Specific Jobs
| Job Name | Component | Trigger | Description |
|---|---|---|---|
| frontend-build | frontend |
on push to main |
Builds and tests the frontend component |
| backend-deploy | backend |
on merge to main |
Deploys the backend component to staging |
| shared-tests | shared |
on any branch push | Runs tests for shared libraries used by both components |
Example: Component-specific job configuration
frontend-build:
stage: build
script:
- npm install
- npm run build
artifacts:
paths:
- dist/
only:
- main
Example: Using component variables
backend-deploy:
stage: deploy
script:
- echo "Deploying backend component"
- ./deploy.sh $BACKEND_VERSION
only:
- main
variables:
BACKEND_VERSION: v1.2.3
5. Using Dynamic Child Pipelines
Dynamic child pipelines allow you to create pipelines that are generated at runtime based on conditions or variables. This is useful for complex workflows where the pipeline structure depends on the project state or configuration.
| Property | Description | Values | Notes |
|---|---|---|---|
| trigger | Defines a child pipeline to be triggered dynamically | include |
Must reference a YAML file or template |
| source | Specifies the location of the child pipeline YAML | template, file |
Can be a local file or a template from a project |
| variables | Variables to pass to the child pipeline | Map of key-value pairs | Available in child pipeline as $VAR_NAME |
Example: Triggering a Dynamic Pipeline
job_name:
trigger:
include:
- artifact: pipeline.yml
variables:
ENVIRONMENT: "staging"
include directive supports both local files and templates. Templates must be defined in the .gitlab directory or a subdirectory.Key Points
- Child pipelines are defined using the
triggerkeyword. - Dynamic pipelines can be generated based on runtime conditions or variables.
- Variables can be passed to child pipelines using the
variableskey. - Child pipeline files must be valid YAML and follow GitLab CI/CD syntax.
6. Implementing Cross-Project Dependencies
| Dependency Type | Description | Configuration | Notes |
|---|---|---|---|
| project | Reference to another project in the same GitLab instance | project: "group/project-name" |
Must be accessible to the runner |
| pipeline | Triggers pipeline in another project | pipeline: "group/project-name" |
Can use variables from the triggering project |
| trigger | Triggers a pipeline in another project with specific variables | trigger: "group/project-name" |
Supports passing variables and ref |
Example: Triggering a Pipeline in Another Project
trigger_cross_project:
trigger:
project: "my-group/dependency-project"
branch: "main"
strategy: "none"
Example: Using Variables in Cross-Project Triggers
trigger_with_vars:
trigger:
project: "my-group/dependency-project"
variables:
DEPLOY_ENV: "$CI_ENVIRONMENT_SLUG"
BUILD_ID: "$CI_PIPELINE_ID"
7. Using Path-Based Job Triggers
Path-based job triggers in GitLab CI/CD allow you to run jobs only when changes occur in specific paths within your repository. This is useful for monorepos where different parts of the codebase may require independent CI/CD pipelines.
| Field | Description | Example |
|---|---|---|
| only.paths | Runs the job only when changes occur in specified paths. | only: paths: - src/backend/** |
| except.paths | Skips the job if changes occur in specified paths. | except: paths: - docs/** |
Example: Path-Based Job Trigger
deploy_backend:
only:
paths:
- src/backend/**
script:
- echo "Deploying backend"
Example: Excluding Paths
build_docs:
except:
paths:
- src/**/*
script:
- echo "Building documentation"
8. Optimizing Artifact Passing in Monorepos
Example: Using artifacts:expire_in to reduce storage costs
build:
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
| Option | Values | Description |
|---|---|---|
| artifacts:expire_in | 1 week, 30 days |
Time after which artifacts are automatically deleted to save storage |
| artifacts:when | on_success, always, failure |
Determines when artifacts are uploaded (default: on_success) |
| artifacts:reports | coverage: coverage.xml |
Uploads reports like code coverage to GitLab for display |
Example: Using artifacts:paths to limit artifact size
test:
script:
- npm test
artifacts:
paths:
- coverage/
- test-results.xml
Example: Using cache to avoid re-downloading dependencies
build:
script:
- npm ci
cache:
key: "node-modules"
paths:
- node_modules/
9. Using Matrix for Multi-Component Testing
Example: Matrix Job Configuration
jobs:
test-components:
<span class="badge badge--new">NEW</span> matrix:
component: [frontend, backend, shared]
node-version: [16, 18, 20]
script:
- echo "Testing $component with Node.js $node-version"
- npm run test -- --component=$component --node-version=$node-version
| Property | Description | Values | Notes |
|---|---|---|---|
| matrix | Defines the matrix dimensions for job expansion | component: [frontend, backend] |
Each combination creates a new job instance |
| matrix.component | Component name to test | frontend, backend |
Used in scripts to target specific components |
| matrix.node-version | Node.js version to use for testing | 16, 18, 20 |
Ensures compatibility across versions |
10. Implementing Conditional Deployments
| Condition | Description | Example |
|---|---|---|
| only | Specifies when a job should run based on branches or tags | |
| except | Excludes jobs from running on specified branches or tags | |
| changes | Runs job only if files matching a pattern have changed | |
| rules | Advanced conditional logic using rule matching | |
Example: Using Rules for Conditional Deployments
deploy_to_staging:
stage: deploy
rules:
- if: $CI_COMMIT_BRANCH == 'staging'
when: on_success
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
when: manual
script:
- echo "Deploying to staging environment"
Example: Deploying Only on Specific File Changes
deploy_frontend:
stage: deploy
only:
changes:
- frontend/**/*
- package.json
script:
- echo "Deploying frontend"
changes keyword can be used in combination with only or except to refine when jobs run based on file modifications.
except as it can cause jobs to run unexpectedly if not properly configured.