CI/CD

GitLab CI/CD

Pipelines GitLab CI/CD, .gitlab-ci.yml, runners et déploiement.

gitlabcicdpipelinerunnersdevops

Structure .gitlab-ci.yml

stages:
  - build
  - test
  - deploy
 
variables:
  NODE_VERSION: "20"
 
build:
  stage: build
  image: node:${NODE_VERSION}-alpine
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour
 
test:
  stage: test
  image: node:${NODE_VERSION}-alpine
  script:
    - npm ci
    - npm test
  coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
 
deploy:
  stage: deploy
  script:
    - ./deploy.sh
  environment:
    name: production
    url: https://app.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

Stages & Jobs

Dépendances entre jobs

stages:
  - build
  - test
  - deploy
 
build-app:
  stage: build
  script: npm run build
 
unit-tests:
  stage: test
  needs: ["build-app"]      # DAG — n'attend que build-app
  script: npm run test:unit
 
integration-tests:
  stage: test
  needs: ["build-app"]
  script: npm run test:integration
  allow_failure: true        # Ne bloque pas le pipeline

Jobs manuels

deploy-prod:
  stage: deploy
  script: ./deploy.sh prod
  when: manual               # Déclenché manuellement
  allow_failure: false

Runners

TypeUtilisation
SharedFournis par GitLab.com, partagés entre projets
SpecificDédiés à un projet ou groupe
GroupPartagés au niveau d'un groupe GitLab

Sélection par tags

build:
  tags:
    - docker
    - linux
  script: make build

Enregistrer un runner

$gitlab-runner register --url https://gitlab.com --token glrt-xxxx --executor docker --docker-image alpine:latest

Variables

Variables prédéfinies

VariableDescription
CI_COMMIT_BRANCHBranche du commit
CI_COMMIT_SHASHA complet du commit
CI_PIPELINE_IDID du pipeline
CI_PROJECT_NAMENom du projet
CI_MERGE_REQUEST_IIDIID de la merge request
CI_REGISTRY_IMAGEURL de l'image du registre

Variables personnalisées

variables:
  DEPLOY_ENV: "staging"
  DB_HOST: "db.example.com"
 
job:
  variables:
    LOCAL_VAR: "valeur locale"
  script:
    - echo $DEPLOY_ENV
    - echo $LOCAL_VAR

Variables protégées et masquées : configurer dans Settings > CI/CD > Variables.

Cache & Artifacts

Cache (réutilisé entre pipelines)

build:
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/
    policy: pull-push        # pull, push, ou pull-push
  script:
    - npm ci
    - npm run build

Artifacts (transmis entre jobs)

build:
  artifacts:
    paths:
      - dist/
      - coverage/
    expire_in: 1 week
    reports:
      junit: junit.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura.xml

Rules & Conditions

deploy-staging:
  script: ./deploy.sh staging
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"
      when: always
    - if: $CI_MERGE_REQUEST_IID
      when: manual
    - when: never
 
tests:
  script: npm test
  rules:
    - changes:                # Seulement si ces fichiers changent
        - src/**/*
        - tests/**/*
    - exists:                 # Seulement si ce fichier existe
        - Dockerfile

Workflow rules (niveau pipeline)

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"
    - if: $CI_COMMIT_TAG

Environnements

deploy-review:
  stage: deploy
  script: ./deploy-review.sh
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://$CI_COMMIT_REF_SLUG.review.example.com
    on_stop: stop-review
    auto_stop_in: 1 week
  rules:
    - if: $CI_MERGE_REQUEST_IID
 
stop-review:
  stage: deploy
  script: ./teardown-review.sh
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    action: stop
  when: manual

Templates & Includes

Include

include:
  - local: '.gitlab/ci/build.yml'
  - project: 'group/shared-ci'
    ref: main
    file: '/templates/deploy.yml'
  - remote: 'https://example.com/ci-template.yml'
  - template: 'Security/SAST.gitlab-ci.yml'

Extends & Ancres YAML

.base-deploy:
  image: alpine:latest
  before_script:
    - apk add --no-cache curl
  script:
    - ./deploy.sh $DEPLOY_ENV
 
deploy-staging:
  extends: .base-deploy
  variables:
    DEPLOY_ENV: staging
  environment:
    name: staging
 
deploy-prod:
  extends: .base-deploy
  variables:
    DEPLOY_ENV: production
  environment:
    name: production
  when: manual

Registre de conteneurs

Build et push

build-image:
  image: docker:24
  services:
    - docker:24-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_SHA

Avec Kaniko (sans Docker-in-Docker)

build-image:
  image:
    name: gcr.io/kaniko-project/executor:v1.23.0-debug
    entrypoint: [""]
  script:
    - >-
      /kaniko/executor
      --context $CI_PROJECT_DIR
      --dockerfile Dockerfile
      --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

Bonnes pratiques

PratiqueDétail
DRYUtiliser extends et include pour factoriser
DAGPréférer needs à l'ordre séquentiel des stages
CacheClé basée sur le lockfile pour invalidation précise
RulesPréférer rules à only/except (déprécié)
ArtifactsToujours définir expire_in pour éviter le stockage infini
SécuritéActiver SAST/DAST via les templates GitLab
VariablesMasquer et protéger les secrets dans les settings