Writing .gitlab-ci.yml Pipelines

35 minLesson 2 of 4

Learning Objectives

  • Write complete .gitlab-ci.yml pipeline configurations
  • Define stages, jobs, and their relationships
  • Use variables, rules, and conditional execution
  • Configure artifacts, caching, and environments
  • Implement manual deployments and environment management

Pipeline Structure

stages:
  - build
  - test
  - deploy
 
build-job:
  stage: build
  script:
    - echo "Building..."
 
test-job:
  stage: test
  script:
    - echo "Testing..."
 
deploy-job:
  stage: deploy
  script:
    - echo "Deploying..."

Jobs in the same stage run in parallel. Stages run sequentially.

Key Keywords

stages

stages:
  - build
  - test
  - deploy

script (Required)

job:
  script:
    - npm install
    - npm run build

image

job:
  image: node:18
  script:
    - npm test

before_script / after_script

before_script:
  - apt-get update
 
job:
  script:
    - npm test
  after_script:
    - echo "Cleanup..."

Variables

variables:
  APP_NAME: "my-app"
  DEPLOY_ENV: "production"
 
deploy:
  script:
    - echo "Deploying $APP_NAME to $DEPLOY_ENV"

Predefined Variables

VariableValue
$CI_COMMIT_BRANCHCurrent branch name
$CI_COMMIT_SHORT_SHAShort commit hash
$CI_PIPELINE_IDPipeline ID
$CI_PROJECT_NAMEProject name
$CI_REGISTRY_IMAGEContainer registry URL

Rules (Conditional Execution)

deploy-prod:
  script:
    - deploy.sh
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual
    - if: $CI_COMMIT_BRANCH == "develop"
      when: on_success

Artifacts

Save files between stages:

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 week
 
deploy:
  stage: deploy
  script:
    - deploy dist/  # Uses artifact from build stage

Caching

Speed up pipelines by caching dependencies:

cache:
  key: $CI_COMMIT_REF_SLUG
  paths:
    - node_modules/
 
install:
  script:
    - npm ci  # Uses cache if available

Environments

deploy-staging:
  stage: deploy
  script:
    - deploy-to-staging.sh
  environment:
    name: staging
    url: https://staging.example.com
 
deploy-prod:
  stage: deploy
  script:
    - deploy-to-prod.sh
  environment:
    name: production
    url: https://example.com
  when: manual
  only:
    - main

needs (Job Dependencies)

Skip stage ordering for faster pipelines:

build-image:
  stage: build
  script: docker build -t app .
 
push-image:
  stage: build
  needs: ["build-image"]
  script: docker push app

Complete Example

stages:
  - test
  - build
  - deploy
 
variables:
  IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
 
test:
  stage: test
  image: python:3.11
  script:
    - pip install -r requirements.txt
    - pytest
  cache:
    paths:
      - .pip-cache/
 
build:
  stage: build
  script:
    - docker build -t $IMAGE .
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker push $IMAGE
  artifacts:
    reports:
      dotenv: build.env
 
deploy-staging:
  stage: deploy
  script:
    - kubectl set image deployment/app app=$IMAGE -n staging
  environment:
    name: staging
    url: https://staging.app.com
 
deploy-prod:
  stage: deploy
  script:
    - kubectl set image deployment/app app=$IMAGE -n production
  environment:
    name: production
    url: https://app.com
  when: manual
  only:
    - main

Summary

  • .gitlab-ci.yml defines your entire CI/CD pipeline
  • Stages run sequentially; jobs within stages run in parallel
  • rules: controls when jobs execute
  • artifacts: pass files between stages
  • cache: speeds up repeated dependency installations
  • environment: tracks deployments
  • when: manual requires human approval
  • needs: creates job dependencies regardless of stage order

Next Steps

Next, we'll set up GitLab Runners, container registries, and deploy to Kubernetes.