CI GitLab¶
L'autre moitié du test, ce sont les pipelines GitLab. C'est composé de:
- cette page: les bases du
.gitlab-ci.yml - Rules et workflow: décider quand un job (ou la pipeline entière) tourne
- Runners et publication: qui exécute les jobs, et comment publier en ftp
- Rules (cas avancés): regex, opérateurs, pipelines manuelles ou planifiées
- Mots-clés avancés:
default,extends,cache,needs,allow_failure... - Exercice preparation324: MR + tag + appel d'API (pre-test)
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
|) 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: neverne tourne jamais, nulle part: surmainla règle ditnever, 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"'. imagene fait rien sur un runner shell. Le job tourne directement sur la machine du runner.