Formation CI/CD complète

Guide gratuit – Économisez vos 2500 € de formation DevOps !

Introduction à la CI/CD

La CI/CD (Intégration Continue / Déploiement Continu) est aujourd’hui le socle de toute organisation qui veut livrer plus vite, plus souvent et avec moins de bugs. C’est un ensemble de pratiques et d’outils qui permettent de transformer chaque commit en un artefact testé, validé, et parfois directement déployé.

CI (Continuous Integration)

  • Chaque commit déclenche automatiquement un build et une batterie de tests.
  • On détecte rapidement les régressions.
  • On partage un tronc commun toujours valide.

CD (Continuous Delivery / Deployment)

  • Les builds validés sont automatiquement mis en staging ou en production.
  • Réduit le time-to-market.
  • Favorise les déploiements fréquents et sécurisés.
💡 L’idée fondatrice : "Si ça marche en local, ça doit marcher partout – et sans clic manuel".

Panorama des outils CI/CD

Il existe des dizaines d’outils CI/CD sur le marché, mais dans cette formation nous allons nous concentrer sur les 5 plus utilisés et incontournables :

  1. GitHub Actions – natif GitHub, parfait pour les projets open source et cloud natifs.
  2. GitLab CI – intégré directement dans GitLab, riche et complet.
  3. Jenkins – le vétéran open source, extrêmement flexible et extensible.
  4. Azure DevOps – plébiscité dans les environnements Microsoft/Enterprise.
  5. CircleCI – outil cloud-first très apprécié pour sa simplicité et ses optimisations.
👉 Ces 5 plateformes couvrent 80% des cas réels. Les autres (Travis CI, Bamboo, TeamCity, Harness, Spinnaker…) sont moins répandues mais reposent sur les mêmes concepts.

GitHub Actions

GitHub Actions est le moteur CI/CD intégré directement dans GitHub. Il permet de déclencher des workflows en réponse à des événements (push, pull request, release, cron…).

Exemple minimal

# .github/workflows/ci.yml
name: Java CI with Maven

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      - name: Build with Maven
        run: mvn clean verify

Ce pipeline compile le projet, exécute les tests et remonte les résultats dans l’onglet "Actions".

GitLab CI

GitLab CI est totalement intégré à GitLab. La configuration se fait via un fichier .gitlab-ci.yml à la racine du projet.

Exemple minimal

# .gitlab-ci.yml
stages:
  - build
  - test

build-job:
  stage: build
  image: maven:3.9.4-eclipse-temurin-17
  script:
    - mvn clean compile

test-job:
  stage: test
  image: maven:3.9.4-eclipse-temurin-17
  script:
    - mvn test

Chaque stage s’exécute dans un conteneur. Ici, le build précède les tests.

Jenkins

Jenkins est le vétéran du CI/CD. Open source, il repose sur des pipelines déclaratifs écrits dans un Jenkinsfile.

Exemple minimal

// Jenkinsfile
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        sh 'mvn clean compile'
      }
    }
    stage('Test') {
      steps {
        sh 'mvn test'
      }
    }
  }
}

Jenkins est extrêmement extensible grâce à ses plugins, mais nécessite une maintenance continue (serveur, mises à jour, sécurité).

Azure DevOps

Azure DevOps propose un moteur de pipelines YAML très riche, orienté Enterprise et multi-langages.

Exemple minimal

# azure-pipelines.yml
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: Maven@3
    inputs:
      mavenPomFile: 'pom.xml'
      goals: 'clean verify'

L’avantage d’Azure : intégration native avec Azure Repos, Boards, Artifacts et les environnements de déploiement.

CircleCI

CircleCI est un outil CI/CD cloud-first, apprécié pour sa simplicité et son exécution rapide. La configuration se fait dans .circleci/config.yml.

Exemple minimal

# .circleci/config.yml
version: 2.1
jobs:
  build:
    docker:
      - image: cimg/openjdk:17.0
    steps:
      - checkout
      - run: mvn clean verify

workflows:
  version: 2
  ci-workflow:
    jobs:
      - build

CircleCI est particulièrement adapté aux projets SaaS et start-ups, avec des pipelines très rapides.

✅ À ce stade, vous avez vu comment écrire un pipeline minimal dans chacun des 5 outils majeurs. La suite va montrer un cas concret avec Selenium Web + Java.

Exemple complet – Selenium + Java

Pour illustrer l’intégration CI/CD, nous allons utiliser un test automatisé simple écrit en Java + Selenium WebDriver, exécuté avec Maven.

1. Code du test Selenium


import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.junit.*;

public class GoogleSearchTest {
    private static WebDriver driver;

    @BeforeClass
    public static void setup() {
        driver = new ChromeDriver();
    }

    @Test
    public void testSearch() {
        driver.get("https://www.google.com");
        WebElement searchBox = driver.findElement(By.name("q"));
        searchBox.sendKeys("CI/CD Selenium");
        searchBox.submit();
        Assert.assertTrue(driver.getTitle().contains("CI/CD"));
    }

    @AfterClass
    public static void tearDown() {
        if (driver != null) driver.quit();
    }
}

Ce test ouvre Google, recherche « CI/CD Selenium » et vérifie que le titre contient bien la requête.

2. Dépendances Maven

<dependencies>
  <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.21.0</version>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
  </dependency>
</dependencies>

3. Intégration dans GitHub Actions

# .github/workflows/selenium.yml
name: Selenium CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      - name: Setup Chrome
        uses: browser-actions/setup-chrome@v1
      - name: Run tests
        run: mvn test

Ici, GitHub Actions installe Chrome, Java et exécute directement le test Selenium dans un job CI.

🔎 Le même test peut être exécuté dans GitLab CI, Jenkins ou Azure DevOps simplement en changeant la configuration YAML ou le Jenkinsfile, sans modifier le code.

Bonnes pratiques CI/CD

Construire un pipeline CI/CD efficace ne se résume pas à « lancer des tests ». Voici les principes clés à respecter.

1. Pipelines rapides

  • Évitez les étapes inutiles (build inutile si pas de modifs côté code source).
  • Cachez vos dépendances Maven/NPM pour accélérer les builds.
  • Exécutez les tests en parallèle dès que possible.

2. Pipelines reproductibles

  • Utilisez des images Docker figées avec des versions précises.
  • Bloquez les dépendances (lockfiles, pom.xml, package-lock.json).

