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:
- main3. 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.xml4. 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:
- mainGitLab 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:
- mainThe 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 jobUse 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:
- mainwhen: 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
| Variable | Value |
|---|---|
| $CI_COMMIT_SHA | Full commit hash |
| $CI_COMMIT_SHORT_SHA | First 8 chars of commit hash |
| $CI_COMMIT_REF_SLUG | Branch name (URL-safe) |
| $CI_REGISTRY | GitLab container registry URL |
| $CI_REGISTRY_IMAGE | Full image path for this project |
| $CI_ENVIRONMENT_URL | URL 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.