Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 1219 minDébutant

GitHub Actions : premier pipeline d'intégration continue

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • expliquer l'intégration continue et le vocabulaire de GitHub Actions ;
  • écrire un premier workflow qui lance les tests d'une API Node.js ;
  • bloquer une fusion quand les tests échouent, et protéger les secrets ;
  • lire un échec et tenir les dépendances à jour avec Dependabot.

3 exercices corrigés1 schéma

GitHub Actions est le service d'automatisation de GitHub : à chaque push ou pull request, il lance sur une machine de GitHub les étapes que tu as décrites dans un fichier YAML, par exemple installer les dépendances, vérifier le code et exécuter les tests. C'est l'outil le plus simple pour mettre en place l'intégration continue sur un projet de BTS. Ce chapitre explique le vocabulaire (workflow, job, step, runner), construit pas à pas un premier pipeline pour une API Node.js, puis montre comment l'utiliser pour bloquer la fusion d'une pull request qui casse les tests, gérer les secrets et lire un échec.

L'intégration continue en deux phrases

L'intégration continue (CI, continuous integration) consiste à intégrer souvent le travail de chacun dans la branche commune, et à vérifier automatiquement chaque intégration : compilation, analyse du code, tests. Le déploiement continu (CD) va plus loin : si toutes les vérifications passent sur main, l'application est livrée automatiquement.

Sans intégration continue, les tests ne tournent que si quelqu'un pense à les lancer, sur sa machine, avec sa configuration. Avec elle, chaque pull request affiche une coche verte ou une croix rouge avant même la relecture : « ça marchait chez moi » ne suffit plus.

Le référentiel du BTS SIO SLAM cite la compétence « Intégrer en continu les versions d'une solution applicative » : un pipeline qui lance tes tests à chaque push en est la preuve la plus directe.

Le vocabulaire de GitHub Actions

TermeDéfinition
WorkflowUn fichier YAML dans .github/workflows/ qui décrit une automatisation ; un dépôt peut en avoir plusieurs
Événement (on)Ce qui déclenche le workflow : push, pull_request, un horaire, un clic manuel
JobUn ensemble d'étapes exécutées sur une même machine ; les jobs d'un workflow tournent en parallèle, sauf dépendance déclarée
StepUne étape d'un job : une commande (run) ou une action réutilisable (uses)
ActionUn composant publié qu'on réutilise, comme actions/checkout qui récupère le code du dépôt
RunnerLa machine virtuelle qui exécute un job : Ubuntu, Windows ou macOS, fournie par GitHub, ou une machine à toi (self-hosted runner)
git pushoupull requestci.ymlRunner Ubuntu : job testsactions/checkoutsetup-node : Node.js 24npm cinpm run lintnpm testtoutes vertescoche vertefusion possibleune étape échouecroix rougefusion bloquée
Un push déclenche le workflow ; le runner exécute les étapes ; le résultat s'affiche sur la pull request et peut bloquer la fusion

Un premier workflow pour une API Node.js

Crée le fichier .github/workflows/ci.yml à la racine du dépôt de Sorbier Frais :

yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  tests:
    runs-on: ubuntu-latest
    steps:
      - name: Récupérer le code
        uses: actions/checkout@v7

      - name: Installer Node.js
        uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm

      - name: Installer les dépendances
        run: npm ci

      - name: Vérifier le style du code
        run: npm run lint

      - name: Lancer les tests
        run: npm test

Ligne par ligne :

LigneRôle
name: CILe nom affiché dans l'onglet Actions et sur les pull requests
on: push: branches: [main]Déclenche le workflow à chaque push sur main
on: pull_request:Et à chaque pull request, ouverte ou mise à jour, quelle que soit la branche
jobs: tests:Un job nommé tests
runs-on: ubuntu-latestIl tourne sur la dernière version d'Ubuntu proposée par GitHub
uses: actions/checkout@v7Récupère le code du dépôt sur le runner ; sans elle, la machine est vide
uses: actions/setup-node@v7Installe Node.js 24, une version LTS maintenue jusqu'en avril 2028 ; cache: npm garde les paquets téléchargés d'une exécution à l'autre
run: npm ciInstalle exactement les versions du package-lock.json (plus strict et plus rapide que npm install)
run: npm run lint et run: npm testLancent les scripts du package.json ; si la commande renvoie un code d'erreur, l'étape échoue et le job s'arrête

Le @v7 désigne la version majeure de l'action. Les actions évoluent : quand GitHub annonce qu'une version est obsolète, change le numéro. Dependabot peut le faire pour toi (plus bas).

Commite et pousse :

bash
git add .github/workflows/ci.yml
git commit -m "ci: lance le linter et les tests à chaque push"
git push

