GitLab CI/CD: Architecting, Deploying, and Optimizing Pipelines
Optimization Security and Monitoring
Extends Reuse Configuration NodeJS Jobs
Learn how to eliminate duplication in your GitLab CI/CD pipelines by reusing configuration with the extends
keyword. This guide covers three primary strategies:
Method | Description | Example |
---|---|---|
extends | Inherit settings from hidden jobs (templates) | .rspec → rspec 1 |
YAML anchors & aliases | Reuse blocks of config (scripts, variables, etc.) | &default_scripts / *default_scripts |
Reference tags | Share tags or other fields across multiple jobs | tags: &common_tags / tags: *common_tags |
Note
You can combine include
with extends
to pull in templates from external files and inherit from them in one step.
1. Anchors & Aliases
Use YAML anchors to define reusable snippets:
.default_scripts: &default_scripts
- ./default-script1.sh
- ./default-script2.sh
job1:
script:
<<: *default_scripts
2. Using extends
Define hidden jobs (prefixed with a dot) as templates, then inherit from them:
.tests:
rules:
- if: $CI_PIPELINE_SOURCE == "push"
.rspec:
extends: .tests
script:
- rake rspec
rspec 1:
extends: .rspec
variables:
RSPEC_SUITE: '1'
rspec 2:
extends: .rspec
variables:
RSPEC_SUITE: '2'
GitLab supports up to 11 inheritance levels, but keeping it under three levels is recommended:
Warning
Deep inheritance trees can become hard to maintain. Aim for 2–3 levels only.
Multi-template Inheritance
You can merge multiple hidden jobs:
.only-important:
variables:
URL: "http://my-url.internal"
IMPORTANT_VAR: "details"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_BRANCH == "stable"
tags:
- production
script:
- echo "Hello world!"
.in-docker:
image: alpine
variables:
URL: "http://docker-url.internal"
tags:
- docker
rspec:
extends:
- .only-important
- .in-docker
variables:
GITLAB: "is-awesome"
script:
- rake rspec
3. Refactoring NodeJS Test Jobs
Imagine a pipeline where the test stage contains two nearly identical NodeJS jobs: unit_testing
and code_coverage
. To speed up feedback, other stages are commented out.
Both jobs share the following configuration:
stage: test
image: node:17-alpine3.14
services:
- name: siddharth67/mongo-db:non-prod
alias: mongo
pull_policy: always
variables:
MONGO_URI: 'mongodb://mongo:27017/superData'
MONGO_USERNAME: non-prod-user
MONGO_PASSWORD: non-prod-password
cache:
key:
files:
- package-lock.json
prefix: node_modules
policy: pull-push
when: on_success
paths:
- node_modules
before_script:
- npm install
3.1 Create a Hidden Template
Extract the shared configuration into a single hidden job:
.prepare_nodejs_environment:
image: node:17-alpine3.14
services:
- name: siddharth67/mongo-db:non-prod
alias: mongo
pull_policy: always
variables:
MONGO_URI: 'mongodb://mongo:27017/superData'
MONGO_USERNAME: non-prod-user
MONGO_PASSWORD: non-prod-password
cache:
policy: pull-push
when: on_success
paths:
- node_modules
key:
files:
- package-lock.json
prefix: node_modules
before_script:
- npm install
3.2 Refactor Job Definitions
Have both jobs inherit from the .prepare_nodejs_environment
template:
unit_testing:
stage: test
extends: .prepare_nodejs_environment
script:
- npm test
artifacts:
when: always
expire_in: 3 days
name: Moca-Test-Results
paths:
- test-results.xml
reports:
junit: test-results.xml
code_coverage:
stage: test
extends: .prepare_nodejs_environment
script:
- npm run coverage
artifacts:
name: Code-Coverage-Report
when: always
expire_in: 3 days
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
coverage: /All files[^|]*\|[^|]*\s+(\d+\.\d+)/
allow_failure: true
4. Inspecting the Merged Configuration
GitLab’s CI Lint or Full configuration view will show the merged result for unit_testing
:
unit_testing:
image: node:17-alpine3.14
services:
- name: siddharth67/mongo-db:non-prod
alias: mongo
pull_policy: always
variables:
MONGO_URI: mongodb://mongo:27017/superData
MONGO_USERNAME: non-prod-user
MONGO_PASSWORD: non-prod-password
cache:
policy: pull-push
when: on_success
paths:
- node_modules
key:
files:
- package-lock.json
prefix: node_modules
before_script:
- npm install
script:
- npm test
artifacts:
paths:
- test-results.xml
5. Pipeline Execution
When you commit these changes, both unit_testing
and code_coverage
run in parallel with the shared setup:
$ npm install
$ npm test
# …
Job succeeded
This approach centralizes maintenance: updating .prepare_nodejs_environment
applies to all linked jobs.
For more on merging hidden jobs or combining include
with extends
, see the GitLab CI/CD documentation on extends
.
Links and References
Watch Video
Watch video content