3. Intégration continue stricte

  • Chaque commit doit déclencher un pipeline complet.
  • N’acceptez pas de merge si les tests échouent.
  • Faites tourner les tests critiques en pre-merge.

4. Visibilité et feedback

  • Publiez des rapports HTML (Surefire, Allure) en artefacts du pipeline.
  • Ajoutez des captures d’écran et des logs pour les tests UI.
  • Envoyez les résultats sur Slack/Teams pour l’équipe.

5. Sécurité

  • Stockez vos secrets (tokens, credentials) dans le gestionnaire natif (GitHub Secrets, GitLab Variables…).
  • Ne les mettez jamais en clair dans le YAML ou le Jenkinsfile.
  • Scannez vos dépendances (Snyk, Dependabot, Trivy).

6. Maintenance

  • Gardez vos runners/agents à jour (OS, versions de Java, ChromeDriver).
  • Sur Jenkins : surveillez la dette technique (plugins obsolètes, jobs orphelins).
✅ Un pipeline CI/CD bien conçu doit être rapide, fiable et transparent. C’est le garant d’une industrialisation réussie des tests automatisés.

Ressources complémentaires

Pour aller plus loin dans la compréhension et la pratique du CI/CD, voici une sélection de ressources fiables et régulièrement mises à jour :

📚 Ces lectures forment une base solide pour renforcer vos connaissances et rester à jour face aux évolutions rapides des outils et des pratiques DevOps.

🔐 Secrets & Runners dans les plateformes CI/CD

Cette section couvre la configuration des secrets (tokens, mots de passe, clés API) et des runners/agents (machines d’exécution) sur les cinq solutions CI/CD les plus utilisées : GitHub Actions, GitLab CI/CD, Azure DevOps, CircleCI et Jenkins. Pour chaque outil, nous détaillons :

  • 📌 Où déclarer les secrets et à quel niveau (projet, organisation, environnement).
  • 📌 Comment consommer ces secrets dans les pipelines (YAML, Groovy, scripts).
  • 📌 Les types de runners/agents disponibles (hébergés vs self-hosted) et leur configuration.
  • 📌 Les bonnes pratiques de sécurité (masquage, rotation, audit, isolement).
  • 📌 L’intégration avec des gestionnaires externes comme Vault, AWS Secrets Manager ou Azure Key Vault.

👉 L’objectif : sécuriser vos pipelines et garantir que vos jobs CI/CD tournent sur des agents maîtrisés, avec un contrôle fin des accès et une hygiène irréprochable des secrets.

GitHub Actions

Configuration des secrets

  • Interface : Dans GitHub, chaque dépôt dispose d’une section Settings > Security > Secrets and variables > Actions. On clique sur New repository secret pour ajouter un secret. Pour les secrets au niveau de l’organisation, on va dans les Settings de l’organisation, puis Secrets and variables > Actions et New organization secret.
  • Niveaux de secrets : GitHub Actions supporte les secrets au niveau du dépôt (Repository), des environnements (Environment) et de l’organisation. Les secrets d’environnement s’ajoutent via Settings > Environments puis on sélectionne l’environnement et Add secret. Les secrets d’organisation peuvent être limités à certains dépôts grâce à des politiques d’accès.
  • Consommation dans les workflows : Dans un workflow YAML, on accède aux secrets via le contexte ${{ secrets.NOM_DU_SECRET }}. Exemple :
    steps:
      - name: Exécuter mon action
        with:
          super_secret: ${{ secrets.SuperSecret }}
        env:
          SUPER_SECRET: ${{ secrets.SuperSecret }}
    Ce qui masque la valeur en sortie (affichée comme ***). ⚠️ Attention : les secrets ne sont pas accessibles dans les conditions if: sans les mapper dans des variables d’environnement.

Runners GitHub Actions

  • Runners managés : GitHub fournit des runners hébergés dans le cloud (GitHub-hosted) avec des images préconfigurées (par exemple ubuntu-latest). Chaque job s’exécute sur une VM fraîchement provisionnée, jetable après exécution. Avantage : zéro maintenance et environnement isolé.
  • Runners auto-hébergés : On installe le service GitHub Runner sur ses machines. Dans l’interface GitHub (dépôt ou organisation), on clique sur Settings > Actions > Runners > New self-hosted runner. On choisit le système d’exploitation, on télécharge et lance le binaire avec l’URL de dépôt et le token d’enregistrement. Le runner s’enregistre via la commande gitHubActions-runner register (interactif ou non-interactif). Les runners auto-hébergés peuvent être tagués avec des étiquettes (labels) lors de l’enregistrement. Exemple dans le YAML :
    runs-on: [self-hosted, ubuntu-latest, my-label]
  • Mise à jour des runners : Par défaut, les runners s’auto-mettent à jour. On peut désactiver ce comportement avec --disableupdate. ⚠️ Si désactivé : au bout de 30 jours sans mise à jour, le runner ne pourra plus traiter de jobs tant qu’il n’aura pas été mis à jour manuellement.

Balisage et filtrage des runners

  • Les jobs utilisent la directive runs-on pour sélectionner les runners. Exemple : runs-on: self-hosted cible tous les runners auto-hébergés. On peut spécifier plusieurs labels :
    runs-on: [self-hosted, linux, x86_64, my-custom-label]
    Pour l’échelle, on peut définir des Runner groups et cibler un groupe via :
    runs-on:
      group: mon-groupe

Bonnes pratiques de sécurité

  • Masquage : GitHub masque automatiquement les secrets dans les logs. On peut aussi appliquer manuellement ::add-mask::VALEUR.
  • Accès restreint : Limiter la visibilité des secrets (environnements protégés, dépôts limités). Contrôler via les rôles GitHub (admin/collaborator). Auditer régulièrement les logs et les PRs pour éviter les fuites accidentelles.
  • Rotation : Renouveler régulièrement les clés et tokens. Préférer l’authentification OIDC (vers Azure, AWS, Vault) pour éviter de stocker des clés statiques.
  • Isolation réseau : Utiliser des runners éphémères (« ephemeral runners ») qui démarrent pour un seul job puis se détruisent.
  • Nettoyage : Les runners GitHub hébergés sont jetables. Sur des runners auto-hébergés, il faut configurer le nettoyage du workspace et des variables après chaque job.

