This is a complete guide to GitLab CI/CD โ from your first pipeline to production deployments.
Your First Pipeline
Create .gitlab-ci.yml in your repository root:
stages:
- build
- test
- deploy
build:
stage: build
image: node:20-alpine
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
test:
stage: test
image: node:20-alpine
script:
- npm ci
- npm test
deploy-staging:
stage: deploy
script:
- echo "Deploying to staging..."
environment:
name: staging
url: https://staging.example.com
only:
- developKey Concepts
Variables
variables:
NODE_ENV: production
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
# Use CI/CD variables (Settings > CI/CD > Variables)
deploy:
script:
- kubectl set image deployment/app app=$DOCKER_IMAGECaching
build:
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .npm/
script:
- npm ci --cache .npmArtifacts
test:
script:
- npm test -- --coverage
artifacts:
paths:
- coverage/
reports:
junit: test-results.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
expire_in: 7 daysDocker Build Pipeline
build-image:
stage: build
image: docker:latest
services:
- docker:dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHAKubernetes Deployment
deploy-production:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl config set-cluster k8s --server=$KUBE_URL --certificate-authority=$KUBE_CA
- kubectl config set-credentials deploy --token=$KUBE_TOKEN
- kubectl config set-context default --cluster=k8s --user=deploy --namespace=production
- kubectl config use-context default
- kubectl set image deployment/app app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- kubectl rollout status deployment/app --timeout=300s
environment:
name: production
url: https://app.example.com
when: manual
only:
- mainSecurity Scanning
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.ymlTips and Tricks
- Use
rules:instead ofonly:/except:for flexible pipeline control - Use
needs:to create DAG pipelines (faster than linear stages) - Use
extends:and.templatejobs for DRY configuration - Use
include:to split large pipelines into multiple files - Set
interruptible: trueon jobs that can be safely cancelled on new pushes