Dernier volet de notre série Architecture Symfony. Après l'architecture hexagonale, les patterns CQRS et la sécurité, on passe au déploiement. Un code parfait qui ne se déploie pas de manière fiable ne sert à rien. Voyons comment construire un pipeline CI/CD complet pour Symfony avec GitHub Actions.
Les 5 étapes d'un pipeline Symfony robuste
Un pipeline CI/CD Symfony professionnel se décompose en cinq jobs ordonnés : lint, test, sécurité, mutation testing et déploiement. Chaque job agit comme un quality gate : si un seul échoue, le déploiement est bloqué.
- Lint — PHP-CS-Fixer (style de code) + PHPStan (analyse statique niveau max)
- Tests — PHPUnit avec couverture de code (unitaires + intégration + fonctionnels)
- Sécurité — Composer audit (vulnérabilités des dépendances) + vérification des secrets
- Mutation testing — Infection pour valider la qualité des tests eux-mêmes
- Déploiement — Build et deploy uniquement si tous les gates sont passés
Le workflow GitHub Actions complet
Voici le fichier .github/workflows/ci.yml que nous utilisons en production. Il est conçu pour un projet Symfony avec PostgreSQL et Redis.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
code-quality:
name: Code Quality (PHP ${{ matrix.php }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ['8.2', '8.3', '8.4']
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: mbstring, xml, ctype, iconv, intl, pdo_pgsql
coverage: xdebug
tools: composer:v2
- name: Cache Composer
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
- name: Install Dependencies
run: composer install --no-interaction --prefer-dist
- name: PHP CS Fixer
run: vendor/bin/php-cs-fixer fix --dry-run --diff
- name: PHPStan
run: vendor/bin/phpstan analyse --level=max --memory-limit=1G
security:
name: Security Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- name: Composer Audit
run: composer audit
- name: Security Checker
uses: symfonycorp/security-checker-action@v5
tests:
name: Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: test_db
POSTGRES_USER: test
POSTGRES_PASSWORD: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: mbstring, xml, ctype, iconv, intl, pdo_pgsql, redis
coverage: xdebug
- name: Install Dependencies
run: composer install --no-interaction
- name: Run Tests with Coverage
run: XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-clover=var/coverage/clover.xml
env:
DATABASE_URL: postgresql://test:test@127.0.0.1:5432/test_db
REDIS_URL: redis://127.0.0.1:6379
- name: Upload Coverage
uses: codecov/codecov-action@v4
with:
files: ./var/coverage/clover.xml
fail_ci_if_error: true
mutation:
name: Mutation Testing
runs-on: ubuntu-latest
needs: tests
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
coverage: xdebug
- name: Install Dependencies
run: composer install --no-interaction
- name: Infection
run: vendor/bin/infection --min-msi=80 --min-covered-msi=90Les quality gates : vos gardiens automatiques
Un quality gate est une condition bloquante. Si elle n'est pas remplie, le code ne passe pas en production. Voici les gates recommandés pour un projet Symfony professionnel.
- PHPStan niveau max — Zéro erreur d'analyse statique
- PHP-CS-Fixer — Zéro violation de style de code
- Tests — 100 % des tests passent
- Couverture — Minimum 80 % de code coverage
- Mutation Score (MSI) — Minimum 80 %, covered MSI minimum 90 %
- Vulnérabilités — Zéro vulnérabilité connue dans les dépendances
Besoin d'un expert Symfony ?
Réserver un appel →Les services PostgreSQL et Redis dans le pipeline
GitHub Actions permet de lancer des services containers directement dans le job. C'est indispensable pour les tests d'intégration et fonctionnels qui nécessitent une vraie base de données.
Le healthcheck sur chaque service garantit que PostgreSQL et Redis sont prêts avant de lancer les tests. Sans ça, tu auras des échecs intermittents liés au timing de démarrage.
Le Makefile : l'interface unifiée
Le Makefile est le point d'entrée unique pour toutes les commandes qualité, que ce soit en local ou en CI. Voici les targets essentielles.
.PHONY: qa
qa: cs-check analyse test infection ## Toutes les vérifications qualité
.PHONY: cs-check
cs-check: ## Vérifie le code style
@vendor/bin/php-cs-fixer fix --dry-run --diff
.PHONY: analyse
analyse: ## PHPStan + Psalm
@vendor/bin/phpstan analyse --level=max --memory-limit=1G
.PHONY: test
test: ## Lance les tests PHPUnit
@vendor/bin/phpunit
.PHONY: test-coverage
test-coverage: ## Tests avec couverture
@XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=var/coverage
.PHONY: infection
infection: ## Mutation testing
@vendor/bin/infection --min-msi=80 --min-covered-msi=90Les métriques cibles
- PHPStan — Level max, 0 erreur
- PHP-CS-Fixer — 0 violation
- Tests — 100 % passent
- Coverage — >= 80 %
- MSI (Mutation Score) — >= 80 %
- Vulnérabilités — 0
Cette série Architecture Symfony touche à sa fin. De l'architecture hexagonale au pipeline CI/CD, tu as maintenant les fondations d'un projet Symfony professionnel. Si tu as un projet existant qui nécessite une mise à niveau, notre offre Bear Upgrade propose des audits et migrations automatisées. Réserve un appel pour en discuter.
Besoin d'un expert Symfony ?
20 ans d'expérience sur l'écosystème PHP/Symfony.