CI/CD Pipeline Best Practices
Problème
Les pipelines CI/CD sont soit inexistants (déploiement manuel), soit trop lents (30+ min), soit cassés silencieusement (tests skip, déploiements partiels).
Solution
Pipeline structuré en stages, cache agressif, tests parallélisés, déploiement atomique avec rollback automatique.
1. Structure du pipeline
# .github/workflows/ci.yml — GitHub Actions
name: CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22, cache: npm }
- run: npm ci
- run: npm run lint
test:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22, cache: npm }
- run: npm ci
- run: npm run test:unit -- --coverage
- run: npm run test:integration
- uses: actions/upload-artifact@v4
if: always()
with: { name: coverage, path: coverage/ }
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22, cache: npm }
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with: { name: dist, path: dist/ }
deploy:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/download-artifact@v4
with: { name: dist, path: dist/ }
- run: npx vercel deploy --prod --token ${{ secrets.VERCEL_TOKEN }}
2. Règles par stage
| Stage | Durée max | Action si échec |
|---|---|---|
| Lint | 2 min | Block PR |
| Test unit | 5 min | Block PR |
| Test integration | 10 min | Block PR |
| Build | 5 min | Block PR |
| Deploy (staging) | 3 min | Auto-rollback |
| Deploy (prod) | 3 min | Auto-rollback + alert |
3. Cache — accélérer le pipeline
# Cache npm
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm # cache automatique
# Cache Docker layers
- uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
# Cache Gradle (Java)
- uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: gradle-${{ hashFiles('**/*.gradle') }}
4. Tests parallélisés
test:
strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- run: npm run test -- --shard=${{ matrix.shard }}/4
5. Déploiement atomique + rollback
# Vercel — rollback automatique si health check échoue
deploy:
steps:
- run: npx vercel deploy --prod
- name: Health check
run: |
sleep 10
curl -f https://myapp.com/api/health || exit 1
- name: Rollback on failure
if: failure()
run: npx vercel rollback ${{ steps.deploy.outputs.prev_url }}
6. Environments et secrets
# Secrets par environment (GitHub)
deploy-staging:
environment: staging # secrets spécifiques au staging
deploy-prod:
environment: production # secrets spécifiques à la prod
# Requires manual approval si configuré dans GitHub
- Jamais de secrets en clair dans le workflow
- Secrets par environment (staging ≠ prod)
- Rotation des tokens CI/CD tous les 90 jours
7. Branch protection rules
main:
- Require PR (no direct push)
- Require status checks: lint, test, build
- Require 1 review minimum
- Dismiss stale reviews on push
- Require linear history (no merge commits)
develop:
- Require status checks: lint, test
- Allow direct push (fast iteration)
Anti-patterns
npm installau lieu denpm ci(non déterministe)- Pas de cache (pipeline 30 min au lieu de 5)
- Tests skip en CI pour "aller plus vite"
- Déploiement sans health check
- Pas de rollback automatique
- Secrets dans le code du workflow
- Deploy sur prod sans environment gate
Références
- [[KNOW-PAT-222]] — DevSecOps Pipeline Setup (SAST, SCA, secret scanning)
- [[KNOW-PAT-226]] — Testing Strategy (pyramide, coverage)
- [[KNOW-PAT-225]] — Secrets Management
- [[KNOW-REF-040]] — Docker Documentation
- [[KNOW-REF-041]] — Kubernetes Documentation