## Introduction

GitLab CI/CD est puissant, mais de petites erreurs peuvent bloquer la livraison. Ce guide se concentre sur les erreurs que vous rencontrerez le plus souvent dans les pipelines réels, pourquoi elles se produisent, comment confirmer la cause racine, et des correctifs sûrs, prêts à copier-coller. Restez pratique : reproduisez le problème avec l'exemple le plus petit, appliquez le plus petit changement sûr, puis généralisez.

Ce que vous obtiendrez :

- Explications claires des messages d'erreur GitLab CI/CD courants

- Reproductions minimales et extraits de jobs adaptables

- Correctifs sûrs par défaut testables localement avant déploiement

## Aperçu du Workflow

Utilisez un flux reproductible qui transforme le bruit en signal :

- Reproduire et capturer le contexte

- Relancez le job échoué avec le même commit.

- Développez toutes les sections réduites dans le log du job. Lisez depuis le haut : infos runner, pull d'image, checkout, before_script , script , after_script , artefacts/upload.

- Notez la ligne qui échoue et la phase concernée.

- Astuce : Activez CI_DEBUG_TRACE=true comme variable CI pour un run unique afin de voir chaque commande exécutée.

- Confirmer la plus petite reproduction

- Mettez en commentaire les étapes non essentielles.

- Durcissez les variables qui affectent le flux.

- Si un service est impliqué (Docker, base de données, Kubernetes), testez avec un job unique et un script minimal.

- Appliquer le plus petit correctif sûr

- Préférez les correctifs de configuration aux contournements par script.

- Ajoutez des garde-fous ( rules , paths , ou timeout explicite) pour prévenir les récidives.

- Vérifier et documenter

- Relancez le job, puis un pipeline complet.

- Ajoutez un court commentaire dans .gitlab-ci.yml près du correctif.

## Erreurs Courantes et Solutions

Voici les échecs fréquents, leurs causes, comment vérifier, et des correctifs sûrs.

### 1) .gitlab-ci.yml Invalide ou Structure YAML Incorrecte

Symptômes

- Le pipeline ne démarre pas, ou vous voyez : "Cette configuration GitLab CI est invalide\)."

- Messages au niveau job comme : "La configuration before_script doit être une chaîne ou une liste de chaînes\)."

Pourquoi ça arrive

- Erreurs d'indentation YAML ou de syntaxe de liste.

- Utilisation d'un mapping là où une liste est attendue, ou vice versa.

Comment diagnostiquer

- Réduisez à un .gitlab-ci.yml minimal avec un seul job echo pour isoler la faute.

- Vérifiez que toutes les listes utilisent des tirets et que toutes les listes de chaînes sont des chaînes simples.

- Validez avec l'outil CI Lint dans GitLab (CI/CD > Éditeur > Lint) ou lancez gitlab-ci-lint localement.

Exemple de correctif sûr

stages: [lint, test]

variables:
 NODE_ENV: 'test'

lint:
 stage: lint
 image: node:20-alpine
 script:
 - node --version
 - npm ci
 - npm run lint

test:
 stage: test
 image: node:20-alpine
 script:
 - npm ci
 - npm test 
 Astuces

- Évitez de mélanger tabulations et espaces.

- Gardez script comme liste de chaînes, pas comme chaîne multiligne unique.

### 2) Pipeline Sans Jobs

Symptômes

- La page du pipeline affiche : "Il n'y a pas de stages/jobs pour ce pipeline." ou rien ne s'exécute pour votre branche/MR.

Pourquoi ça arrive

- rules ou only/except excluent votre ref.

- workflow: rules empêche la création du pipeline.

Comment diagnostiquer

- Inspectez la branche ou l'événement MR et les variables d'environnement ( CI_PIPELINE_SOURCE , CI_COMMIT_BRANCH ).

- Ajoutez temporairement un job fourre-tout pour vérifier la correspondance.

Exemple de correctif sûr avec rules et fallback

workflow:
 rules:
 - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
 - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
 - when: always # assure la création d'un pipeline en cas de doute