Intégration avec des gestionnaires externes

  • HashiCorp Vault : Intégration possible via OIDC. Utiliser l’action hashicorp/vault-action pour extraire des secrets en runtime.
  • AWS Secrets Manager : Utiliser l’action AWS officielle. Authentification recommandée via OIDC/IAM Roles for Service Accounts, plutôt que de stocker des clés AWS dans GitHub.
  • Azure Key Vault : Intégration via OIDC avec l’action azure/login ou azure/keyvault. Microsoft fournit des workflows complets pour cette configuration.

GitLab CI/CD

Configuration des secrets (CI/CD variables)

  • Interface : Dans GitLab, pour un projet donné, aller dans Settings > CI/CD > Variables et cliquer sur Add variable. Pour un groupe : Settings > CI/CD > Variables puis Add variable. Au niveau de l’instance (self-managed), les administrateurs ajoutent des variables globales via Admin Area > Settings > CI/CD > Variables.
  • Niveaux et portées : GitLab distingue les variables au niveau projet, groupe ou instance. Les variables de groupe sont héritées par tous les projets du groupe (et sous-groupes). On peut définir une environment scope pour limiter une variable à un ou plusieurs environnements (Premium+). Les variables peuvent être Protected (utilisables seulement sur branches/tags protégés) ou Masked (masquées dans les logs).
  • Consommation : Dans .gitlab-ci.yml, les variables sont exposées comme variables d’environnement. Exemple :
    job:
      script:
        - echo "Mon secret est $MY_SECRET"
    Les variables définies dans l’UI sont automatiquement injectées dans le job.

Runners GitLab CI/CD

  • Runners managés (GitLab-hosted) : GitLab.com propose des shared runners gérés par GitLab. Ces runners tournent sur des VMs jetables, automatiquement redimensionnées selon la demande. Idéal pour démarrer rapidement sans maintenance.
  • Runners auto-hébergés : On installe GitLab Runner sur ses propres serveurs. Trois niveaux possibles :
    • Instance Runner : via Admin Area > CI/CD > Runners > New instance runner.
    • Group Runner : dans Settings > CI/CD > Runners d’un groupe, cliquer sur New group runner.
    • Project Runner : dans Settings > CI/CD > Runners d’un projet, cliquer sur New project runner.
    Chaque fois, GitLab fournit un token et une commande gitlab-runner register pour enregistrer le runner. On y définit description, tags, executor (Docker, Shell, Kubernetes, etc.).
  • Mise à jour des runners : GitLab Runner ne s’auto-met pas à jour. Il faut télécharger et déployer manuellement les nouvelles versions du binaire. GitLab recommande de surveiller les versions publiées pour maintenir la compatibilité.

Balisage et utilisation des runners

  • Les runners GitLab utilisent des tags pour filtrer les jobs. Lors de l’enregistrement, on assigne des tags (ex. docker, ubuntu). Dans le YAML :
    deploy_prod:
      stage: deploy
      tags: ["k8s", "privileged"]
      script:
        - echo "Déploiement en production"
    Seuls les runners portant ces tags prendront ce job. Si aucun tag n’est défini, il faut activer les runners non tagués dans l’UI.

Bonnes pratiques de sécurité

  • Masquage : Les variables marquées Masked sont remplacées par [MASKED] dans les logs. ⚠️ Certaines valeurs simples (courtes, booléennes) ne sont pas masquées correctement. Pour les secrets sensibles, privilégier un gestionnaire externe (Vault, Key Vault).
  • Accès restreint : Utiliser des variables Protected pour éviter leur usage sur des branches non protégées. Restreindre les droits : seul un Maintainer peut créer des variables, un Reviewer peut les consommer. Vérifier les MR pour éviter de compromettre les secrets.
  • Rotation : Renouveler régulièrement les clés stockées dans GitLab. Utiliser OIDC pour connecter GitLab à un gestionnaire de secrets externe, sans stockage direct.
  • Isolation réseau : Héberger les runners auto-gérés dans un réseau privé/VPC. Utiliser des exécuteurs Docker ou Kubernetes pour isoler chaque job dans un conteneur.
  • Nettoyage : Les runners conservent des répertoires de travail (builds/). Configurer la purge automatique via config.toml ou tâches cron. En mode Docker, les conteneurs sont supprimés après chaque job.

Intégration avec des gestionnaires externes

  • HashiCorp Vault : Intégration native (Premium+). Les secrets sont extraits à l’exécution via OIDC et injectés dans le job.
  • Azure Key Vault : Possibilité de lier une variable de groupe à un Key Vault. Les secrets sont récupérés dynamiquement au runtime.
  • Google Secret Manager : Disponible via intégrations externes ou API. Un job peut exécuter gcloud secrets versions access pour lire un secret de GSM.

Azure DevOps

Configuration des secrets

  • Interface : Dans Azure DevOps, les secrets sont gérés comme des variables sécurisées dans des groupes de variables. Pour un projet, aller dans Pipelines > Library > + Variable group. On crée un groupe, on ajoute les variables et on active l’icône cadenas pour les marquer comme secret. Les valeurs ne sont plus visibles après enregistrement.
  • Niveaux et portées : Les groupes de variables peuvent être définis au niveau projet, puis attachés à plusieurs pipelines. Ils peuvent aussi être liés à des environnements ou des releases. L’accès se contrôle via les paramètres de sécurité du groupe.
  • Consommation dans les pipelines : Dans un pipeline YAML, on référence les variables avec la syntaxe $(NOM_VARIABLE). Exemple :
    - bash: |
        echo "Le secret est $SECRET_ONE"
      env:
        SECRET_ONE: $(MaVariableSecret)
    Les secrets sont automatiquement masqués dans les logs (affichés comme ***).

Runners Azure Pipelines

  • Agents managés (Microsoft-hosted) : Azure fournit des agents hébergés avec des images préconfigurées (ubuntu-latest, windows-2022, etc.). Chaque job s’exécute sur une machine éphémère et isolée.
  • Agents auto-hébergés : Un administrateur crée un Agent Pool dans Project Settings > Agent pools > Add pool. On télécharge le package d’agent et on exécute config.sh ou config.cmd avec un PAT. L’agent s’enregistre dans le pool et attend les jobs. Plusieurs agents peuvent cohabiter sur une même machine si nécessaire.
  • Mises à jour : Les agents managés sont mis à jour par Microsoft. Les auto-hébergés doivent être mis à jour manuellement en téléchargeant les nouvelles versions.

Balisage et ciblage des agents

  • Azure utilise des Agent Pools et des capabilities/demands. Exemple dans un YAML :
    pool:
      name: Default
    On peut ajouter des demands pour cibler des capacités spécifiques (logiciels installés, variables d’environnement).

