GitLab
06 / 09

GitLab CI/CD Pipelines

GitLab CI/CD Pipelines

GitLab CI/CD is defined in .gitlab-ci.yml at the root of the repository. It is one of the most feature-complete CI/CD systems available, with DAG pipelines, environments, review apps, and artifact management built in.

.gitlab-ci.yml Anatomy

stages:
  - build
  - test
  - deploy

variables:
  NODE_ENV: production

default:
  image: node:20
  before_script:
    - npm ci

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour

test:
  stage: test
  script:
    - npm test
  coverage: '/Statements.*?([d.]+)%/'

deploy_staging:
  stage: deploy
  script:
    - ./deploy.sh staging
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - main

Job Keywords

# Run on specific branches/tags
only:
  - main
  - /^release-.*/

# Modern alternative: rules (more flexible)
rules:
  - if: '$CI_COMMIT_BRANCH == "main"'
  - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    when: manual

# Dependencies between jobs
needs:            # DAG — run as soon as dependency is done (skip stage order)
  - job: build

dependencies:     # Download artifacts from specific jobs
  - build

# Retry on failure
retry:
  max: 2
  when: runner_system_failure

# Timeout per job
timeout: 30 minutes

Pipeline Types

  • Branch pipelines: run on every push to a branch

  • Merge request pipelines: run when MR is created/updated (source: merge_request_event)

  • Merged results pipelines: test MR as if already merged with target branch

  • Merge trains: pipeline tests queued MRs sequentially before merging

  • Scheduled pipelines: cron-based, configured in CI/CD → Schedules

  • Triggered pipelines: via API, web hook, or another pipeline (trigger keyword)

  • Parent-child pipelines: trigger: include — split huge .gitlab-ci.yml across files

Runners

# GitLab-hosted runners: available on gitlab.com (SaaS), use tags to target
# Self-managed: install runner on your own infrastructure

# Register a runner
gitlab-runner register   --url https://gitlab.com   --token <token>   --executor docker   --docker-image alpine

# Runner tags — match runner to jobs
build_app:
  tags:
    - docker
    - linux

Artifacts & Caching

# Artifacts: pass files between jobs or download after pipeline
artifacts:
  paths:
    - build/
  reports:
    junit: test-results.xml
    coverage_report:
      coverage_format: cobertura
      path: coverage/cobertura-coverage.xml
  expire_in: 7 days

# Cache: speed up jobs by reusing node_modules, pip packages, etc.
cache:
  key:
    files:
      - package-lock.json
  paths:
    - node_modules/

Environments & Review Apps

  • Environments track deployments — visible in Deployments → Environments

  • Review Apps: auto-create a temporary environment for every MR (dynamic environments)

  • Stop review app: define a stop job with action: stop and trigger on MR close

  • Protected environments: only specific roles can deploy to production

  • Deployment freezes: CI/CD → Deployment freezes — block deploys during maintenance windows

Predefined CI Variables

$CI_COMMIT_SHA          # full commit SHA
$CI_COMMIT_SHORT_SHA    # first 8 chars
$CI_COMMIT_BRANCH       # branch name
$CI_COMMIT_TAG          # tag name (if pipeline is for a tag)
$CI_PIPELINE_ID         # unique pipeline ID
$CI_JOB_NAME            # current job name
$CI_PROJECT_ID          # project numeric ID
$CI_REGISTRY            # GitLab container registry URL
$CI_REGISTRY_IMAGE      # full image path
$CI_ENVIRONMENT_NAME    # set when job has environment:

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free