Skip to content

CI GitLab

L'autre moitié du test, ce sont les pipelines GitLab. C'est composé de:

Note

Bien que j'aie essayé de tout synthetiser dans cette doc, retenez que la doc entière, potentiellement plus utile, sera disponible sur http://http://192.168.177.129:4000.

Le fichier

Tout est défini dans un .gitlab-ci.yml à la racine du projet. C'est possible (et je préfère) de l'éditer directement dans vscode ou autre éditeur de texte, mais gitlab propose son propre éditeur un peu plus sophistiqué dans Build > Pipeline editor.

Voc

Mot Ce que c'est
pipeline l'ensemble de ce qui tourne suite à un push, un tag ou une merge request
stage une étape. Les stages tournent dans l'ordre de la liste stages:
job une tâche, rattachée à un stage. Les jobs d'un même stage tournent en parallèle
runner la machine qui exécute les jobs (voir page runners)
artifact des fichiers produits par un job, gardés et passés aux jobs suivants

Si un job échoue, les stages suivants ne tournent pas (c'est ce qu'on veut dans la plupart des cas).

Exemple minimal

stages:
  - build
  - test
  - deploy

build:
  stage: build

  script: |
    npm install
    npm run build

test:
  stage: test

  script: |
    npm test

deploy:
  stage: deploy

  script: |
    npm run deploy

Scripts multi-lignes

Il y a deux moyens de définir des listes en YAML. La première, plus courante, est d'utiliser des -. Ça marche dans la plupart des cas, genre pour les stages:. Cependant, pour les script:, il est préférable d'utiliser cette syntaxe:

script: |
  ligne 1
  ligne 2
La pipe (|) fait en sorte que l'élément qui suit soit traité comme un bloc multi-lignes, évitant d'avoir recours aux - qui, pour une raison sombre, cassent quand on utilise de la syntaxe complexe à base de " et '.

C'est utile pour les script:, mais évitez de l'utiliser aux autres endroits.

Vos yeux vous remerciront

Évitez d'écrire du YAML trop serré, espacez les éléments.

NON:

display-info:
  stage: info
  before_script:
    - apt-get update && apt-get install -y iproute2
  script: |
    echo "Branch: $CI_COMMIT_BRANCH"
    echo "Message: $CI_COMMIT_MESSAGE"
    ip a

OUI:

display-info:
  stage: info

  before_script:
    - apt-get update && apt-get install -y iproute2

  script: |
    echo "Branch: $CI_COMMIT_BRANCH"
    echo "Message: $CI_COMMIT_MESSAGE"
    ip a

Les fields principaux

Mot-clé Rôle
stage l'étape du job
script les commandes du job (obligatoire)
before_script des commandes qui tournent avant script (installer des paquets, npm i...)
image l'image docker du job (ignorée par un runner en mode shell)
tags choisir le runner (ex: shell, self-hosted)
rules conditions pour que le job tourne
artifacts fichiers à garder après le job
needs dépendre d'un job précis, sans attendre tout le stage d'avant
variables définir des variables pour le job

before_script

Pour installer ce qu'il faut avant le script. Sur une image debian par exemple:

display-info:
  stage: info

  before_script:
    - apt-get update && apt-get install -y iproute2

  script: |
    echo "Branch: $CI_COMMIT_BRANCH"
    echo "Message: $CI_COMMIT_MESSAGE"
    ip a

artifacts

build:
  stage: build
  script: |
    npm run build

  artifacts:
    paths:
      - dist/
    expire_in: 1 hour

Les jobs des stages suivants récupèrent automatiquement les artifacts des stages précédents. On peut aussi les télécharger depuis l'interface gitlab.

needs

publish:
  stage: publish
  needs:
    - job: build
      artifacts: true

Variables prédéfinies

GitLab en fournit plein, pas besoin de les définir.
En voici une petite liste, mais elles sont toutes disponibles sur http://192.168.177.129:4000 page "CI/CD variables":

Variable Valeur
$CI_COMMIT_BRANCH nom de la branche (vide sur un tag)
$CI_COMMIT_TAG nom du tag (uniquement si la pipeline vient d'un tag)
$CI_COMMIT_MESSAGE message du commit
$CI_DEFAULT_BRANCH nom de la branche par défaut du repo
$CI_PIPELINE_SOURCE d'où vient la pipeline: push, merge_request_event, schedule, web...
$CI_MERGE_REQUEST_TARGET_BRANCH_NAME branche cible de la merge request (que dans une pipeline de MR)
$CI_OPEN_MERGE_REQUESTS défini si la branche a une MR ouverte
$CI_JOB_TOKEN jeton temporaire du job, pour appeler l'API (ne jamais l'afficher)
$CI_API_V4_URL URL de base de l'API GitLab (ex: <gitlab>/api/v4)
$CI_COMMIT_REF_NAME nom de la branche ou du tag
$CI_COMMIT_SHA hash complet du commit ($CI_COMMIT_SHORT_SHA pour la version courte)
$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME branche source de la MR (que dans une pipeline de MR)
$CI_PROJECT_DIR dossier où le projet est cloné sur le runner
$CI_JOB_NAME nom du job

Pour les secrets (identifiants, etc...), ils vont dans Settings > CI/CD > Variables et on les utilise comme $FTP_USER.
Les valeurs possibles de $CI_PIPELINE_SOURCE sont dans rules (cas avancés).

Les pièges classiques

  • Le job qui ne tourne jamais. Un job avec uniquement rules: - if: '$CI_COMMIT_BRANCH == "main"' + when: never ne tourne jamais, nulle part: sur main la règle dit never, ailleurs aucune règle ne match donc le job est exclu aussi. S'il n'y a que ce job, gitlab refuse même de créer la pipeline (plus aucun job à lancer). Voir rules et workflow.
  • Guillemets. Dans un if:, mettre toute la condition entre guillemets simples, avec les doubles à l'intérieur: '$CI_COMMIT_BRANCH == "main"'.
  • image ne fait rien sur un runner shell. Le job tourne directement sur la machine du runner.