Bonnes pratiques de sécurité

  • Masquage : toutes les variables marquées secret sont masquées par défaut dans les logs.
  • Accès restreint : limiter les permissions sur les groupes de variables aux seuls utilisateurs autorisés.
  • Rotation : renouveler régulièrement les clés et utiliser de préférence Azure Key Vault.
  • Isolation réseau : placer les agents auto-hébergés dans des VNets sécurisés.
  • Nettoyage : configurer la suppression automatique des fichiers temporaires et workspaces après chaque job.

Intégration avec des gestionnaires externes

  • Azure Key Vault : intégration native via Link secrets from Azure Key Vault. Les secrets sont injectés directement en runtime.
  • HashiCorp Vault : intégration possible via OIDC ou CLI, avec une Service Connection.
  • AWS Secrets Manager : accessible via une Service Connection AWS et l’AWS CLI, de préférence avec OIDC/IAM Roles.

CircleCI

Configuration des secrets

  • Interface projet : Dans l’UI CircleCI, accéder à Project Settings > Environment Variables. Cliquer sur Add Environment Variable, saisir nom et valeur. Les variables sont chiffrées et ne sont plus lisibles après création. Pour les projets publics, elles ne sont jamais exposées publiquement.
  • Contexts d’organisation : CircleCI propose les Contexts pour partager des secrets entre projets. Dans Organization Settings > Contexts, on crée un contexte et on ajoute des variables. Dans un job YAML, on ajoute context: [mon-context]. Les jobs héritent des variables de ce contexte, et on peut en combiner plusieurs.
  • Masquage : Les variables et contexts ajoutés via l’UI sont masqués automatiquement dans les logs (affichés comme ****). Attention aux commandes shell avec set -x qui peuvent bypasser ce masquage.
  • Consommation : Dans .circleci/config.yml, les variables sont injectées automatiquement. Exemple : echo $MY_SECRET dans un job. On peut aussi ajouter des clés SSH via Project Settings > SSH Permissions.

Runners CircleCI

  • Runners managés (cloud) : Par défaut, CircleCI exécute les jobs sur son infrastructure cloud (VMs/containers). On choisit un resource_class dans le YAML, ex. resource_class: large. Les environnements sont maintenus et mis à jour par CircleCI.
  • Runners auto-hébergés : CircleCI propose des runners à déployer soi-même : – Machine runner (VM ou serveur hôte) – Container runner (cluster Kubernetes, pods). On télécharge l’agent, on l’enregistre avec un token dans Project Settings > Runners. Dans le YAML, on spécifie resource_class: machine pour cibler un runner auto-hébergé.
  • Resource Classes : CircleCI n’utilise pas de labels personnalisés mais des classes prédéfinies (small, medium, large, etc.). Les runners auto-hébergés peuvent être configurés pour accepter certaines classes.

Bonnes pratiques de sécurité

  • Masquage : ne jamais afficher volontairement une variable sensible dans les logs.
  • Rotation : renouveler régulièrement les secrets et mettre à jour les contexts.
  • Isolation réseau : placer les runners auto-hébergés dans un réseau sécurisé (VPC, firewall).
  • Nettoyage : configurer la suppression des répertoires de travail et conteneurs après chaque job.

Intégration avec des gestionnaires externes

  • HashiCorp Vault : Support via OIDC. On configure un rôle Vault qui fait confiance à CircleCI, puis un orb ou script pour récupérer les secrets.
  • AWS Secrets Manager : Récupération via AWS CLI ou orb officiel. L’authentification se fait de préférence avec OIDC/IAM Role plutôt que des clés statiques.
  • Azure Key Vault : Utilisable via Azure CLI dans un job. Exemple :
    - run:
        name: Récupérer un secret Key Vault
        command: |
          az login --identity
          SECRET=$(az keyvault secret show \
            --name mon-secret \
            --vault-name mon-vault \
            --query value -o tsv)
          echo $SECRET

Jenkins

Configuration des credentials (secrets)

  • Interface : Dans Jenkins, les secrets sont gérés via le Credentials Provider. Aller dans Manage Jenkins > Credentials, puis choisir l’emplacement (par ex. System > Global credentials). Cliquer sur Add Credentials et sélectionner le type : texte simple, couple utilisateur/mot de passe, clé SSH, certificat, etc. Chaque secret reçoit un ID unique (ex. jenkins-token-xyz).
  • Portée : Les credentials peuvent être définis avec un scope Global (utilisable par tous les jobs) ou System (pour Jenkins lui-même). Il est aussi possible d’utiliser les Domains pour isoler les credentials selon les jobs ou dossiers.
  • Utilisation dans les Pipelines : Dans un Jenkinsfile, on utilise les IDs pour injecter les secrets :
    pipeline {
      agent any
      environment {
        MY_SECRET = credentials('jenkins-token-xyz')
      }
      stages {
        stage('Test') {
          steps {
            sh 'echo "Le secret est $MY_SECRET"'
          }
        }
      }
    }
    Jenkins masque automatiquement la valeur dans les logs (affichée comme ****).

Agents Jenkins

  • Agents auto-hébergés : Ajouter des nodes via Manage Jenkins > Manage Nodes and Clouds > New Node. Choisir Permanent Agent, définir le répertoire racine, les labels, et la méthode de lancement (SSH, JNLP). Un agent SSH requiert des credentials valides, et un agent JNLP se connecte via le fichier agent.jar.
  • Labels : Chaque agent peut avoir un ou plusieurs labels (ex. linux, docker). Dans un pipeline :
    pipeline {
      agent none
      stages {
        stage('Build') {
          agent { label 'docker' }
          steps {
            sh 'echo "Hello depuis l’agent Docker"'
          }
        }
      }
    }
    Seuls les agents portant le label docker exécuteront le job.
  • Mise à jour : Les agents JNLP reçoivent automatiquement la nouvelle version du agent.jar depuis le contrôleur. Pour les agents SSH, il faut surveiller la compatibilité Java et mettre à jour manuellement si nécessaire.

