Les utilisateurs étaient stockés uniquement dans Redis (CacheUserRepository), ce qui exposait à une perte totale des comptes en cas de restart Redis, FLUSHDB ou perte du volume Docker. Les tables student_guardians et teacher_assignments référençaient des user IDs sans FK réelle. PostgreSQL devient la source de vérité via DoctrineUserRepository (DBAL, upsert ON CONFLICT). CachedUserRepository décore l'interface existante avec le pattern cache-aside : lectures Redis d'abord → miss → PostgreSQL → populate Redis ; écritures PostgreSQL d'abord → mise à jour Redis. Si Redis est indisponible, l'application continue via PostgreSQL seul. Une commande de migration (app:migrate-users-to-postgres) permet de copier les données Redis existantes vers PostgreSQL de manière idempotente.
300 lines
13 KiB
Makefile
300 lines
13 KiB
Makefile
.DEFAULT_GOAL := help
|
|
|
|
# =============================================================================
|
|
# Docker
|
|
# =============================================================================
|
|
|
|
# Fichiers compose - ajouter monitoring si MONITORING=1
|
|
COMPOSE_FILES := -f compose.yaml
|
|
ifdef MONITORING
|
|
COMPOSE_FILES += -f compose.monitoring.yaml
|
|
endif
|
|
|
|
.PHONY: up
|
|
up: ## Lancer les services (ajouter MONITORING=1 pour inclure observabilité)
|
|
docker compose $(COMPOSE_FILES) up -d
|
|
|
|
.PHONY: up-full
|
|
up-full: ## Lancer TOUS les services (app + monitoring)
|
|
docker compose -f compose.yaml -f compose.monitoring.yaml up -d
|
|
|
|
.PHONY: down
|
|
down: ## Arrêter tous les services (app + monitoring)
|
|
docker compose -f compose.yaml -f compose.monitoring.yaml down --remove-orphans
|
|
|
|
.PHONY: restart
|
|
restart: ## Redémarrer les services
|
|
docker compose $(COMPOSE_FILES) down
|
|
docker compose $(COMPOSE_FILES) up -d
|
|
|
|
.PHONY: rebuild
|
|
rebuild: ## Reconstruire et relancer les services (sans cache)
|
|
docker compose $(COMPOSE_FILES) down
|
|
docker compose $(COMPOSE_FILES) build --no-cache
|
|
docker compose $(COMPOSE_FILES) up -d
|
|
|
|
.PHONY: build
|
|
build: ## Reconstruire les images Docker (sans cache)
|
|
docker compose $(COMPOSE_FILES) build --no-cache
|
|
|
|
.PHONY: logs
|
|
logs: ## Voir les logs de tous les services (Ctrl+C pour quitter)
|
|
docker compose $(COMPOSE_FILES) logs -f
|
|
|
|
.PHONY: ps
|
|
ps: ## Afficher le statut des services
|
|
docker compose $(COMPOSE_FILES) ps
|
|
|
|
.PHONY: clean
|
|
clean: ## Supprimer volumes et images locales
|
|
docker compose -f compose.yaml -f compose.monitoring.yaml down -v --rmi local
|
|
|
|
# =============================================================================
|
|
# Monitoring
|
|
# =============================================================================
|
|
|
|
.PHONY: monitoring-up
|
|
monitoring-up: ## Lancer uniquement les services de monitoring
|
|
docker compose -f compose.monitoring.yaml up -d
|
|
|
|
.PHONY: monitoring-down
|
|
monitoring-down: ## Arrêter les services de monitoring
|
|
docker compose -f compose.monitoring.yaml down
|
|
|
|
.PHONY: monitoring-logs
|
|
monitoring-logs: ## Voir les logs du monitoring
|
|
docker compose -f compose.monitoring.yaml logs -f
|
|
|
|
.PHONY: grafana
|
|
grafana: ## Ouvrir Grafana dans le navigateur (http://localhost:3001)
|
|
@echo "Grafana: http://localhost:3001 (admin/admin)"
|
|
@command -v xdg-open >/dev/null && xdg-open http://localhost:3001 || echo "Ouvrir manuellement: http://localhost:3001"
|
|
|
|
.PHONY: prometheus
|
|
prometheus: ## Ouvrir Prometheus dans le navigateur (http://localhost:9090)
|
|
@echo "Prometheus: http://localhost:9090"
|
|
@command -v xdg-open >/dev/null && xdg-open http://localhost:9090 || echo "Ouvrir manuellement: http://localhost:9090"
|
|
|
|
.PHONY: glitchtip
|
|
glitchtip: ## Ouvrir GlitchTip dans le navigateur (http://localhost:8081)
|
|
@echo "GlitchTip: http://localhost:8081"
|
|
@command -v xdg-open >/dev/null && xdg-open http://localhost:8081 || echo "Ouvrir manuellement: http://localhost:8081"
|
|
|
|
# =============================================================================
|
|
# Shell
|
|
# =============================================================================
|
|
|
|
.PHONY: shell
|
|
shell: ## Ouvrir un shell dans le container PHP
|
|
docker compose exec php sh
|
|
|
|
.PHONY: bash
|
|
bash: shell ## Alias pour 'make shell'
|
|
|
|
.PHONY: console
|
|
console: ## Exécuter une commande Symfony (ex: make console c='debug:router')
|
|
docker compose exec php php bin/console $(c)
|
|
|
|
.PHONY: shell-frontend
|
|
shell-frontend: ## Ouvrir un shell dans le container frontend
|
|
docker compose exec frontend sh
|
|
|
|
# =============================================================================
|
|
# Backend - Qualité
|
|
# =============================================================================
|
|
|
|
.PHONY: phpstan
|
|
phpstan: ## Analyse statique PHPStan (level 9)
|
|
docker compose exec php composer phpstan
|
|
|
|
.PHONY: arch
|
|
arch: ## Tests d'architecture PHPat
|
|
docker compose exec php composer arch
|
|
|
|
.PHONY: cs-fix
|
|
cs-fix: ## Corriger le code style PHP (PHP-CS-Fixer)
|
|
docker compose exec php composer cs-fix
|
|
|
|
.PHONY: cs-check
|
|
cs-check: ## Vérifier le code style PHP sans corriger
|
|
docker compose exec php composer cs-check
|
|
|
|
.PHONY: setup-test-db
|
|
setup-test-db: ## Créer et migrer la base de test PostgreSQL
|
|
docker compose exec php php bin/console doctrine:database:create --if-not-exists --env=test -q
|
|
docker compose exec php php bin/console doctrine:migrations:migrate --no-interaction --env=test -q
|
|
|
|
.PHONY: test-php
|
|
test-php: setup-test-db ## Lancer les tests PHPUnit
|
|
docker compose exec -e APP_ENV=test php composer test
|
|
|
|
.PHONY: warmup
|
|
warmup: ## Préchauffer le cache Symfony
|
|
docker compose exec php php bin/console cache:warmup
|
|
|
|
# =============================================================================
|
|
# Frontend - Qualité
|
|
# =============================================================================
|
|
|
|
.PHONY: lint
|
|
lint: ## Lancer ESLint sur le frontend
|
|
docker compose exec frontend pnpm run lint
|
|
|
|
.PHONY: check-types
|
|
check-types: ## Vérifier les types TypeScript (svelte-check)
|
|
docker compose exec frontend pnpm run check
|
|
|
|
.PHONY: test-js
|
|
test-js: ## Lancer les tests Vitest
|
|
docker compose exec frontend pnpm run test
|
|
|
|
.PHONY: e2e
|
|
e2e: e2e-ci e2e-ratelimit ## Lancer tous les tests E2E (CI + rate limiting)
|
|
|
|
.PHONY: e2e-ci
|
|
e2e-ci: ## Lancer les tests E2E sans rate limiting (rapide, parallèle)
|
|
docker compose exec php php bin/console cache:pool:clear cache.rate_limiter --env=dev
|
|
cd frontend && CI=true PLAYWRIGHT_BASE_URL=http://ecole-alpha.classeo.local:5174 npx playwright test
|
|
|
|
.PHONY: e2e-ratelimit
|
|
e2e-ratelimit: ## Lancer les tests de rate limiting (lent, séquentiel)
|
|
docker compose exec php php bin/console cache:pool:clear cache.rate_limiter --env=dev
|
|
cd frontend && PLAYWRIGHT_BASE_URL=http://ecole-alpha.classeo.local:5174 npx playwright test --workers=1 --grep="Rate Limiting|CAPTCHA"
|
|
|
|
# =============================================================================
|
|
# Tout-en-un
|
|
# =============================================================================
|
|
|
|
.PHONY: test
|
|
test: test-php test-js ## Lancer tous les tests (PHPUnit + Vitest)
|
|
|
|
.PHONY: check
|
|
check: phpstan cs-check lint check-types ## Lancer tous les linters et checks
|
|
|
|
.PHONY: ci
|
|
ci: ## Lancer TOUS les tests et checks (comme en CI)
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo " Code Style PHP (PHP-CS-Fixer)"
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@$(MAKE) cs-check
|
|
@echo ""
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo " Analyse statique PHP (PHPStan level 9)"
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@$(MAKE) phpstan
|
|
@echo ""
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo " Tests d'architecture (PHPat)"
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@$(MAKE) arch
|
|
@echo ""
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo " Tests PHP (PHPUnit)"
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@$(MAKE) test-php
|
|
@echo ""
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo " Lint Frontend (ESLint)"
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@$(MAKE) lint
|
|
@echo ""
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo " Types Frontend (svelte-check)"
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@$(MAKE) check-types
|
|
@echo ""
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo " Tests Frontend (Vitest)"
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@$(MAKE) test-js
|
|
@echo ""
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo " ✅ Tous les checks sont passés !"
|
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@echo ""
|
|
@echo " Note: Tests E2E (make e2e) à lancer séparément depuis l'hôte"
|
|
|
|
# =============================================================================
|
|
# Scripts
|
|
# =============================================================================
|
|
|
|
.PHONY: setup-hooks
|
|
setup-hooks: ## Installer les git hooks (pre-push: make ci)
|
|
@echo "Installation des git hooks..."
|
|
@cp scripts/hooks/pre-push .git/hooks/pre-push
|
|
@chmod +x .git/hooks/pre-push
|
|
@echo "✅ Git hooks installés (pre-push)"
|
|
|
|
.PHONY: check-bc
|
|
check-bc: ## Vérifier l'isolation des Bounded Contexts
|
|
./scripts/check-bc-isolation.sh
|
|
|
|
.PHONY: check-naming
|
|
check-naming: ## Vérifier les conventions de nommage
|
|
./scripts/check-naming.sh
|
|
|
|
.PHONY: check-tenants
|
|
check-tenants: ## Vérifier que les tenants répondent
|
|
./scripts/check-tenants.sh
|
|
|
|
# =============================================================================
|
|
# Setup initial
|
|
# =============================================================================
|
|
|
|
.PHONY: install
|
|
install: up jwt-keys setup-hooks migrate warmup ## Installation complète après clone
|
|
|
|
.PHONY: migrate
|
|
migrate: ## Exécuter les migrations Doctrine
|
|
docker compose exec php php bin/console doctrine:database:create --if-not-exists
|
|
docker compose exec php php bin/console doctrine:migrations:migrate --no-interaction
|
|
|
|
.PHONY: jwt-keys
|
|
jwt-keys: ## Générer les clés JWT (requis après clone)
|
|
@echo "Génération des clés JWT..."
|
|
@docker compose exec php mkdir -p config/jwt
|
|
@docker compose exec php openssl genpkey -out config/jwt/private.pem -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096 -pass pass:$${JWT_PASSPHRASE:-classeo_jwt_passphrase_change_me}
|
|
@docker compose exec php openssl pkey -in config/jwt/private.pem -out config/jwt/public.pem -pubout -passin pass:$${JWT_PASSPHRASE:-classeo_jwt_passphrase_change_me}
|
|
@echo "Clés JWT générées dans backend/config/jwt/"
|
|
|
|
# =============================================================================
|
|
# Dev helpers
|
|
# =============================================================================
|
|
|
|
.PHONY: token
|
|
token: ## Créer un token d'activation (interactif). Options: email=, role=, tenant=, minor=1
|
|
docker compose exec php php bin/console app:dev:create-test-activation-token \
|
|
$(if $(email),--email=$(email),) \
|
|
$(if $(role),--role=$(role),) \
|
|
$(if $(tenant),--tenant=$(tenant),) \
|
|
$(if $(minor),--minor,) \
|
|
--base-url=http://localhost:5174
|
|
|
|
.PHONY: token-alpha
|
|
token-alpha: ## Créer un token sur ecole-alpha. Options: email=, role=, minor=1
|
|
docker compose exec -T php php bin/console app:dev:create-test-activation-token -n \
|
|
--tenant=ecole-alpha --base-url=http://ecole-alpha.classeo.local:5174 \
|
|
$(if $(email),--email=$(email),--email=alpha@test.com) \
|
|
$(if $(role),--role=$(role),) \
|
|
$(if $(minor),--minor,)
|
|
|
|
.PHONY: token-beta
|
|
token-beta: ## Créer un token sur ecole-beta. Options: email=, role=, minor=1
|
|
docker compose exec -T php php bin/console app:dev:create-test-activation-token -n \
|
|
--tenant=ecole-beta --base-url=http://ecole-beta.classeo.local:5174 \
|
|
$(if $(email),--email=$(email),--email=beta@test.com) \
|
|
$(if $(role),--role=$(role),) \
|
|
$(if $(minor),--minor,)
|
|
|
|
# =============================================================================
|
|
# Help
|
|
# =============================================================================
|
|
|
|
.PHONY: help
|
|
help: ## Afficher cette aide
|
|
@echo ""
|
|
@echo " Classeo - Commandes disponibles"
|
|
@echo ""
|
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}'
|
|
@echo ""
|