L'onglet Actions du dépôt affiche l'exécution en direct : chaque étape, sa durée, et sa sortie complète quand on la déplie.

Le même principe pour d'autres langages

Seules les étapes d'installation et de test changent :

ProjetÉtapes clés
PHP, Symfonyshivammathur/setup-php@v2 avec php-version: '8.5', puis composer install --no-progress et vendor/bin/phpunit
C#, .NETactions/setup-dotnet@v6 avec dotnet-version: '10.0.x', puis dotnet restore, dotnet build --no-restore et dotnet test --no-build
Pythonactions/setup-python@v7 avec python-version: '3.15', puis pip install -r requirements.txt et pytest
Java, Mavenactions/setup-java@v6 avec distribution: temurin et java-version: '25', puis mvn -B verify

Pour une application de bureau WinForms, qui ne compile que sous Windows, remplace runs-on: ubuntu-latest par runs-on: windows-latest.

Tester avec une vraie base de données

Les tests d'intégration de l'API ont besoin d'une base MySQL. GitHub Actions peut démarrer un conteneur à côté du job, avec services :

yaml
jobs:
  tests:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:8.4
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: sorbier_test
        ports:
          - 3306:3306
        options: >-
          --health-cmd="mysqladmin ping -h 127.0.0.1 -proot"
          --health-interval=5s --health-timeout=3s --health-retries=10
    env:
      DB_HOST: 127.0.0.1
      DB_USER: root
      DB_PASSWORD: root
      DB_NAME: sorbier_test
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: mysql -h 127.0.0.1 -uroot -proot sorbier_test < sql/schema.sql
      - run: npm test

Le mot de passe root n'est pas un secret : cette base est créée vide pour les tests et détruite à la fin du job. Les options --health-* font attendre GitHub que MySQL soit prêt avant de lancer les étapes. Le script de création des tables vient du dépôt ; si tu as besoin d'une base d'exemple, celle du cours SQL convient.

Bloquer la fusion si les tests échouent

Un pipeline rouge que personne ne regarde ne sert à rien. Rends-le obligatoire : dans les règles de la branche main (protéger la branche main), active Require status checks to pass et sélectionne le job tests. Le bouton de fusion d'une pull request reste alors grisé tant que le job n'est pas vert.

Ajoute un badge en haut de ton README, qui affiche l'état du dernier pipeline :

markdown
![CI](https://github.com/ton-pseudo/sorbier-frais/actions/workflows/ci.yml/badge.svg)

La commission de l'E6 voit tout de suite que tes tests tournent automatiquement.

Les secrets dans GitHub Actions

Une étape de déploiement a besoin d'un mot de passe ou d'une clé : jamais dans le fichier YAML, qui est versionné et lisible par tous ceux qui voient le dépôt. Enregistre-les dans Settings, Secrets and variables, Actions, New repository secret, puis utilise-les ainsi :

yaml
      - name: Déployer sur le serveur de recette
        run: ./scripts/deploy.sh
        env:
          SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}

GitHub masque la valeur dans les journaux (***). Les secrets ne sont pas transmis aux workflows déclenchés par la pull request d'un fork : un inconnu ne peut pas les lire en proposant une modification malveillante. Le jeton GITHUB_TOKEN, créé automatiquement pour chaque exécution, donne au workflow des droits sur le dépôt ; limite-les au strict nécessaire :

yaml
permissions:
  contents: read

Lire un échec

Quand une étape échoue, GitHub t'envoie un courriel, la pull request affiche une croix rouge, et l'onglet Actions déplie l'étape en erreur. La méthode :

  1. Lis la fin de la sortie de l'étape rouge : le message d'erreur est presque toujours dans les dernières lignes. Pour des tests, c'est le nom du test qui échoue, la valeur attendue et la valeur obtenue.
  2. Reproduis en local avec la même commande (npm ci puis npm test). Beaucoup d'échecs viennent d'une différence avec ta machine : un fichier ignoré qui existe chez toi mais pas dans le dépôt, une variable d'environnement définie dans ton .env local, un fichier dont la casse diffère (Notes.js et notes.js sont un seul fichier sous Windows et macOS, deux sous Linux).
  3. Corrige, commite, pousse : le workflow repart tout seul sur la pull request.

Le bouton Re-run jobs relance un job sans nouveau commit, utile quand l'échec venait d'un incident réseau.

Le coût

Pour un dépôt public, les runners standards de GitHub sont gratuits et illimités. Pour un dépôt privé, l'offre gratuite inclut un quota mensuel de minutes, largement suffisant pour un projet de BTS : un pipeline Node.js de lint et de tests dure une à deux minutes. Les runners Windows et macOS consomment le quota plus vite que Linux : reste sur ubuntu-latest quand le projet le permet.

