D

GitLab CI/CD

.gitlab-ci.yml syntax — stages, jobs, variables, rules, caching and environments.

Updated 2026-09-03

On this page

Pipelines are defined in .gitlab-ci.yml at the repo root. Jobs run within stages, and stages run in the order they're declared — every job in one stage completes before the next stage starts, unless you opt out with needs.

Minimal Pipeline

stages:
  - build
  - test
  - deploy
 
build:
  stage: build
  script:
    - npm ci
    - npm run build
 
test:
  stage: test
  script:
    - npm test
 
deploy:
  stage: deploy
  script:
    - ./deploy.sh
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

Variables

variables:
  NODE_ENV: production
 
deploy:
  script:
    - echo "Deploying to $CI_ENVIRONMENT_NAME"
  environment:
    name: production
    url: https://example.com

Predefined variables

GitLab exposes dozens of built-in variables — $CI_COMMIT_SHA, $CI_COMMIT_BRANCH, $CI_PIPELINE_ID, $CI_PROJECT_DIR — without any config. Check the predefined variables reference before writing a script step that reconstructs something GitLab already gives you.

Rules

deploy_staging:
  script: ./deploy.sh staging
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'
 
deploy_prod:
  script: ./deploy.sh production
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual

rules

The current, flexible way to control when a job runs — conditions, when: manual, when: never, all in one ordered list evaluated top to bottom.

only / except (legacy)

The older syntax for the same purpose. Still works, but rules supersedes it — new pipelines should use rules, not a mix of both in the same job.

Caching & Artifacts

build:
  script:
    - npm ci
    - npm run build
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
  artifacts:
    paths:
      - dist/
    expire_in: 1 week

Cache vs. artifacts

Cache speeds up later pipeline runs by reusing dependencies (node_modules) — it's best-effort and can be empty. Artifacts pass build output between stages of the same pipeline run and are guaranteed available to downstream jobs — don't rely on cache for something a later job actually needs to exist.

needs (DAG pipelines)

test:
  stage: test
  needs: [build]
  script: npm test

needs vs. stage order

By default a job waits for every job in the previous stage. needs lets a job start as soon as its specific dependencies finish, even if other jobs in an earlier stage are still running — turns a strictly sequential pipeline into a dependency graph.

Runners

gitlab-runner list

Lists runners registered on this machine.

gitlab-runner register

Registers a new runner against a GitLab instance, interactively prompting for the registration token and executor.

gitlab-runner verify

Checks that registered runners can still authenticate against GitLab.

Include (shared pipeline config)

include:
  - project: 'my-group/ci-templates'
    file: '/templates/deploy.yml'
  - local: '.gitlab/ci/test.yml'

Why include over copy-paste

include lets multiple projects share the same pipeline template from one source — a security scan step or a standard deploy job gets fixed once centrally instead of being patched in every repo that copied it.

Official documentation