Bonnes pratiques de sécurité

  • Masquage : Utiliser les mécanismes intégrés (credentials(), withCredentials) pour s’assurer que les secrets ne sont jamais affichés en clair.
  • Accès restreint : Gérer les droits avec la sécurité matricielle. Limiter la création et l’utilisation des credentials aux rôles appropriés.
  • Rotation : Renouveler régulièrement les clés et tokens stockés. Automatiser la rotation si possible.
  • Isolation réseau : Héberger les agents dans des environnements contrôlés (VPC, conteneurs Docker, VM privées). Restreindre leurs accès réseau.
  • Nettoyage : Configurer le nettoyage des workspaces après chaque job (Wipe out workspace ou deleteDir() dans pipeline). Supprimer les fichiers temporaires et variables d’environnement sensibles.

Intégration avec des gestionnaires externes

  • HashiCorp Vault : via le plugin HashiCorp Vault Plugin. Permet d’injecter dynamiquement des secrets dans les jobs Jenkins en se connectant à Vault via AppRole ou OIDC.
  • AWS Secrets Manager : via le plugin AWS Secrets Manager Credentials Provider, qui expose directement les secrets comme credentials Jenkins. Alternativement, appel de l’AWS CLI dans les pipelines.
  • Azure Key Vault : via le plugin Azure Key Vault. Les secrets sont importés depuis un coffre-fort Azure et injectés dans les jobs sous forme de variables d’environnement.

✨ Conclusion

La gestion des secrets 🔐 et des runners/agents ⚙️ est une pierre angulaire de toute stratégie CI/CD sérieuse. Peu importe la plateforme choisie (GitHub Actions, GitLab CI/CD, Azure DevOps, CircleCI ou Jenkins), les mêmes fondamentaux s’appliquent :

  • 📦 Stocker les secrets de manière centralisée et sécurisée
  • 🙈 Garantir leur masquage dans les logs
  • 🚦 Restreindre leur usage aux branches ou environnements sensibles
  • 🔄 Assurer une rotation régulière des clés et tokens
  • 🛡️ Maintenir une isolation stricte des environnements et des agents

L’intégration avec des gestionnaires externes comme HashiCorp Vault, AWS Secrets Manager ou Azure Key Vault est désormais une bonne pratique incontournable.

  • ✅ Elle permet de déléguer le stockage et la rotation des secrets à des solutions spécialisées
  • ✅ Elle simplifie l’audit et la conformité (GDPR, ISO, SOC2)
  • ✅ Elle renforce la sécurité en éliminant le besoin de secrets codés en dur

🚀 La maturité d’une équipe CI/CD se mesure souvent à sa discipline autour des secrets et de l’hygiène des runners. Une simple erreur — fuite de clé API, agent mal isolé, secret exposé dans un script — peut anéantir en quelques minutes la confiance bâtie après des mois d’automatisation.

À l’inverse, une gestion rigoureuse et proactive des secrets et des agents devient un socle invisible mais vital 🪨 : elle garantit la résilience, la conformité et le professionnalisme de vos pipelines, et permet de livrer vos applications avec fiabilité, rapidité et sérénité. ✨

📖 Erreurs fréquentes et HOWTO – Le carnet du pipelineur aguerri

Voici le répertoire complet des erreurs, architectures et bonnes pratiques CI/CD. 30 cartes, organisées par catégories, pour couvrir les problèmes réels rencontrés en intégration continue et donner des solutions concrètes.

❌ Erreur 1 – Pipeline rouge permanent

Symptôme : Aucun commit ne passe.

Cause : Tests instables (flaky) ou dépendances externes.

Solution : Stabiliser les tests, mocker les API externes.

❌ Erreur 2 – Build trop long

Symptôme : +30 min pour un pipeline.

Cause : Pas de cache Maven/NPM, trop de jobs séquentiels.

Solution : Activer le caching et paralléliser les jobs.

❌ Erreur 3 – Secret exposé

Symptôme : Token ou mot de passe dans le repo.

Cause : Variable codée en dur dans le YAML.

Solution : Utiliser GitHub Secrets, GitLab Variables, Azure Key Vault.

❌ Erreur 4 – Version mismatch

Symptôme : Les tests passent en local mais échouent en CI.

Cause : Versions différentes de Java, ChromeDriver, Node…

Solution : Utiliser des images Docker fixes et versions figées.

❌ Erreur 5 – Timeout pipeline

Symptôme : Le pipeline s’arrête après 60 min.

Cause : Tests trop lourds ou blocage.

Solution : Split en pipelines plus courts, surveiller les jobs gourmands.

⚙️ GitHub 6 – Actions manquantes

Symptôme : Impossible de lancer Chrome ou Java.

Cause : Pas de step setup-java ou setup-chrome.

Solution : Ajouter les actions officielles GitHub Marketplace.

⚙️ GitHub 7 – Permissions insuffisantes

Symptôme : Job échoue lors de l’accès aux packages.

Cause : Droits non configurés.

Solution : Ajouter permissions: write-all ou affiner les droits.

⚙️ GitLab 8 – Runner indisponible

Symptôme : Jobs en attente indéfiniment.

Cause : Aucun runner enregistré pour le projet.

Solution : Enregistrer un runner avec gitlab-runner register.

⚙️ GitLab 9 – Cache non pris en compte

Symptôme : Dépendances rechargées à chaque job.

Cause : Mauvaise clé de cache.

Solution : Utiliser des clés dynamiques liées au pom.xml ou package.json.

🏗️ Jenkins 10 – Plugins obsolètes

Symptôme : Jenkins plante après mise à jour.

Cause : Plugins incompatibles.

Solution : Surveiller les changelogs et tester sur un Jenkins de pré-prod.

🏗️ Jenkins 11 – Jobs spaghetti

Symptôme : Jobs manuels imbriqués, impossibles à maintenir.

Cause : Pas de pipelines déclaratifs.

Solution : Migrer vers Jenkinsfile déclaratif.

💡 Azure 12 – Variables mal gérées

Symptôme : Secrets exposés dans les logs.

Cause : Mauvaise déclaration de variables.

Solution : Déclarer comme secret variables dans Azure.

💡 Azure 13 – Agents saturés

Symptôme : Pipelines lents.

Cause : Agents partagés trop utilisés.

Solution : Passer à des agents self-hosted.

✅ CircleCI 14 – Config invalide

Symptôme : Le job n’apparaît pas.

Cause : YAML mal indenté ou version manquante.

Solution : Vérifier le schéma et la version (2.1 recommandé).

✅ CircleCI 15 – Cache ignoré

Symptôme : Dépendances rechargées.

Cause : Pas de save_cache / restore_cache.

Solution : Ajouter les steps de caching dans le job.