Tenir les dépendances à jour avec Dependabot

Dependabot, intégré à GitHub, surveille les dépendances de ton projet. Il t'alerte quand l'une d'elles a une vulnérabilité connue, et peut ouvrir automatiquement une pull request de mise à jour, que ton pipeline teste aussitôt. Active les alertes dans Settings, Security, puis ajoute le fichier .github/dependabot.yml :

yaml
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: monthly

Le second bloc met aussi à jour les versions des actions utilisées dans tes workflows.

Déployer automatiquement avec GitHub Actions

Le même mécanisme peut livrer l'application quand main est verte : publier un site statique sur GitHub Pages (dans Settings, Pages, source GitHub Actions, avec les actions officielles actions/upload-pages-artifact et actions/deploy-pages), construire et pousser une image Docker vers un registre, ou se connecter en SSH au serveur de recette pour y lancer le script de déploiement. Le déploiement ajoute des questions de sécurité et de retour arrière : commence par un pipeline de tests fiable, puis automatise le déploiement vers un environnement de recette avant la production. Le cours Docker montre comment empaqueter l'application, et le cours Tests comment écrire les tests que le pipeline lance. Le cours Intégration et déploiement continus (CI/CD) va plus loin : écrire un workflow complet, la matrice et le cache, GitLab CI, les environnements et les stratégies de déploiement.

Exercices

Exercice 1 sur 3 Lire un workflow Réussi À revoir

yaml
name: Qualité
on:
  pull_request:
    branches: [main]
jobs:
  php:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.5'
      - run: composer install --no-progress
      - run: vendor/bin/phpunit
  1. Ce workflow tourne-t-il quand Lina pousse un commit directement sur main ?
  2. Que se passe-t-il si composer install échoue ?
  3. Que faut-il régler sur GitHub pour qu'une pull request ne puisse pas être fusionnée quand les tests échouent ?
  4. Pourquoi l'étape actions/checkout est-elle indispensable ?
Voir la réponseMasquer la réponse de l'exercice 1
  1. Non : il n'est déclenché que par les pull requests dont la branche cible est main.
  2. L'étape échoue, le job s'arrête, phpunit ne tourne pas, et la pull request affiche une croix rouge.
  3. Une règle de protection (ou un ruleset) sur main avec Require status checks to pass, en sélectionnant le job php.
  4. Le runner démarre vide : sans checkout, le code du dépôt n'y est pas, et composer install ne trouve pas de composer.json.

Tu avais trouvé ?

Exercice 2 sur 3 Trouver les problèmes Réussi À revoir

Ce workflow pose trois problèmes, dont un qui le fait échouer à coup sûr. Trouve-les.

yaml
name: CI
on: [push]
jobs:
  tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v7
        with:
          node-version: 24
      - run: npm ci
      - run: npm test
        env:
          DB_PASSWORD: Kq7!vT2pL9zR
Voir la réponseMasquer la réponse de l'exercice 2
  1. L'étape uses: actions/checkout@v7 manque : npm ci ne trouve pas de package.json sur un runner vide.
  2. Un mot de passe est écrit en clair dans un fichier versionné. Il faut le stocker dans les secrets du dépôt et écrire DB_PASSWORD: ${{ secrets.DB_PASSWORD }}, puis changer ce mot de passe, désormais exposé dans l'historique. Si c'est le mot de passe d'une base de test créée par le workflow, un service MySQL jetable comme dans ce chapitre évite d'avoir un secret.
  3. Le workflow ne tourne que sur push : les pull requests ouvertes depuis un fork ne seront pas testées. Ajouter pull_request dans on (par exemple on: [push, pull_request], ou push limité à main plus pull_request pour éviter les doublons).

Tu avais trouvé ?

Exercice 3 sur 3 Écrire un workflow Réussi À revoir

Écris un workflow ci.yml pour une application ASP.NET Core en .NET 10, dont les tests sont dans la solution : il doit tourner à chaque pull request et à chaque push sur main, restaurer les dépendances, compiler en mode Release et lancer les tests.

Voir la réponseMasquer la réponse de l'exercice 3
yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read

jobs:
  build-et-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-dotnet@v6
        with:
          dotnet-version: '10.0.x'
      - run: dotnet restore
      - run: dotnet build --no-restore --configuration Release
      - run: dotnet test --no-build --configuration Release

ASP.NET Core tourne sous Linux : ubuntu-latest convient. --no-restore et --no-build évitent de refaire les étapes précédentes ; dotnet test --no-build doit utiliser la même configuration que la compilation.

Tu avais trouvé ?

Chapitre terminé !

Fais les 3 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Préparer son dépôt GitHub pour l'E5 et l'E6Revoir le sommaire du cours