build:
 stage: build
 image: alpine:3.20
 rules:
 - changes:
 - src/**
 when: on_success
 - when: manual # fallback visible si aucun changement ne correspond
 script:
 - echo "Construction..." 

### 3) Job Bloqué ou en Attente : Pas de Runners

 Symptômes

- Le statut du job reste en pending avec : "Ce job est bloqué car le projet n'a aucun runner en ligne qui lui est assigné."\

Pourquoi ça arrive

- Aucun runner en ligne, ou les tags du runner ne correspondent pas au job.

- Le runner n'est pas autorisé à s'exécuter sur ce projet ou cette branche protégée.

Comment diagnostiquer

- Comparez les tags du job et du runner dans Settings > CI/CD > Runners .

- Confirmez que le runner est en ligne et non mis en pause.

- Pour les branches protégées, assurez-vous que le runner est marqué protégé ou que le job n'est pas restreint aux refs protégées.

Exemple de correctif sûr : aligner les tags ou supprimer l'exigence de tag

# Si votre runner a le tag 'docker', le job doit l'inclure
build-image:
 tags: ['docker']
 image: docker:24
 services: ['docker:24-dind']
 variables:
 DOCKER_HOST: 'tcp://docker:2375'
 DOCKER_TLS_CERTDIR: ''
 script:
 - docker version
 - docker build -t demo: ci . 

### 4) Docker-in-Docker : Impossible de Se Connecter au Démon Docker

 Symptômes

- "Impossible de se connecter au démon Docker à unix:///var/run/docker.sock. Le démon docker est-il en cours d'exécution ?"\

Pourquoi ça arrive

- Service Docker non démarré, mauvais hôte, ou TLS mal configuré.

- Mismatch MTU sur l'interface réseau (fréquent avec les VPNs).

Comment diagnostiquer

- Affichez les variables d'env et essayez docker info .

- Assurez-vous que l'alias du service correspond au DOCKER_HOST .

Exemple de correctif sûr

image: docker:24
services:
 - name: docker:24-dind
 command: ['--mtu=1460'] # résout les problèmes MTU sur certains réseaux

variables:
 DOCKER_HOST: 'tcp://docker:2375'
 DOCKER_TLS_CERTDIR: ''
 DOCKER_DRIVER: 'overlay2'

build:
 stage: build
 script:
 - docker version
 - docker build -t $CI_REGISTRY_IMAGE:ci-$CI_COMMIT_SHORT_SHA .
 - echo 'Construction terminée' 
 Astuces

- Désactivez TLS pour le service dind dans CI et gardez le réseau du job isolé.

- Si vous utilisez un runner partagé, préférez les images de base petites pour réduire le temps de pull.

### 5) Upload d'Artefacts : Fichier Introuvable

Symptômes

- "Upload des artefacts... AVERTISSEMENT : Aucun fichier à uploader" ou "Impossible de trouver un fichier correspondant à ..."\

Pourquoi ça arrive

- Le chemin est incorrect, les fichiers générés vont dans un autre répertoire, ou le job a échoué avant de les produire.

Comment diagnostiquer

- Ajoutez ls -R pour confirmer les chemins.

- Assurez-vous que le répertoire de travail est $CI_PROJECT_DIR .

Exemple de correctif sûr

test:
 stage: test
 image: node:20-alpine
 script:
 - npm ci
 - npm test -- --reporter=junit --reporter-options output=reports/junit.xml
 - mkdir -p dist && echo ok > dist/health.txt
 artifacts:
 when: always
 paths:
 - reports/junit.xml
 - dist/
 expire_in: '7 days' 

### 6) Le Cache Ne Persiste Pas Entre les Jobs

 Symptômes

- Les dépendances se réinstallent à chaque fois ; le taux de cache hit apparaît à 0%.

Pourquoi ça arrive

- Clé de cache trop large, trop étroite, ou qui change à chaque run.

Comment diagnostiquer

- Affichez la clé de cache et comparez entre jobs (ajoutez echo "Clé cache : $CI_CACHE_KEY" ).

Exemple de correctif sûr : clé basée sur le contenu avec fallback

cache:
 key:
 files:
 - package-lock.json
 paths:
 - node_modules/
 policy: pull-push

install:
 stage: .pre
 image: node:20-alpine
 script:
 - npm ci --cache .npm --prefer-offline
 artifacts:
 paths: [.npm]
 expire_in: '1 day' 

### 7) Échec de Récupération des Sous-modules Git

 Symptômes

- "fatal: could not read Username for 'https://gitlab.com': No such device or address"\

- "fatal: repository not found" pour les sous-modules.

Pourquoi ça arrive

- Les sous-modules utilisent HTTPS sans identifiants, ou pointent vers un projet privé auquel le token ne peut pas accéder.

Comment diagnostiquer

- Affichez .gitmodules et vérifiez les URLs.

- Vérifiez que les projets de sous-modules accordent l'accès à CI_JOB_TOKEN si vous utilisez des chemins relatifs.

Exemple de correctif sûr : utiliser CI_JOB_TOKEN pour HTTPS

variables:
 GIT_SUBMODULE_STRATEGY: 'recursive'
 GIT_SUBMODULE_UPDATE_FLAGS: '--jobs 4'

before_script:
 - git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/" .insteadOf "https://gitlab.com/"

submodule_job:
 stage: test
 image: alpine:3.20
 script:
 - git submodule sync --recursive
 - git submodule update --init --recursive
 - echo 'Sous-modules prêts' 
 Astuces

- Préférez les URLs de sous-modules relatives dans la même instance GitLab pour permettre l'auth CI_JOB_TOKEN .

- Pour des sous-modules cross-instance ou privés, utilisez une clé SSH de déploiement stockée dans une variable CI.

### 8) Variables Protégées Manquantes sur Branches Non Protégées

Symptômes

- docker login ou CLI cloud échoue avec 403 ou erreurs d'auth seulement sur les branches de fonctionnalité.

Pourquoi ça arrive

- Les variables sont marquées protégées et ne sont exposées que sur les refs protégées.

Comment diagnostiquer

- Comparez les drapeaux de protection des variables avec les paramètres de protection de branche dans Settings > CI/CD > Variables .

Exemple de correctif sûr : restreindre le job aux refs protégées quand nécessaire

docker_push:
 stage: deploy
 rules:
 - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
 - if: '$CI_COMMIT_TAG'
 - when: never
 script:
 - echo "$REGISTRY_PASSWORD" | docker login -u "$REGISTRY_USER" --password-stdin "$CI_REGISTRY"
 - docker push $CI_REGISTRY_IMAGE:release 
 Alternative : Si les branches de fonctionnalité ont aussi besoin du secret, déprotégez la variable (moins sécurisé) ou créez une variable non protégée séparée pour le développement.

### 9) Kubernetes : Erreurs kubectl ou Helm

Symptômes

- kubectl : "unable to recognize: no matches for kind ..."\

- Helm : "UPGRADE FAILED: another operation is in progress" ou timeouts.

Pourquoi ça arrive

- Mauvais apiVersion ou CRDs manquantes ; permissions manquantes ; verrous Helm obsolètes ; kubeconfig non chargé.

Comment diagnostiquer

- Affichez kubectl version --client et les versions serveur.

- Lancez kubectl auth can-i ... pour vérifier les permissions.

- Utilisez helm list et helm history pour inspecter l'état du release.

Exemple de correctif sûr : passer kubeconfig via une variable et utiliser les upgrades Helm atomiques

deploy:
 stage: deploy
 image: alpine/helm:3.14.4
 variables:
 KUBECONFIG: '/builds/$CI_PROJECT_PATH/.kube/config'
 before_script:
 - mkdir -p $(dirname "$KUBECONFIG" )
 - echo "$KUBECONFIG_DATA" | base64 -d > "$KUBECONFIG"
 - kubectl version --client
 - kubectl config get-contexts
 script:
 - kubectl apply -f k8s/ns.yaml
 - helm upgrade --install app charts/app \
 --namespace app \
 --create-namespace \
 --atomic --wait --timeout 5m 
 Astuces

- Gardez les versions client kubectl /Helm compatibles avec votre cluster.

- Utilisez --atomic et --wait pour échouer vite et rollback en cas d'erreur.

- Envisagez l'intégration Kubernetes de GitLab pour injecter automatiquement le kubeconfig.

### 10) Job Dépassant la Limite de Temps

Symptômes

- "script exceeded time limit" ou job annulé après une durée fixe.

Pourquoi ça arrive

- Timeout par défaut trop bas ; pulls d'images lents ; cache misses ; suites de tests longues.

Comment diagnostiquer

- Vérifiez la répartition de la durée du job dans les logs.

- Notez les temps de pull d'image et les attentes réseau.

Exemple de correctif sûr : définir un timeout par job et optimiser les pulls

long_tests:
 stage: test
 image: python:3.12-slim
 timeout: 45m
 script:
 - pip install -r requirements.txt
 - pytest -m 'not slow' -n auto --dist loadscope 
 Astuces

- Utilisez des images de base plus petites et activez le cache côté registre quand disponible.

- Divisez les jobs longs en shards parallèles et fusionnez les rapports comme artefacts.

- Ajustez le timeout au niveau projet dans Settings > CI/CD > General pipelines > Timeout si nécessaire.

## Plan Pilote Local

Objectif : valider vos correctifs et patterns avec le plus petit pipeline utile que vous pouvez inspecter localement avant de le déployer sur tous les projets.

Périmètre

- Un repo, un runner partagé ou spécifique au projet.

- Stages : validate, test, build, package.

- Build Docker-in-Docker, cache basique, et un artefact.

Critères de succès

- Pipeline passe en moins de 10 minutes sur un runner propre.

- Cache hit au second run pour les dépendances.

- Aucun job en pending ; aucun avertissement d'upload d'artefacts.

Pipeline pilote de référence

stages: [validate, test, build, package]

default:
 image: docker:24
 services: ['docker:24-dind']
 variables:
 DOCKER_HOST: 'tcp://docker:2375'
 DOCKER_TLS_CERTDIR: ''

validate_yaml:
 stage: validate
 image: alpine:3.20
 script:
 - echo 'Validation de la structure YAML'
 - grep -q 'stages:' .gitlab-ci.yml

unit_tests:
 stage: test
 image: node:20-alpine
 cache:
 key:
 files: [package-lock.json]
 paths: [node_modules/]
 policy: pull-push
 script:
 - npm ci
 - npm test -- --reporter=junit --reporter-options output=reports/junit.xml
 artifacts:
 when: always
 paths: [reports/junit.xml]
 expire_in: '7 days'

build_image:
 stage: build
 tags: ['docker'] # assurez-vous que cela correspond à votre tag runner
 script:
 - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
 - docker build -t $CI_REGISTRY_IMAGE:ci-$CI_COMMIT_SHORT_SHA .
 - docker image ls | head -n 5

package_sbom:
 stage: package
 image: alpine:3.20
 script:
 - mkdir -p out && echo '{"sbom":"demo"}' > out/sbom.json
 artifacts:
 paths: [out/sbom.json]
 expire_in: '7 days' 
 Comment exécuter et inspecter

- Poussez une branche de fonctionnalité et ouvrez une petite MR.

- Confirmez que les tags runner correspondent et que le cache hit au second run.

- Cassez intentionnellement un chemin (ex: artefacts) pour voir l'erreur, puis revenez en arrière.

Déploiement

- Copiez les patterns dans d'autres repos, en ajustant images, tags, et clés de cache.

- Gardez les jobs pilotes comme templates que vous pouvez inclure à travers les projets.

## Conclusion

Vous disposez maintenant d'un ensemble pratique de patterns pour reconnaître et corriger les erreurs GitLab CI/CD les plus courantes :

- Validez le YAML tôt et gardez les scripts simples.

- Assurez la disponibilité des runners et l'alignement des tags.

- Configurez Docker-in-Docker de manière prévisible.

- Produisez les artefacts fiablement et cachez ce qui est coûteux à reconstruire.

- Authentifiez correctement les sous-modules et registres.

- Déployez sur Kubernetes avec kubeconfig explicite, attentes, et rollbacks atomiques.

- Contrôlez les timeouts et parallélisez les tâches longues.

Prochaines étapes

- Implémentez le pipeline pilote et enregistrez les métriques de référence.

- Corrigez d'abord l'erreur la plus douloureuse dans votre environnement, puis étendez.

- Gardez les changements petits, observables, et faciles à annuler.