Module Technique 4 — CI/CD avec GitHub Actions

Automatiser tests et déploiements pour fiabiliser tes projets

ci-cd
github-actions
automatisation
Auteur·rice

François Boussengui

Date de publication

25 mars 2026

0.0.1 🎯 Objectifs d’apprentissage

  1. Expliquer les concepts de CI et CD et leurs bénéfices
  2. Écrire un workflow GitHub Actions complet
  3. Configurer des tests automatisés avec pytest
  4. Mettre en place du linting et formatage automatique
  5. Comprendre le déploiement continu

📚 Prérequis : Git, Docker, Python

⏱️ Temps estimé : 3 heures


1 Pourquoi automatiser ?

Sans CI/CD, chaque développeur doit manuellement lancer les tests, vérifier le formatage, et déployer. Résultat : des oublis, des bugs en production, des déploiements risqués.

CI (Intégration Continue) CD (Déploiement Continu)
Quand À chaque push ou PR Après validation CI
Quoi Tests, linting, build Déploiement staging/prod
Objectif Détecter les bugs tôt Livrer rapidement

flowchart LR
    A[📝 Push] --> B[🔍 Lint]
    B --> C[🧪 Tests]
    C --> D{Tout passe ?}
    D -->|Oui| E[📦 Build]
    D -->|Non| F[❌ Alerte]
    E --> G[🚀 Deploy]

Pipeline CI/CD typique

💡 En data science, le CI/CD sert à valider que les modèles se chargent, que les prédictions sont cohérentes, et à déployer automatiquement les APIs de scoring.


2 Structure d’un workflow GitHub Actions

Un workflow est un fichier .yml dans .github/workflows/ :

# .github/workflows/ci.yml
name: CI Pipeline

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

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

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'

      - name: Install dependencies
        run: |
          pip install -r requirements.txt
          pip install pytest black flake8

      - name: Run linting
        run: |
          black --check .
          flake8 . --max-line-length 120

      - name: Run tests
        run: pytest tests/ -v --tb=short
Concept Description
Trigger (on) Événement déclencheur (push, PR, schedule)
Job Groupe de tâches sur une VM dédiée
Step Étape individuelle dans un job
Action Module réutilisable (actions/checkout@v4)
Secret Variable chiffrée pour données sensibles

3 Tests automatisés avec pytest

3.1 Écrire des tests pour l’assurance

# tests/test_sinistralite.py
import pytest
from models.sinistralite import calculer_frequence, calculer_sp

def test_frequence_normale():
    """Fréquence = nb_sinistres / exposition"""
    assert calculer_frequence(100, 1000) == 0.1

def test_frequence_zero_exposition():
    with pytest.raises(ZeroDivisionError):
        calculer_frequence(10, 0)

def test_sp_normal():
    assert calculer_sp(70000, 100000) == 0.7

@pytest.mark.parametrize("nb_sin,expo,expected", [
    (50, 1000, 0.05),
    (100, 1000, 0.10),
    (200, 1000, 0.20),
])
def test_frequence_parametrique(nb_sin, expo, expected):
    assert calculer_frequence(nb_sin, expo) == expected

$ pytest tests/ -v
tests/test_sinistralite.py::test_frequence_normale PASSED
tests/test_sinistralite.py::test_frequence_zero_exposition PASSED
tests/test_sinistralite.py::test_sp_normal PASSED
tests/test_sinistralite.py::test_frequence_parametrique[50-1000-0.05] PASSED
tests/test_sinistralite.py::test_frequence_parametrique[100-1000-0.1] PASSED
tests/test_sinistralite.py::test_frequence_parametrique[200-1000-0.2] PASSED

============ 6 passed in 0.08s ============

📝 Bonnes pratiques

  • Un test par comportement, pas par fonction
  • Noms descriptifs (test_frequence_zero_exposition)
  • @pytest.mark.parametrize pour tester plusieurs cas
  • Toujours tester les cas limites et erreurs

4 Linting et formatage

Black formate le code automatiquement — plus de débats de style :

black --check .   # Vérifier
black .           # Formater

Flake8 détecte les erreurs de style et bugs potentiels :

flake8 . --max-line-length 120 --ignore=E203,W503

5 Déploiement continu

  deploy:
    needs: [test, lint]
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - run: docker build -t mon-api:${{ github.sha }} .
      - run: docker push mon-registry/mon-api:${{ github.sha }}

⚠️ Sécurité — Ne jamais stocker de secrets dans le code. Utiliser les GitHub Secrets :

    env:
      AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}

Synthèse

5.0.1 🎯 Les 5 points essentiels

  1. CI détecte les bugs tôt — Tests et linting à chaque push
  2. CD accélère la livraison — Déploiement automatique après validation
  3. GitHub Actions = YAML — Triggers, jobs, steps
  4. pytest est le standard — Tests paramétriques, fixtures, markers
  5. Les secrets restent secrets — GitHub Secrets, jamais en dur

Auto-évaluation

Réponse : CI automatise tests et validation à chaque changement. CD automatise le déploiement après validation. La CI est un prérequis au CD.

Réponse : Les secrets dans le code sont visibles dans l’historique Git. GitHub Secrets les chiffre et les injecte uniquement pendant l’exécution du workflow.

Réponse : Pour vérifier qu’une fonction lève bien une exception dans un cas d’erreur (ex: division par zéro). C’est un test de robustesse.

Réponse : Déterministe et non configurable : élimine les débats de style, garantit un code homogène, permet de se concentrer sur la logique métier.


← Retour à la Semaine 4 Voir la Fiche de travail →