🔎 Carte 16 – Rapports HTML

Symptôme : Résultats illisibles dans la console.

Cause : Pas de reporting.

Solution : Publier Allure, Surefire ou Extent Reports en artefacts.

🔎 Carte 17 – Notifications d’équipe

Symptôme : L’équipe ne sait pas si ça casse.

Cause : Pas d’intégration Slack/Teams.

Solution : Ajouter un webhook vers l’outil de communication.

🔎 Carte 18 – Tests flaky

Symptôme : Résultats aléatoires.

Cause : Attentes mal gérées ou dépendance réseau.

Solution : Stabiliser avec des retries et des mocks.

🛠️ Exercice Guidé : Construire un pipeline CI/CD complet avec Selenium

Cet exercice a pour objectif de vous entraîner à créer un pipeline CI/CD réel avec GitHub Actions. Nous allons partir d’un projet Java Maven vierge, écrire des tests Selenium, configurer un workflow YAML, ajouter du caching, générer des rapports, envoyer des notifications, et élargir le pipeline aux autres plateformes (GitLab, Jenkins, Azure, CircleCI).

🎯 Objectif pédagogique : comprendre toutes les étapes d’un pipeline moderne, et acquérir des réflexes de rapidité, de fiabilité, et de sécurité dans vos projets.

Étape 1 : Préparer le projet Maven

Créez un projet Java Maven avec l’arborescence standard :

my-project/
 ├─ pom.xml
 ├─ src/
 │   ├─ main/java
 │   └─ test/java

Maven est idéal car il gère les dépendances (Selenium, JUnit) et s’intègre naturellement avec les CI.

Étape 2 : Définir le pom.xml complet

Ajoutez les dépendances nécessaires à Selenium et JUnit 5, ainsi que les plugins utiles :

<dependencies>
  <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.21.0</version>
  </dependency>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.9.0</version>
    <scope>test</scope>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>3.0.0</version>
    </plugin>
  </plugins>
</build>
💡 Astuce : figer les versions (Java, Selenium, JUnit) est crucial pour éviter les « works on my machine ».

Étape 3 : Écrire un premier test Selenium

Exemple simple pour vérifier la page Google :


import org.junit.jupiter.api.*;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

class GoogleTest {
  WebDriver driver;

  @BeforeEach
  void setup() {
    driver = new ChromeDriver();
  }

  @Test
  void testGoogleHomePage() {
    driver.get("https://www.google.com");
    Assertions.assertTrue(driver.getTitle().contains("Google"));
  }

  @AfterEach
  void teardown() {
    driver.quit();
  }
}

👉 Vérifiez en local avec : mvn clean test.

Étape 4 : Créer le workflow GitHub Actions minimal

Ajoutez .github/workflows/ci.yml :

name: Java CI with Selenium

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: 17
      - run: mvn clean test

✅ À ce stade, les tests s’exécutent déjà en CI !

Étape 5 : Ajouter le cache Maven

Pour accélérer les pipelines, cachez le répertoire Maven :

- name: Cache Maven packages
  uses: actions/cache@v3
  with:
    path: ~/.m2/repository
    key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
    restore-keys: |
      ${{ runner.os }}-maven-

🔥 Gain de plusieurs minutes par exécution.

Étape 6 : Installer Chrome et ChromeDriver

Ajoutez l’action officielle pour Chrome :

- name: Setup Chrome
  uses: browser-actions/setup-chrome@v1

Chrome est nécessaire pour exécuter Selenium en CI.

Étape 7 : Lancer Selenium en mode headless

Modifiez votre test pour passer Chrome en mode headless :


ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new");
driver = new ChromeDriver(options);

✅ Recommandé en CI pour exécuter sans interface graphique.

Étape 8 : Générer un rapport HTML

Ajoutez le plugin Surefire ou Allure pour publier un rapport lisible :

- name: Upload Surefire Report
  uses: actions/upload-artifact@v4
  with:
    name: surefire-reports
    path: target/surefire-reports/

📊 Les artefacts permettent d’analyser les échecs facilement.

Étape 9 : Ajouter une notification Slack/Teams

Intégrez une étape Slack pour alerter l’équipe :

- name: Notify Slack
  uses: rtCamp/action-slack-notify@v2
  env:
    SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
    SLACK_COLOR: ${{ job.status }}
    SLACK_MESSAGE: "Pipeline terminé avec le statut: ${{ job.status }}"
🔐 Protégez toujours vos webhooks avec secrets.

Étape 10 : Lancer plusieurs jobs en parallèle

Ajoutez un job de lint et un job de test :

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: mvn checkstyle:check

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: mvn test

🚄 Résultat : feedback plus rapide grâce à la parallélisation.

Étape 11 : Exécuter sur plusieurs environnements

Utilisez une matrice pour tester plusieurs versions de Java :

strategy:
  matrix:
    java: [11, 17, 21]

🧪 Vérifie la compatibilité multi-version.

Étape 12 : Étendre vers GitLab CI

Le même pipeline peut être transposé dans GitLab CI :

stages:
  - test

test-job:
  stage: test
  image: maven:3.9.4-eclipse-temurin-17
  script:
    - mvn clean test

🔄 Les concepts restent identiques : jobs, stages, runners.

Étape 13 : Sécurité et gestion des secrets

  • Utilisez secrets.GITHUB_TOKEN au lieu de tokens en clair.
  • Ne jamais commiter de mots de passe ou clés API.
  • Scannez vos dépendances avec Dependabot ou Snyk.

Étape 14 : Pipeline complet et amélioration continue

Votre pipeline final couvre :

  • ✅ Build et tests automatisés
  • ✅ Caching pour rapidité
  • ✅ Rapports HTML
  • ✅ Notifications d’équipe
  • ✅ Multi-jobs et multi-versions
  • ✅ Sécurité des secrets
🎉 Vous avez construit un pipeline CI/CD complet digne d’un projet professionnel. C’est la base pour industrialiser vos tests et fiabiliser vos déploiements.

🚀 Créer son premier pipeline CI/CD – Guide exhaustif (version longue)

Cette section propose un parcours complet pour construire, étendre et durcir un pipeline CI/CD professionnel. Nous partons d’un petit projet Java/Selenium, puis nous ajoutons progressivement des bonnes pratiques, de la parallélisation, des rapports, de la sécurité logiciel (supply chain), de la gouvernance et de la mise en production continue. Chaque étape fournit du code prêt à copier et des recommandations concrètes.

