GitLab CI/CD Pipeline Guide 2026

Build, test, and deploy with .gitlab-ci.yml — from zero to production pipeline

GitLab CI/CD runs pipelines directly from your repository with zero external setup. Create a .gitlab-ci.yml file in your repo root, push, and GitLab runs it automatically. This guide covers the essential patterns you need for production pipelines.

Want to generate a pipeline config instantly? Use our GitLab CI/CD Generator — select your language, configure stages, and download a ready-to-use .gitlab-ci.yml.

1. Pipeline Structure

A typical pipeline has 4 stages that run sequentially. Jobs within the same stage run in parallel:

stages:
  - lint
  - test
  - build
  - deploy

If any job in a stage fails, the pipeline stops and subsequent stages don't run. This prevents deploying broken code.

2. Node.js Pipeline Example

image: node:20-alpine

stages:
  - lint
  - test
  - build
  - deploy

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/

lint:
  stage: lint
  script:
    - npm ci
    - npm run lint
  allow_failure: true

test:
  stage: test
  script:
    - npm ci
    - npm run test -- --coverage
  coverage: '/All files.*?\|\s*([\d.]+)/'
  artifacts:
    reports:
      junit: junit.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

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

deploy:
  stage: deploy
  script:
    - echo "Deploying to production..."
  environment:
    name: production
    url: https://example.com
  when: manual
  only:
    - main

3. Python Pipeline Example

image: python:3.12-slim

stages:
  - lint
  - test
  - build

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .cache/pip/

variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

lint:
  stage: lint
  script:
    - pip install ruff
    - ruff check .

test:
  stage: test
  services:
    - postgres:16-alpine
  variables:
    POSTGRES_DB: test_db
    POSTGRES_USER: runner
    POSTGRES_PASSWORD: password
    DATABASE_URL: "postgresql://runner:password@postgres/test_db"
  script:
    - pip install -r requirements.txt
    - pytest --cov --junitxml=report.xml
  artifacts:
    reports:
      junit: report.xml

4. Docker Build & Push

Building and pushing Docker images is one of the most common CI/CD tasks:

build-docker:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
    - docker build -t $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest
  only:
    - main

GitLab provides a built-in container registry ($CI_REGISTRY), so you don't need Docker Hub. The $CI_COMMIT_SHORT_SHA tag ensures each build produces a unique, traceable image.

5. Kubernetes Deployment

deploy-k8s:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl set image deployment/myapp
        myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
        --namespace=production
    - kubectl rollout status deployment/myapp
        --namespace=production --timeout=300s
  environment:
    name: production
  when: manual
  only:
    - main

The rollout status command waits for the deployment to complete and fails the pipeline if it doesn't finish within 5 minutes — catching stuck deployments automatically.

6. Caching Strategy

Proper caching cuts pipeline times by 50-80%. Key rules:

cache:
  key:
    files:
      - package-lock.json  # Cache invalidates when deps change
  paths:
    - node_modules/
  policy: pull-push  # Default: download cache, upload after job

Use key: files to bust cache only when your lockfile changes. For jobs that only read cache (like deploy), use policy: pull to skip the upload step.

7. Staging → Production Pipeline

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

deploy-production:
  stage: deploy
  script:
    - ./deploy.sh production
  environment:
    name: production
    url: https://example.com
  when: manual  # Requires click to deploy
  needs:
    - deploy-staging  # Only after staging succeeds
  only:
    - main

when: manual adds a play button in the GitLab UI — production deploys require explicit human approval. needs: [deploy-staging] ensures you can't deploy to production without a successful staging deploy first.

8. Essential CI/CD Variables

VariableValue
$CI_COMMIT_SHAFull commit hash
$CI_COMMIT_SHORT_SHAFirst 8 chars of commit hash
$CI_COMMIT_REF_SLUGBranch name (URL-safe)
$CI_REGISTRYGitLab container registry URL
$CI_REGISTRY_IMAGEFull image path for this project
$CI_ENVIRONMENT_URLURL of the deployment environment

Store secrets (API keys, SSH keys, tokens) in Settings → CI/CD → Variables with the "Masked" flag enabled. Never hardcode secrets in .gitlab-ci.yml.

Generate Your Pipeline

Instead of writing YAML from scratch, use our GitLab CI/CD Generator. Pick your language (Node.js, Python, Go, Java, Rust, PHP, Ruby, .NET), configure test services (PostgreSQL, Redis, MySQL), choose a deployment target (Docker, Kubernetes, SSH, AWS), and download a complete .gitlab-ci.yml ready for production.