Principes et mise en place du CI/CD
Guide complet sur les principes CI/CD : intégration continue, déploiement continu, mise en place pratique avec exemples concrets. Parfait pour débuter avec les pipelines.
Sommaire
- Introduction
- Comprendre le CI/CD
- Anatomie d’une pipeline CI/CD
- Mise en place pratique
- Bonnes pratiques
- Gestion des échecs et rollbacks
- FAQ
Introduction
Vous avez probablement entendu parler de CI/CD sans vraiment comprendre ce que cela apporte concrètement. Peut-être que vous déployez encore manuellement vos applications, en croisant les doigts pour que tout se passe bien ?
Le CI/CD va révolutionner votre façon de développer en automatisant les tâches répétitives et en réduisant drastiquement les risques d’erreur. Dans cet article, nous allons démystifier ces concepts et voir comment les mettre en place simplement.
Comprendre le CI/CD
Qu’est-ce que l’intégration continue (CI) ?
L’intégration Continue consiste à automatiser la validation de votre code à chaque modification :
Le processus traditionnel :
- Développeur A travaille sur sa fonctionnalité (3 jours)
- Développeur B travaille sur la sienne (3 jours)
- Ils fusionnent leur code -> Conflits et bugs =1
- 2 jours pour résoudre les problèmes
- Tests manuels -> Encore des bugs
- Correction -> Nouveaux tests…
Avec l’intégration continue :
- Chaque commit déclenche automatiquement :
- Tests unitaires
- Tests d’intégration
- Vérifications de qualité de code
- Build automatique
- Feedback immédiat en cas de problème
- Conflits détectés rapidement
Qu’est-ce que le déploiement continu (CD) ?
Le déploiement Continu automatise la mise en production :
Continuous Delivery (Livraison Continue) :
- Le code est automatiquement préparé pour le déploiement
- déploiement manuel après validation
Continuous Deployment (déploiement Continu) :
- Le code est automatiquement déployé en production
- Aucune intervention manuelle
Les bénéfices du CI/CD
Rapidité de livraison :
- De quelques semaines à quelques heures
- Mise sur le marché accélérée
Qualité améliorée :
- Tests systématiques
- Détection précoce des bugs
- Rollback automatique si problème
Réduction du stress :
- Fini les déploiements du vendredi soir
- Process reproductible et fiable
Collaboration renforcée :
- Feedback rapide entre équipes
- Intégration facilitée du code
Anatomie d’une pipeline CI/CD
Les étapes essentielles
Code Push → Build → Test → Deploy → Monitor
→ → → → →
Trigger Compile Unit Staging Alerts
Install E2E Prod Metrics
Lint API Logs
1. Déclenchement (Trigger) :
- Push sur une branche
- Pull Request
- Tag de version
- Programmation (cron)
2. Construction (Build) :
- Installation des dépendances
- Compilation du code
- Vérification du linting
- Génération des assets
3. Tests :
- Tests unitaires
- Tests d’intégration
- Tests end-to-end
- Tests de sécurité
4. déploiement :
- déploiement en staging
- Tests de validation
- déploiement en production
- Vérifications post-déploiement
5. Monitoring :
- Surveillance des erreurs
- Métriques de performance
- Alertes automatiques
Les outils populaires
Plateformes CI/CD intégrées :
- GitHub Actions - Intégré é GitHub
- GitLab CI - Intégré é GitLab
- Bitbucket Pipelines - Intégré é Bitbucket
Solutions dédiées :
- Jenkins - Open source, très flexible
- CircleCI - Cloud, facile à configurer
- Travis CI - Populaire pour l’open source
Cloud providers :
- AWS CodePipeline - écosystème AWS
- Azure DevOps - Microsoft
- Google Cloud Build - Google Cloud
Mise en place pratique
Exemple avec GitHub Actions
Créons une pipeline complète pour une application Node.js :
.github/workflows/ci-cd.yml :
name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
NODE_VERSION: '18'
jobs:
# ==================
# PHASE CI
# ==================
test:
name: Tests et Qualité
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
- name: Run unit tests
run: npm run test:unit
- name: Run integration tests
run: npm run test:integration
- name: Build application
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-files
path: dist/
# ==================
# PHASE CD - STAGING
# ==================
deploy-staging:
name: Deploy to Staging
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
environment:
name: staging
url: https://staging.monapp.com
steps:
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: build-files
path: dist/
- name: Deploy to staging server
run: |
echo "Deploying to staging..."
# Vos commandes de déploiement ici
rsync -av dist/ user@staging-server:/var/www/html/
- name: Run smoke tests
run: |
curl -f https://staging.monapp.com/health || exit 1
npm run test:e2e -- --baseUrl=https://staging.monapp.com
# ==================
# PHASE CD - PRODUCTION
# ==================
deploy-production:
name: Deploy to Production
needs: [test, deploy-staging]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment:
name: production
url: https://monapp.com
steps:
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: build-files
path: dist/
- name: Deploy to production
run: |
echo "Deploying to production..."
# Blue-green deployment ou rolling update
./scripts/deploy-production.sh
- name: Verify deployment
run: |
curl -f https://monapp.com/health || exit 1
npm run test:smoke -- --baseUrl=https://monapp.com
- name: Notify team
if: success()
run: |
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"déploiement en production réussi!"}' \
${{ secrets.SLACK_WEBHOOK }}
Exemple avec GitLab CI
.gitlab-ci.yml :
stages:
- build
- test
- deploy-staging
- deploy-production
variables:
NODE_VERSION: "18"
# ==================
# BUILD STAGE
# ==================
build:
stage: build
image: node:${NODE_VERSION}
cache:
paths:
- node_modules/
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 hour
# ==================
# TEST STAGE
# ==================
test:unit:
stage: test
image: node:${NODE_VERSION}
script:
- npm ci
- npm run test:unit
test:integration:
stage: test
image: node:${NODE_VERSION}
services:
- postgres:13
- redis:6-alpine
script:
- npm ci
- npm run test:integration
# ==================
# DEPLOY STAGING
# ==================
deploy:staging:
stage: deploy-staging
script:
- echo "Deploying to staging..."
- rsync -av dist/ $STAGING_SERVER:/var/www/html/
environment:
name: staging
url: https://staging.monapp.com
only:
- develop
# ==================
# DEPLOY PRODUCTION
# ==================
deploy:production:
stage: deploy-production
script:
- echo "Deploying to production..."
- ./scripts/deploy-production.sh
environment:
name: production
url: https://monapp.com
only:
- main
when: manual # Nécessite une validation manuelle
Configuration des environnements
Variables d’environnement par stage :
# Staging
environment:
name: staging
variables:
DATABASE_URL: $STAGING_DB_URL
API_URL: https://api-staging.monapp.com
CACHE_TTL: 300
# Production
environment:
name: production
variables:
DATABASE_URL: $PRODUCTION_DB_URL
API_URL: https://api.monapp.com
CACHE_TTL: 3600
Gestion des secrets :
- Tokens d’API
- Clés de déploiement
- Mots de passe de base de données
- Certificats SSL
Bonnes pratiques
Architecture des branches
GitFlow simplifié :
main (production) -> Merge après validation
↓
develop (staging) -> intégration des features
↓
feature/xxx -> Développement des fonctionnalités
Tests en pyramide
E2E Tests (Peu)
↓
Integration Tests (Quelques-uns)
↓
Unit Tests (Beaucoup)
Répartition recommandée :
- 70% Tests unitaires (rapides, isolés)
- 20% Tests d’intégration (modules ensemble)
- 10% Tests E2E (parcours utilisateur complets)
déploiement sécurisé
Stratégies de déploiement :
- Blue-Green Deployment :
Blue (v1.0) -> Traffic 100%
Green (v1.1) -> déploiement en parallèle
Switch -> Green -> Traffic 100%
- Rolling Deployment :
Serveur 1: v1.0 -> v1.1
Serveur 2: v1.0 -> v1.1
Serveur 3: v1.0 -> v1.1
- Canary Deployment :
90% Traffic -> v1.0 (stable)
10% Traffic -> v1.1 (nouvelle version)
Si OK -> 100% vers v1.1
Monitoring et alertes
# Healthcheck automatique aprés déploiement
- name: Health Check
run: |
for i in {1..5}; do
if curl -f https://monapp.com/health; then
echo "Health check passed"
exit 0
fi
echo "é Waiting for app to start..."
sleep 10
done
echo "❌ Health check failed"
exit 1
Gestion des échecs et rollbacks
Rollback automatique
- name: Deploy with rollback
run: |
# Sauvegarde de la version actuelle
kubectl rollout history deployment/monapp
# déploiement
kubectl set image deployment/monapp app=monapp:${{ github.sha }}
# Vérification
kubectl rollout status deployment/monapp --timeout=300s
# Rollback si échec
if ! curl -f https://monapp.com/health; then
echo "❌ Deployment failed, rolling back..."
kubectl rollout undo deployment/monapp
exit 1
fi
Notifications d’échec
- name: Notify on failure
if: failure()
uses: actions/slack@v1
with:
message: |
=> déploiement échoué !
Branche: ${{ github.ref }}
Commit: ${{ github.sha }}
Voir: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
FAQ
Dois-je déployer automatiquement en production ?
Pour les équipes expériences : Oui, avec des tests robustes et du monitoring.
Pour débuter : Commencez par l’automatisation jusqu’au staging, puis déploiement manuel en production.
Combien de temps doit prendre ma pipeline ?
Objectifs recommandés :
- CI (build + tests) : < 10 minutes
- déploiement staging : < 5 minutes
- déploiement production : < 15 minutes
Si c’est plus long, parallélisez ou optimisez.
Comment gérer les bases de données ?
Migrations :
- name: Run database migrations
run: |
npm run migrate:up
npm run seed:production
Stratégies :
- Migrations backward-compatible
- Scripts de rollback préparés
- Backup automatique avant migration
Que faire si un test est flaky (instable) ?
- Identifier la cause (timing, dépendances externes)
- Stabiliser le test (mocks, attentes explicites)
- En attendant : Retry automatique
- name: Run flaky tests with retry
uses: nick-invision/retry@v2
with:
timeout_minutes: 10
max_attempts: 3
command: npm run test:e2e
Comment débuter simplement ?
Phase 1 : CI simple (tests + build)
Phase 2 : déploiement automatique en staging
Phase 3 : déploiement automatique en production
Phase 4 : Monitoring avancé et optimisations
Puis-je faire du CI/CD sans cloud ?
Oui ! Avec Jenkins ou GitLab self-hosted sur vos serveurs. Mais le cloud simplifie la maintenance.
Le CI/CD demande un investissement initial, mais les gains en productivité et en qualité sont énormes. Commencez petit, et itérez progressivement !