🧭 Plan rapide : Préparation ➜ Workflow de base ➜ Tests & rapports ➜ Caching & parallélisation ➜ Matrices ➜ Secrets & permissions ➜ Qualité & sécurité ➜ Artefacts & versioning ➜ Environnements & déploiements ➜ Observabilité ➜ Optimisations & coûts ➜ Modèle multi-plateformes (GitHub/GitLab/Jenkins/Azure/CircleCI) ➜ Annexes (checklists & snippets).

Étape 0 — Préparer un projet reproductible

Un pipeline stable commence par un projet facile à reconstruire n’importe où. Assurez-vous d’avoir un pom.xml verrouillé et un jeu de tests minimaux.

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>demo-ci</artifactId>
  <version>1.0.0</version>
  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>4.21.0</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.2.5</version>
        <configuration>
          <reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
          <argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Vérifiez en local : mvn -q -B -e clean verify. Tout doit passer avant l’automatisation.

Étape 1 — Workflow GitHub Actions minimal viable

Créez .github/workflows/ci.yml pour compiler et lancer les tests à chaque push et PR.

name: CI (Java + Maven)

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Temurin JDK 17 (cache Maven)
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '17'
          cache: 'maven'

      - name: Build & Test
        run: mvn -B clean verify

      - name: Upload Surefire Reports
        uses: actions/upload-artifact@v4
        with:
          name: surefire-reports
          path: target/surefire-reports

Ce pipeline devient le garde-fou de votre branche principale.

Étape 2 — Test E2E Selenium (Chrome headless)

Ajoutez un test simple pour valider l’environnement navigateur en CI.

import org.junit.*;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class GoogleTest {
  private WebDriver driver;

  @Before
  public void setup() {
    ChromeOptions opts = new ChromeOptions();
    opts.addArguments("--headless=new", "--no-sandbox", "--disable-gpu");
    driver = new ChromeDriver(opts);
  }

  @Test
  public void searchCICD() {
    driver.get("https://www.google.com");
    WebElement box = driver.findElement(By.name("q"));
    box.sendKeys("CI/CD Selenium");
    box.submit();
    Assert.assertTrue(driver.getTitle().toLowerCase().contains("ci/cd"));
  }

  @After
  public void teardown() {
    if (driver != null) driver.quit();
  }
}

Sur les runners GitHub, Chrome est disponible. Sinon, ajoutez l’étape browser-actions/setup-chrome.

Étape 3 — Paralléliser et séparer les responsabilités

Divisez le pipeline en jobs parallèles : lint, unit, e2e. Un échec coupe court au reste.

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: { distribution: temurin, java-version: '17', cache: 'maven' }
      - name: Lint (Checkstyle)
        run: mvn -B -q checkstyle:check

  unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: { distribution: temurin, java-version: '17', cache: 'maven' }
      - name: Unit tests
        run: mvn -B -q -Dgroups=unit test

  e2e:
    runs-on: ubuntu-latest
    needs: [unit]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: { distribution: temurin, java-version: '17', cache: 'maven' }
      - name: E2E tests
        run: mvn -B -q -Dgroups=e2e verify

Conseil : balisez vos tests via catégories (JUnit) pour sélectionner précisément ce qui tourne par job.

Étape 4 — Matrices d’exécution (versions JDK, OS, navigateurs)

Validez la compatibilité multi-environnements avec une matrice.

jobs:
  matrix-tests:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
        java: [11, 17]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: ${{ matrix.java }}
          cache: maven
      - name: Verify
        run: mvn -B -q clean verify

Évitez les matrices trop larges : ciblez ce qui apporte une vraie couverture.

Étape 5 — Gestion fine des caches & dépendances

Cache Maven explicite (si vous n’utilisez pas l’option cache: maven de setup-java).

- name: Cache Maven repository
  uses: actions/cache@v3
  with:
    path: ~/.m2/repository
    key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
    restore-keys: |
      ${{ runner.os }}-m2-

Nettoyez régulièrement les caches pour éviter les corruptions (clé changeante, TTL côté plate-forme).

Étape 6 — Artefacts, versioning et rétention

Publiez vos binaires et rapports, avec une politique de rétention adaptée.

- name: Package JAR
  run: mvn -B -q -DskipTests package

- name: Upload artifact (JAR)
  uses: actions/upload-artifact@v4
  with:
    name: app-jar
    path: target/*.jar
    retention-days: 14

Astuce : ajoutez un suffixe avec le GITHUB_SHA ou la version sémantique pour tracer l’origine.

Étape 7 — Qualité de code : SonarQube & seuils

Intégrez une Quality Gate qui bloque les merges en cas d’échec.

- name: Sonar Scan
  uses: SonarSource/sonarcloud-github-action@v2
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  with:
    args: >-
      -Dsonar.projectKey=com.example:demo-ci
      -Dsonar.java.binaries=target

Activez l’exigence « checks obligatoires » sur la branche main dans les protections de branches.

Étape 8 — Sécurité de la supply chain (SCA, SAST, SBOM)

Ajoutez des scans de vulnérabilités et un SBOM.

- name: Dependency scan (Snyk)
  uses: snyk/actions/maven@master
  env:
    SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
  with:
    command: test

- name: Generate SBOM (CycloneDX)
  run: mvn org.cyclonedx:cyclonedx-maven-plugin:2.7.10:makeAggregateBom

- name: Upload SBOM
  uses: actions/upload-artifact@v4
  with:
    name: sbom-cyclonedx
    path: target/bom.xml

Fixez des seuils (fail build si vulnérabilités critiques).

Étape 9 — Secrets, permissions & OIDC

Réduisez les permissions par défaut et utilisez OIDC pour les clouds.

permissions:
  contents: read
  id-token: write  # nécessaire pour OIDC

steps:
  - name: Configure OIDC to AWS
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789012:role/gha-deploy
      aws-region: eu-west-3

Ne stockez pas d’AWS keys statiques : préférez l’échange OIDC + rôle IAM.

Étape 10 — Concurrency, auto-cancel & tri des triggers

Évitez d’empiler des runs obsolètes en PR.

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]

Résultat : le dernier commit annule les exécutions précédentes inutiles.

Étape 11 — Workflows réutilisables & composite actions

Factorisez la logique (DRY) avec des workflows appelables ou des actions composites.

# .github/workflows/maven-build.yml
name: Reusable Maven Build
on: workflow_call
jobs:
  mvn:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: { distribution: temurin, java-version: '17', cache: 'maven' }
      - run: mvn -B -q clean verify
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  call-maven:
    uses: ./.github/workflows/maven-build.yml

Gain : maintenance centralisée et homogénéité entre repos.

Étape 12 — Tests de contrat & données de test

Stabilisez vos E2E : utilisez des mocks, du service virtualization et un jeu de données contrôlé.

  • Générez des données à la volée (fixtures) pour éviter les collisions.
  • Contrats d’API (Pact) pour prévenir les régressions entre services.
  • Snapshots HTML + screenshots pour diagnostiquer.

Étape 13 — Rapports riches (Allure) & artefacts visuels

Ajoutez Allure pour un reporting agréable et navigable.

<plugin>
  <groupId>io.qameta.allure</groupId>
  <artifactId>allure-maven</artifactId>
  <version>2.12.0</version>
  <configuration>
    <resultsDirectory>${project.build.directory}/allure-results</resultsDirectory>
  </configuration>
</plugin>
- name: Upload Allure Results
  uses: actions/upload-artifact@v4
  with:
    name: allure-results
    path: target/allure-results

Étape 14 — Promotion entre environnements & gates

Utilisez les Environments GitHub pour staging et production avec approbations.

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - run: echo "Deploying to staging..."

  deploy-prod:
    needs: [deploy-staging]
    runs-on: ubuntu-latest
    environment: production  # peut exiger une approbation manuelle
    steps:
      - run: echo "Deploying to prod..."

Ajoutez des checks : qualité, sécurité, couverture minimale, etc.

Étape 15 — Stratégies de déploiement (canary, blue/green, feature flags)

  • Canary : pourcentages progressifs de trafic.
  • Blue/Green : deux environnements interchangeables.
  • Feature flags : activer/désactiver sans redeployer.

Couplez la stratégie à un monitoring serré (latence, erreurs, SLOs).

Étape 16 — Observabilité & diagnostics

Exposez des métriques, logs et traces corrélées au commit SHA.

  • Ajoutez un step summary GitHub avec un récapitulatif lisible.
  • Centralisez les logs de test et d’application en artefacts.
  • Reliez vos dashboards (Grafana, Datadog) avec des liens de run.
- name: Step Summary
  run: |
    echo "## Résumé du build" >> $GITHUB_STEP_SUMMARY
    echo "Commit: $GITHUB_SHA" >> $GITHUB_STEP_SUMMARY

Étape 17 — Coûts & performance des pipelines

  • Activez cancel-in-progress pour PR.
  • Cachez intelligemment (Maven, Docker layers) en évitant la corruption.
  • Réduisez les images Docker (base distroless, JDK/JRE slim).
  • Externalisez les tâches lourdes (analyse SAST) en jobs planifiés.

Étape 18 — Runners self-hosted & exécutions éphémères

Pour des besoins spécifiques (GPU, Android, iOS), déployez des runners dédiés.

  • Étiquetez vos runners (labels) et ciblez-les dans vos jobs.
  • Prévoyez un autoscaling (K8s, ASG) pour absorber les pics.
  • Nettoyez après run (actions de post) pour éviter la dérive.

Étape 19 — Gestion des branches & stratégies de merge

  • Trunk-based development : petites PRs, intégration rapide.
  • GitFlow : pour versions planifiées et hotfixes.
  • Exigez des revues + statut CI vert + qualité OK avant merge.

Étape 20 — Intégrations multi-plateformes (exemples prêts à l’emploi)

GitLab CI

stages: [build, test]

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

cache:
  paths:
    - .m2/repository

build:
  stage: build
  image: maven:3.9.6-eclipse-temurin-17
  script:
    - mvn -B -q clean compile

test:
  stage: test
  image: maven:3.9.6-eclipse-temurin-17
  script:
    - mvn -B -q verify
  artifacts:
    paths:
      - target/surefire-reports
    expire_in: 14 days

Jenkins (déclaratif)

pipeline {
  agent any
  options { timestamps() skipDefaultCheckout(true) }
  stages {
    stage('Checkout') { steps { checkout scm } }
    stage('Build & Test') { steps { sh 'mvn -B clean verify' } }
    stage('Archive Reports') {
      steps {
        junit 'target/surefire-reports/*.xml'
        archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
      }
    }
  }
  post { always { cleanWs() } }
}

Azure DevOps

trigger: [ main ]

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: JavaToolInstaller@0
    inputs:
      versionSpec: '17'
      jdkArchitectureOption: 'x64'
      jdkSourceOption: 'PreInstalled'

  - script: mvn -B clean verify
    displayName: 'Build & Test'

  - task: PublishBuildArtifacts@1
    inputs:
      pathToPublish: 'target/surefire-reports'
      artifactName: 'surefire-reports'

CircleCI

version: 2.1
jobs:
  build:
    docker:
      - image: cimg/openjdk:17.0
    steps:
      - checkout
      - restore_cache:
          keys:
            - mvn-{{ checksum "pom.xml" }}
      - run: mvn -B clean verify
      - save_cache:
          paths: ~/.m2
          key: mvn-{{ checksum "pom.xml" }}
      - store_artifacts:
          path: target/surefire-reports
workflows:
  version: 2
  ci:
    jobs: [ build ]

Annexes — Checklists & snippets utiles

Checklist « PR prête à merger »

  • ✅ CI verte (tous les jobs) ; ✅ Couverture ≥ seuil ; ✅ Quality Gate OK ; ✅ Scan SCA sans critiques ; ✅ SBOM généré.
  • ✅ Conflits résolus, ✅ changelog/README mis à jour, ✅ secrets via vault/secrets store.

Déclencheurs supplémentaires

on:
  schedule:
    - cron: '0 2 * * *'    # nightly
  workflow_dispatch:
    inputs:
      run-e2e:
        description: 'Inclure les tests E2E'
        type: boolean
        default: false

Contrôle conditionnel

- name: E2E (optionnel)
  if: ${{ inputs.run-e2e == true }}
  run: mvn -B -q -Dgroups=e2e verify

Politique de rétention

Fixez des retention-days courts pour les rapports et plus longs pour les artefacts de release.

🎉 En appliquant ces étapes, vous obtenez un pipeline rapide, fiable, auditable et sécurisé. La progression est incrémentale : partez du workflow minimal et ajoutez, une par une, les capacités qui comptent pour votre équipe (qualité, sécurité, promotion, observabilité).