chore: remplace le Makefile par un service compose wakdo-migrate (migrate + seed idempotents)
All checks were successful
All checks were successful
Le Makefile portait surtout des cibles mortes/trompeuses (test/test-unit/ test-integration/lint annoncaient "pas implemente" alors que les tests tournent ; install-hooks pointait sur des fichiers absents) ; sa seule cible porteuse, `init`, existait parce que `docker compose up` seul n'applique pas les migrations. En deplacant migrate + seed DANS la stack, `docker compose up` devient l'unique commande qui amene une stack complete et loginnable -> Cr 7.c.4 satisfait sans dependance a l'outil `make`. - db/migrate-container.sh : runner in-container (connexion par le reseau compose), applique db/migrations/*.sql (suivi schema_migrations) puis db/seeds/*.sql (suivi seeds_applied), idempotent. - Service one-shot `wakdo-migrate` (depends_on db healthy) ; wakdo-app/web attendent sa completion (service_completed_successfully). - Makefile supprime ; db/migrate.sh (hote) conserve pour l'usage manuel / --status. - Docs realignees : README, .env.example, db/README, docker-compose, PROJECT_CONTEXT (`make *` -> `docker compose *`, Cr 7.b porte par les scripts Bash). Correction au passage : la CI/CD est Forgejo Actions (pas GitHub Actions), protections cote Forgejo. - Journal : docs/journal/2026-06-17--makefile-to-compose-migrate.md (rationale + verif sur base ephemere : 2 migrations + 2 seeds, idempotent ; note de deploiement pour les bases deja seedees). Verifie : docker compose config valide ; runner teste sur MariaDB ephemere (5 roles, 23 permissions, admin present) ; re-run = 0 nouveau. Aucun code PHP/JS touche.
This commit is contained in:
parent
d880f2512a
commit
56b26db0c1
10 changed files with 236 additions and 276 deletions
|
|
@ -157,9 +157,8 @@ TRAEFIK_DOMAIN_ADMIN=admin.example.com
|
||||||
# traefik - setups simples
|
# traefik - setups simples
|
||||||
# proxy - autre convention frequente
|
# proxy - autre convention frequente
|
||||||
#
|
#
|
||||||
# Le reseau doit exister AVANT 'make init' (cree par votre stack de
|
# Le reseau doit exister AVANT 'docker compose up' (cree par votre stack de
|
||||||
# reverse proxy, ou manuellement : docker network create <nom>).
|
# reverse proxy, ou manuellement : docker network create <nom>). Sinon
|
||||||
# La cible 'make init' echoue proprement avec un message d'aide si le
|
# 'docker compose up' echoue avec une erreur sur le reseau externe introuvable.
|
||||||
# reseau est introuvable.
|
|
||||||
|
|
||||||
REVERSE_PROXY_NETWORK=traefik_proxy
|
REVERSE_PROXY_NETWORK=traefik_proxy
|
||||||
|
|
|
||||||
233
Makefile
233
Makefile
|
|
@ -1,233 +0,0 @@
|
||||||
#
|
|
||||||
# Wakdo - Makefile d'orchestration locale
|
|
||||||
#
|
|
||||||
# Conventions :
|
|
||||||
# - Une cible = une action unitaire. Les cibles composites sont commentees.
|
|
||||||
# - Chaque cible est documentee par un `## description` pour auto-help.
|
|
||||||
# - Echec sur erreur (set -e implicite via bash recipes + pipefail).
|
|
||||||
#
|
|
||||||
# Documentation :
|
|
||||||
# make help
|
|
||||||
#
|
|
||||||
|
|
||||||
SHELL := /usr/bin/env bash
|
|
||||||
.SHELLFLAGS := -eu -o pipefail -c
|
|
||||||
|
|
||||||
# === Configuration ===
|
|
||||||
|
|
||||||
# Chargement du .env s'il existe (variables Make + export pour docker compose)
|
|
||||||
ifneq (,$(wildcard .env))
|
|
||||||
include .env
|
|
||||||
export
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Prefixe du projet compose (utilise pour nommer les containers)
|
|
||||||
PROJECT := wakdo
|
|
||||||
|
|
||||||
# Nom du fichier compose (override possible : make up COMPOSE_FILE=docker-compose.prod.yml)
|
|
||||||
COMPOSE_FILE := docker-compose.yml
|
|
||||||
COMPOSE := docker compose -f $(COMPOSE_FILE) -p $(PROJECT)
|
|
||||||
|
|
||||||
# Services docker-compose
|
|
||||||
SERVICE_WEB := wakdo-web
|
|
||||||
SERVICE_APP := wakdo-app
|
|
||||||
SERVICE_DB := wakdo-db
|
|
||||||
SERVICE_CRON := wakdo-cron
|
|
||||||
|
|
||||||
# === Meta ===
|
|
||||||
|
|
||||||
.DEFAULT_GOAL := help
|
|
||||||
.PHONY: help
|
|
||||||
help: ## Liste toutes les cibles disponibles avec leur description
|
|
||||||
@echo "Wakdo - cibles Make disponibles :"
|
|
||||||
@echo ""
|
|
||||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " \033[1m%-22s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
|
|
||||||
@echo ""
|
|
||||||
|
|
||||||
# === Orchestration principale ===
|
|
||||||
|
|
||||||
.PHONY: init
|
|
||||||
init: ## Build et demarre toute la stack en une commande (Cr RNCP 7.c.4)
|
|
||||||
@test -f .env || { echo "ERREUR: .env manquant. Executer : cp .env.example .env"; exit 1; }
|
|
||||||
@$(MAKE) --no-print-directory check-env
|
|
||||||
@echo "[init] Verification du reseau docker '$(REVERSE_PROXY_NETWORK)'..."
|
|
||||||
@docker network inspect $(REVERSE_PROXY_NETWORK) >/dev/null 2>&1 || { \
|
|
||||||
echo "ERREUR: reseau docker '$(REVERSE_PROXY_NETWORK)' introuvable."; \
|
|
||||||
echo " - Si un Traefik est installe sur l'hote, verifier le nom de son reseau ;"; \
|
|
||||||
echo " - Adapter REVERSE_PROXY_NETWORK dans .env en consequence ;"; \
|
|
||||||
echo " - Sinon creer le reseau manuellement :"; \
|
|
||||||
echo " docker network create $(REVERSE_PROXY_NETWORK)"; \
|
|
||||||
exit 1; }
|
|
||||||
@echo "[init] Build des images..."
|
|
||||||
@$(COMPOSE) build
|
|
||||||
@echo "[init] Demarrage des services..."
|
|
||||||
@$(COMPOSE) up -d
|
|
||||||
@echo "[init] Attente de la base de donnees..."
|
|
||||||
@$(MAKE) --no-print-directory wait-db
|
|
||||||
@echo "[init] Execution des migrations..."
|
|
||||||
@$(MAKE) --no-print-directory migrate
|
|
||||||
@echo "[init] Stack operationnelle."
|
|
||||||
@$(COMPOSE) ps
|
|
||||||
|
|
||||||
.PHONY: up
|
|
||||||
up: ## Demarre les services sans rebuild
|
|
||||||
@$(COMPOSE) up -d
|
|
||||||
|
|
||||||
.PHONY: down
|
|
||||||
down: ## Arrete et supprime les containers (volumes preserves)
|
|
||||||
@$(COMPOSE) down
|
|
||||||
|
|
||||||
.PHONY: stop
|
|
||||||
stop: ## Arrete les services sans les supprimer
|
|
||||||
@$(COMPOSE) stop
|
|
||||||
|
|
||||||
.PHONY: restart
|
|
||||||
restart: ## Redemarre tous les services
|
|
||||||
@$(COMPOSE) restart
|
|
||||||
|
|
||||||
.PHONY: build
|
|
||||||
build: ## Build les images (utilise le cache)
|
|
||||||
@$(COMPOSE) build
|
|
||||||
|
|
||||||
.PHONY: rebuild
|
|
||||||
rebuild: ## Rebuild complet sans cache puis restart
|
|
||||||
@$(COMPOSE) build --no-cache
|
|
||||||
@$(COMPOSE) up -d
|
|
||||||
|
|
||||||
# === Observabilite ===
|
|
||||||
|
|
||||||
.PHONY: ps
|
|
||||||
ps: ## Affiche le statut des services
|
|
||||||
@$(COMPOSE) ps
|
|
||||||
|
|
||||||
.PHONY: logs
|
|
||||||
logs: ## Suit les logs de tous les services (Ctrl+C pour sortir)
|
|
||||||
@$(COMPOSE) logs -f --tail=100
|
|
||||||
|
|
||||||
.PHONY: logs-app
|
|
||||||
logs-app: ## Suit les logs du service applicatif PHP-FPM
|
|
||||||
@$(COMPOSE) logs -f --tail=100 $(SERVICE_APP)
|
|
||||||
|
|
||||||
.PHONY: logs-web
|
|
||||||
logs-web: ## Suit les logs du service web Apache
|
|
||||||
@$(COMPOSE) logs -f --tail=100 $(SERVICE_WEB)
|
|
||||||
|
|
||||||
.PHONY: logs-db
|
|
||||||
logs-db: ## Suit les logs de la base de donnees
|
|
||||||
@$(COMPOSE) logs -f --tail=100 $(SERVICE_DB)
|
|
||||||
|
|
||||||
# === Acces shell ===
|
|
||||||
|
|
||||||
.PHONY: shell-app
|
|
||||||
shell-app: ## Ouvre un shell dans le container applicatif
|
|
||||||
@$(COMPOSE) exec $(SERVICE_APP) sh
|
|
||||||
|
|
||||||
.PHONY: shell-db
|
|
||||||
shell-db: ## Ouvre le client mariadb dans le container de base de donnees
|
|
||||||
@$(COMPOSE) exec $(SERVICE_DB) mariadb -u root -p"$${DB_ROOT_PASSWORD}"
|
|
||||||
|
|
||||||
.PHONY: shell-cron
|
|
||||||
shell-cron: ## Ouvre un shell dans le container cron
|
|
||||||
@$(COMPOSE) exec $(SERVICE_CRON) sh
|
|
||||||
|
|
||||||
# === Verification env ===
|
|
||||||
|
|
||||||
.PHONY: check-env
|
|
||||||
check-env: ## Verifie que les variables critiques Wakdo sont definies dans .env
|
|
||||||
@missing=""; \
|
|
||||||
for var in DB_PASSWORD DB_ROOT_PASSWORD REVERSE_PROXY_NETWORK TRAEFIK_DOMAIN_KIOSK TRAEFIK_DOMAIN_ADMIN APP_URL_KIOSK APP_URL_ADMIN CORS_ALLOWED_ORIGIN; do \
|
|
||||||
if [ -z "$${!var:-}" ]; then missing="$$missing $$var"; fi; \
|
|
||||||
done; \
|
|
||||||
if [ -n "$$missing" ]; then \
|
|
||||||
echo "ERREUR: variables manquantes dans .env :$$missing"; \
|
|
||||||
echo "Conseil : si vous aviez un .env pre-existant (tooling externe),"; \
|
|
||||||
echo " merger les variables manquantes depuis .env.example au lieu"; \
|
|
||||||
echo " d'ecraser le fichier."; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# === Base de donnees ===
|
|
||||||
|
|
||||||
.PHONY: wait-db
|
|
||||||
wait-db: ## Attend que la base de donnees accepte les connexions (timeout 60s)
|
|
||||||
@echo "[wait-db] En attente de MariaDB..."
|
|
||||||
@timeout 60 bash -c 'until $(COMPOSE) exec -T $(SERVICE_DB) healthcheck.sh --connect --innodb_initialized >/dev/null 2>&1; do sleep 2; done' \
|
|
||||||
|| { echo "ERREUR: MariaDB ne repond pas apres 60s"; $(COMPOSE) logs --tail=50 $(SERVICE_DB); exit 1; }
|
|
||||||
@echo "[wait-db] OK"
|
|
||||||
|
|
||||||
.PHONY: migrate
|
|
||||||
migrate: ## Applique les migrations SQL en attente (db/migrations/)
|
|
||||||
@bash db/migrate.sh
|
|
||||||
|
|
||||||
.PHONY: seed
|
|
||||||
seed: ## Charge les donnees de demo (db/seeds/)
|
|
||||||
@bash db/seed.sh
|
|
||||||
|
|
||||||
.PHONY: backup
|
|
||||||
backup: ## Declenche un dump SQL horodate immediat (via le container cron)
|
|
||||||
@mkdir -p ./var/backups
|
|
||||||
@echo "[backup] Execution manuelle de /scripts/backup-db.sh dans wakdo-cron..."
|
|
||||||
@$(COMPOSE) exec -T $(SERVICE_CRON) /scripts/backup-db.sh
|
|
||||||
@echo "[backup] Dernier dump :"
|
|
||||||
@ls -lh ./var/backups/ | tail -n 1
|
|
||||||
|
|
||||||
.PHONY: backup-ls
|
|
||||||
backup-ls: ## Liste les dumps SQL presents dans ./var/backups/
|
|
||||||
@ls -lh ./var/backups/ 2>/dev/null || echo "[backup-ls] Pas de backups (./var/backups/ vide ou inexistant)."
|
|
||||||
|
|
||||||
# === Tests ===
|
|
||||||
|
|
||||||
.PHONY: test
|
|
||||||
test: ## Lance la suite complete de tests PHPUnit [a venir]
|
|
||||||
@echo "[test] Pas encore implemente. PHPUnit via .phar sera configure en P2."
|
|
||||||
|
|
||||||
.PHONY: test-unit
|
|
||||||
test-unit: ## Lance uniquement les tests unitaires [a venir]
|
|
||||||
@echo "[test-unit] Pas encore implemente."
|
|
||||||
|
|
||||||
.PHONY: test-integration
|
|
||||||
test-integration: ## Lance uniquement les tests d'integration [a venir]
|
|
||||||
@echo "[test-integration] Pas encore implemente."
|
|
||||||
|
|
||||||
# === Qualite code ===
|
|
||||||
|
|
||||||
.PHONY: lint
|
|
||||||
lint: ## Lance php -l sur tous les fichiers src/ [a venir]
|
|
||||||
@echo "[lint] Pas encore implemente. PHP syntax check via php -l + outil de style en P2."
|
|
||||||
|
|
||||||
# === Nettoyage ===
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean: ## Stop + suppression containers + volumes (DESTRUCTIF, demande confirmation)
|
|
||||||
@read -p "Supprimer containers ET volumes (les donnees seront perdues) ? [y/N] " ans; \
|
|
||||||
if [ "$$ans" = "y" ] || [ "$$ans" = "Y" ]; then \
|
|
||||||
$(COMPOSE) down -v; \
|
|
||||||
echo "[clean] Stack et volumes supprimes."; \
|
|
||||||
else \
|
|
||||||
echo "[clean] Annule."; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
.PHONY: clean-force
|
|
||||||
clean-force: ## Version non interactive de clean (pour CI uniquement)
|
|
||||||
@$(COMPOSE) down -v
|
|
||||||
|
|
||||||
# === Documentation ===
|
|
||||||
|
|
||||||
.PHONY: docs-render
|
|
||||||
docs-render: ## Regenere les diagrammes Mermaid (docs/**/_diagrams/*.mmd -> *.svg)
|
|
||||||
@echo "[docs-render] Recherche des sources Mermaid sous docs/..."
|
|
||||||
@count=0; \
|
|
||||||
for src in $$(find docs -name '*.mmd' -path '*/_diagrams/*'); do \
|
|
||||||
out="$${src%.mmd}.svg"; \
|
|
||||||
echo " $$src -> $$out"; \
|
|
||||||
npx -y -p @mermaid-js/mermaid-cli mmdc -i "$$src" -o "$$out" >/dev/null 2>&1 \
|
|
||||||
|| { echo "[docs-render] ECHEC sur $$src"; exit 1; }; \
|
|
||||||
count=$$((count + 1)); \
|
|
||||||
done; \
|
|
||||||
echo "[docs-render] $$count diagramme(s) genere(s)."
|
|
||||||
|
|
||||||
# === Hooks Git ===
|
|
||||||
|
|
||||||
.PHONY: install-hooks
|
|
||||||
install-hooks: ## Installe les hooks git depuis .githooks/ [a venir]
|
|
||||||
@echo "[install-hooks] Pas encore implemente. Voir scripts/install-hooks.sh a venir."
|
|
||||||
32
README.md
32
README.md
|
|
@ -55,9 +55,9 @@ Realisation avec l'assistance d'outils d'IA generative (Claude Code, BYAN), conf
|
||||||
| Tests | PHPUnit | 11.x (`.phar` autonome, sans Composer) |
|
| Tests | PHPUnit | 11.x (`.phar` autonome, sans Composer) |
|
||||||
| Front | HTML5 + CSS3 + JS ES6+ vanilla | — |
|
| Front | HTML5 + CSS3 + JS ES6+ vanilla | — |
|
||||||
| Conteneurisation | Docker + docker compose v2 | — |
|
| Conteneurisation | Docker + docker compose v2 | — |
|
||||||
| Orchestration locale | Makefile | — |
|
| Orchestration locale | docker compose v2 (service one-shot `wakdo-migrate`) | — |
|
||||||
| CI/CD | GitHub Actions | — |
|
| CI/CD | Forgejo Actions | — |
|
||||||
| Versioning | Git + GitHub | Conventional Commits |
|
| Versioning | Git + Forgejo (`git.acadenice.com`, miroir GitHub) | Conventional Commits |
|
||||||
|
|
||||||
Detail et justifications : `docs/PROJECT_CONTEXT.md` section 6.
|
Detail et justifications : `docs/PROJECT_CONTEXT.md` section 6.
|
||||||
|
|
||||||
|
|
@ -106,19 +106,22 @@ git clone git@github.com:AcadeNice/wakdo_corentin.git
|
||||||
cd wakdo_corentin
|
cd wakdo_corentin
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Editer .env : DB_PASSWORD, DB_ROOT_PASSWORD, APP_URL_*, TRAEFIK_DOMAIN_*
|
# Editer .env : DB_PASSWORD, DB_ROOT_PASSWORD, APP_URL_*, TRAEFIK_DOMAIN_*
|
||||||
make init
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Attention au `.env` pre-existant.** Si un fichier `.env` existe deja a la racine (tooling externe, autre plateforme installee dans le meme repertoire), **ne pas faire** `cp .env.example .env` — cela ecraserait les variables existantes. Faire un **merge manuel** a la place : ajouter les variables manquantes du template dans le `.env` actuel. Les prefixes de variables de ce projet (`APP_`, `DB_`, `SESSION_`, `CORS_`, `UPLOAD_`, `CRON_`, `TRAEFIK_`, `REVERSE_PROXY_`) sont disjoints de ceux utilises par des outils tiers courants, donc la cohabitation est safe.
|
> **Attention au `.env` pre-existant.** Si un fichier `.env` existe deja a la racine (tooling externe, autre plateforme installee dans le meme repertoire), **ne pas faire** `cp .env.example .env` — cela ecraserait les variables existantes. Faire un **merge manuel** a la place : ajouter les variables manquantes du template dans le `.env` actuel. Les prefixes de variables de ce projet (`APP_`, `DB_`, `SESSION_`, `CORS_`, `UPLOAD_`, `CRON_`, `TRAEFIK_`, `REVERSE_PROXY_`) sont disjoints de ceux utilises par des outils tiers courants, donc la cohabitation est safe.
|
||||||
|
|
||||||
Critere RNCP Cr 7.c.4 couvert : une seule commande (`make init`) orchestre build, demarrage, attente BDD, migrations et seed.
|
Critere RNCP Cr 7.c.4 couvert : une seule commande (`docker compose up -d`) lance la
|
||||||
|
stack complete. Le service one-shot `wakdo-migrate` applique le schema (migrations)
|
||||||
|
puis les donnees de reference (seed) avant que l'app ne serve ; `wakdo-app`/`wakdo-web`
|
||||||
|
attendent sa completion (`depends_on: service_completed_successfully`). Migrations et
|
||||||
|
seed sont idempotents (tables de suivi `schema_migrations` / `seeds_applied`).
|
||||||
|
Detail : `docs/journal/2026-06-17--makefile-to-compose-migrate.md`.
|
||||||
|
|
||||||
Services accessibles apres `make init` :
|
Services accessibles apres `docker compose up -d` :
|
||||||
- Borne : la valeur de `TRAEFIK_DOMAIN_KIOSK` dans `.env`
|
- Borne : la valeur de `TRAEFIK_DOMAIN_KIOSK` dans `.env`
|
||||||
- Admin + API : la valeur de `TRAEFIK_DOMAIN_ADMIN` dans `.env`
|
- Admin + API : la valeur de `TRAEFIK_DOMAIN_ADMIN` dans `.env`
|
||||||
|
|
||||||
Liste complete des cibles : `make help`.
|
|
||||||
|
|
||||||
### Installation Docker sur un hote neuf (Debian / Ubuntu)
|
### Installation Docker sur un hote neuf (Debian / Ubuntu)
|
||||||
|
|
||||||
Procedure officielle detaillee : `https://docs.docker.com/engine/install/` (selectionner la distribution). Resume pour Debian stable :
|
Procedure officielle detaillee : `https://docs.docker.com/engine/install/` (selectionner la distribution). Resume pour Debian stable :
|
||||||
|
|
@ -153,13 +156,13 @@ docker network create mon_reseau_proxy
|
||||||
# REVERSE_PROXY_NETWORK=mon_reseau_proxy
|
# REVERSE_PROXY_NETWORK=mon_reseau_proxy
|
||||||
```
|
```
|
||||||
|
|
||||||
Avant le premier `make init`, s'assurer que le reseau existe. Verification rapide :
|
Avant le premier `docker compose up`, s'assurer que le reseau existe. Verification rapide :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker network inspect "$(grep ^REVERSE_PROXY_NETWORK .env | cut -d= -f2)"
|
docker network inspect "$(grep ^REVERSE_PROXY_NETWORK .env | cut -d= -f2)"
|
||||||
```
|
```
|
||||||
|
|
||||||
Si la commande retourne une erreur, soit adapter `REVERSE_PROXY_NETWORK` au nom du reseau utilise par votre proxy, soit creer le reseau manuellement. La cible `make init` echoue proprement avec un message d'aide si le reseau est introuvable.
|
Si la commande retourne une erreur, soit adapter `REVERSE_PROXY_NETWORK` au nom du reseau utilise par votre proxy, soit creer le reseau manuellement (le reseau externe doit exister avant `docker compose up`).
|
||||||
|
|
||||||
*Section mise a jour au fil de l'implementation (migrations reelles, seed, CI/CD deploiement).*
|
*Section mise a jour au fil de l'implementation (migrations reelles, seed, CI/CD deploiement).*
|
||||||
|
|
||||||
|
|
@ -170,8 +173,8 @@ Si la commande retourne une erreur, soit adapter `REVERSE_PROXY_NETWORK` au nom
|
||||||
```
|
```
|
||||||
.
|
.
|
||||||
|-- .claude/ # Methodologie BYAN (visible jury : CLAUDE.md + rules/)
|
|-- .claude/ # Methodologie BYAN (visible jury : CLAUDE.md + rules/)
|
||||||
|-- .github/
|
|-- .forgejo/
|
||||||
| `-- workflows/ # CI/CD GitHub Actions [a venir]
|
| `-- workflows/ # CI Forgejo Actions (ci.yml : secret-scan, php-lint, static-tests, js-tests, auto-merge)
|
||||||
|-- .githooks/ # pre-commit + commit-msg [a venir]
|
|-- .githooks/ # pre-commit + commit-msg [a venir]
|
||||||
|-- docker/ # Dockerfiles customs par service
|
|-- docker/ # Dockerfiles customs par service
|
||||||
| |-- apache/
|
| |-- apache/
|
||||||
|
|
@ -199,7 +202,6 @@ Si la commande retourne une erreur, soit adapter `REVERSE_PROXY_NETWORK` au nom
|
||||||
|-- .env.example
|
|-- .env.example
|
||||||
|-- .dockerignore
|
|-- .dockerignore
|
||||||
|-- .gitignore
|
|-- .gitignore
|
||||||
|-- Makefile
|
|
||||||
|-- docker-compose.yml
|
|-- docker-compose.yml
|
||||||
`-- README.md
|
`-- README.md
|
||||||
```
|
```
|
||||||
|
|
@ -212,7 +214,7 @@ Si la commande retourne une erreur, soit adapter `REVERSE_PROXY_NETWORK` au nom
|
||||||
|
|
||||||
- **Commits** : Conventional Commits en anglais (`feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `ci`, `db`, `perf`, `style`). Format : `type(scope): description`. Voir `docs/PROJECT_CONTEXT.md` section 9.
|
- **Commits** : Conventional Commits en anglais (`feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `ci`, `db`, `perf`, `style`). Format : `type(scope): description`. Voir `docs/PROJECT_CONTEXT.md` section 9.
|
||||||
- **Branches** : `feat/*`, `fix/*`, `refactor/*`, `docs/*`, `ci/*`, `db/*`, `chore/*`, `test/*` depuis `dev`. Merge vers `dev` par PR squashee. Periodiquement `dev` -> `main` par PR avec tag semver.
|
- **Branches** : `feat/*`, `fix/*`, `refactor/*`, `docs/*`, `ci/*`, `db/*`, `chore/*`, `test/*` depuis `dev`. Merge vers `dev` par PR squashee. Periodiquement `dev` -> `main` par PR avec tag semver.
|
||||||
- `main` et `dev` sont proteges cote GitHub (PR requise, force push bloque, resolution des conversations requise).
|
- `main` et `dev` sont proteges cote Forgejo (PR requise, force push bloque, checks requis : secret-scan / php-lint / static-tests).
|
||||||
- Pas d'emoji dans le code, les commits ou les specs techniques (Mantra IA-23).
|
- Pas d'emoji dans le code, les commits ou les specs techniques (Mantra IA-23).
|
||||||
|
|
||||||
*Sections detaillees (setup env de dev, lint, tests) : a completer au fil de l'implementation.*
|
*Sections detaillees (setup env de dev, lint, tests) : a completer au fil de l'implementation.*
|
||||||
|
|
@ -227,7 +229,7 @@ Si la commande retourne une erreur, soit adapter `REVERSE_PROXY_NETWORK` au nom
|
||||||
|
|
||||||
## Deploiement
|
## Deploiement
|
||||||
|
|
||||||
*Section a completer. Strategie cible : CI GitHub Actions sur PR vers `dev` (lint + PHPUnit), CD automatique sur merge vers `main` via SSH + `make rebuild`, voir `docs/PROJECT_CONTEXT.md` section 7 Bloc 5.*
|
*Strategie : CI Forgejo Actions sur PR vers `dev`/`main` (secret-scan gitleaks, php-lint, static-tests PHPStan+PHPUnit, js-tests) avec auto-merge sur label + CI verte. CD : declenchement humain, redeploiement par `docker compose pull && docker compose up -d`. Voir `docs/PROJECT_CONTEXT.md` section 7 Bloc 5.*
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ bash db/migrate.sh --status # liste l'etat sans rien appliquer
|
||||||
Le runner cible le conteneur `wakdo-db` et lit les identifiants dans `.env`
|
Le runner cible le conteneur `wakdo-db` et lit les identifiants dans `.env`
|
||||||
(`DB_NAME`, `DB_ROOT_PASSWORD`). Il maintient une table `schema_migrations`
|
(`DB_NAME`, `DB_ROOT_PASSWORD`). Il maintient une table `schema_migrations`
|
||||||
(une ligne par fichier applique) : relancer ne rejoue que les nouvelles
|
(une ligne par fichier applique) : relancer ne rejoue que les nouvelles
|
||||||
migrations. La cible `make migrate` est destinee a appeler ce script.
|
migrations. La cible `bash db/migrate.sh` est destinee a appeler ce script.
|
||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
|
|
||||||
|
|
|
||||||
66
db/migrate-container.sh
Normal file
66
db/migrate-container.sh
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Wakdo - runner migrations + seed IN-CONTAINER (service compose one-shot wakdo-migrate).
|
||||||
|
#
|
||||||
|
# Applique, dans l'ordre lexicographique et de maniere IDEMPOTENTE :
|
||||||
|
# 1. db/migrations/*.sql (suivi : table schema_migrations)
|
||||||
|
# 2. db/seeds/*.sql (suivi : table seeds_applied)
|
||||||
|
# Relancer ne rejoue que les fichiers en attente (tracking par nom de fichier).
|
||||||
|
#
|
||||||
|
# Contrairement a db/migrate.sh (hote, via `docker exec`), ce runner tourne DANS
|
||||||
|
# un conteneur et se connecte a la base PAR LE RESEAU compose (DB_HOST). Il est
|
||||||
|
# lance par le service `wakdo-migrate` apres que `wakdo-db` soit healthy ; les
|
||||||
|
# services applicatifs (app/web) attendent sa COMPLETION (service_completed_successfully).
|
||||||
|
#
|
||||||
|
# But : `docker compose up` amene une stack COMPLETE et utilisable (schema + donnees
|
||||||
|
# de reference, dont l'admin bootstrap) en une seule commande, sans dependance a
|
||||||
|
# l'hote (Cr 7.c.4) -> remplace `make init`.
|
||||||
|
#
|
||||||
|
# Variables injectees par docker-compose : DB_HOST, DB_PORT, DB_NAME, DB_ROOT_PASSWORD.
|
||||||
|
# Root requis : migrations = DDL, seeds = INSERT de reference.
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
: "${DB_HOST:?DB_HOST manquant}"
|
||||||
|
: "${DB_NAME:?DB_NAME manquant}"
|
||||||
|
: "${DB_ROOT_PASSWORD:?DB_ROOT_PASSWORD manquant}"
|
||||||
|
PORT="${DB_PORT:-3306}"
|
||||||
|
|
||||||
|
db() { mariadb -h "$DB_HOST" -P "$PORT" -uroot -p"$DB_ROOT_PASSWORD" "$@"; }
|
||||||
|
|
||||||
|
# Applique les *.sql d'un dossier non encore enregistres dans sa table de suivi.
|
||||||
|
apply_tracked() {
|
||||||
|
local dir="$1" table="$2"
|
||||||
|
local f base n applied=0
|
||||||
|
|
||||||
|
db "$DB_NAME" -e "CREATE TABLE IF NOT EXISTS ${table} (
|
||||||
|
filename VARCHAR(255) NOT NULL PRIMARY KEY,
|
||||||
|
applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
local files=("$dir"/*.sql)
|
||||||
|
if [ ${#files[@]} -eq 0 ]; then
|
||||||
|
echo "[${table}] aucun fichier dans ${dir}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
for f in "${files[@]}"; do
|
||||||
|
base="$(basename "$f")"
|
||||||
|
n="$(db "$DB_NAME" -N -s -e "SELECT COUNT(*) FROM ${table} WHERE filename='${base}';")"
|
||||||
|
if [ "$n" = "0" ]; then
|
||||||
|
echo "[${table}] application de ${base} ..."
|
||||||
|
db "$DB_NAME" < "$f"
|
||||||
|
db "$DB_NAME" -e "INSERT INTO ${table} (filename) VALUES ('${base}');"
|
||||||
|
applied=$((applied + 1))
|
||||||
|
else
|
||||||
|
echo "[${table}] ${base} deja applique, ignore"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "[${table}] termine (${applied} nouveau(x))."
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "[migrate] cible ${DB_HOST}:${PORT}/${DB_NAME}"
|
||||||
|
apply_tracked /db/migrations schema_migrations
|
||||||
|
apply_tracked /db/seeds seeds_applied
|
||||||
|
echo "[migrate] stack a jour (schema + donnees de reference)."
|
||||||
|
|
@ -7,7 +7,9 @@
|
||||||
# deja appliques, donc relancer ne rejoue que les nouvelles migrations.
|
# deja appliques, donc relancer ne rejoue que les nouvelles migrations.
|
||||||
#
|
#
|
||||||
# Cible : le service docker-compose `wakdo-db` (MariaDB). Lance depuis l'hote
|
# Cible : le service docker-compose `wakdo-db` (MariaDB). Lance depuis l'hote
|
||||||
# (c'est ce que `make migrate` appellera). Identifiants lus dans .env.
|
# (usage manuel / `--status`, identifiants lus dans .env). Au boot de la stack,
|
||||||
|
# c'est le service `wakdo-migrate` (db/migrate-container.sh, via le reseau) qui
|
||||||
|
# applique migrations + seed automatiquement.
|
||||||
#
|
#
|
||||||
# Usage :
|
# Usage :
|
||||||
# bash db/migrate.sh # applique les migrations en attente
|
# bash db/migrate.sh # applique les migrations en attente
|
||||||
|
|
@ -30,7 +32,7 @@ DB_ROOT_PASSWORD="$(grep -E '^DB_ROOT_PASSWORD=' "$ENV_FILE" | cut -d= -f2-)"
|
||||||
db() { docker exec -i "$CONTAINER" mariadb -uroot -p"$DB_ROOT_PASSWORD" "$@"; }
|
db() { docker exec -i "$CONTAINER" mariadb -uroot -p"$DB_ROOT_PASSWORD" "$@"; }
|
||||||
|
|
||||||
# Le conteneur doit etre en marche.
|
# Le conteneur doit etre en marche.
|
||||||
docker exec "$CONTAINER" true 2>/dev/null || { echo "ERREUR : conteneur $CONTAINER non demarre (make up)" >&2; exit 1; }
|
docker exec "$CONTAINER" true 2>/dev/null || { echo "ERREUR : conteneur $CONTAINER non demarre (docker compose up -d)" >&2; exit 1; }
|
||||||
|
|
||||||
# Journal des migrations appliquees.
|
# Journal des migrations appliquees.
|
||||||
db "$DB_NAME" -e "CREATE TABLE IF NOT EXISTS schema_migrations (
|
db "$DB_NAME" -e "CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ DB_ROOT_PASSWORD="$(grep -E '^DB_ROOT_PASSWORD=' "$ENV_FILE" | cut -d= -f2-)"
|
||||||
|
|
||||||
db() { docker exec -i "$CONTAINER" mariadb -uroot -p"$DB_ROOT_PASSWORD" "$@"; }
|
db() { docker exec -i "$CONTAINER" mariadb -uroot -p"$DB_ROOT_PASSWORD" "$@"; }
|
||||||
|
|
||||||
docker exec "$CONTAINER" true 2>/dev/null || { echo "ERREUR : conteneur $CONTAINER non demarre (make up)" >&2; exit 1; }
|
docker exec "$CONTAINER" true 2>/dev/null || { echo "ERREUR : conteneur $CONTAINER non demarre (docker compose up -d)" >&2; exit 1; }
|
||||||
|
|
||||||
if [ ! -d "$SEEDS_DIR" ]; then
|
if [ ! -d "$SEEDS_DIR" ]; then
|
||||||
echo "[seed] aucun repertoire db/seeds/ - rien a charger"
|
echo "[seed] aucun repertoire db/seeds/ - rien a charger"
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@
|
||||||
# wakdo_uploads : named volume pour les uploads produits back-office
|
# wakdo_uploads : named volume pour les uploads produits back-office
|
||||||
# ./var/backups : bind-mount lecture-ecriture pour les dumps SQL
|
# ./var/backups : bind-mount lecture-ecriture pour les dumps SQL
|
||||||
#
|
#
|
||||||
# Variables d'env consommees depuis .env (chargees par make via `include .env`
|
# Variables d'env consommees depuis .env : docker compose lit automatiquement le
|
||||||
# et transmises ici par docker compose qui fait l'expansion automatique).
|
# fichier .env a la racine et fait l'expansion des ${...} ci-dessous.
|
||||||
#
|
#
|
||||||
# Persistance : un `make down` preserve les named volumes. Seul `make clean`
|
# Persistance : `docker compose down` preserve les named volumes ; seul
|
||||||
# (interactif) ou `docker compose down -v` supprime les donnees.
|
# `docker compose down -v` supprime les donnees.
|
||||||
#
|
#
|
||||||
|
|
||||||
name: wakdo
|
name: wakdo
|
||||||
|
|
@ -62,8 +62,7 @@ volumes:
|
||||||
wakdo_db_data:
|
wakdo_db_data:
|
||||||
# Named volume MariaDB. Permissions gerees par Docker (UID mysql=999
|
# Named volume MariaDB. Permissions gerees par Docker (UID mysql=999
|
||||||
# dans le conteneur), zero souci cote hote. Survit a `docker compose down`.
|
# dans le conteneur), zero souci cote hote. Survit a `docker compose down`.
|
||||||
# Pour remise a zero : `make clean` (interactif, confirme) ou
|
# Pour remise a zero : `docker compose down -v` (destructif : supprime les volumes).
|
||||||
# `docker compose down -v` (destructif direct).
|
|
||||||
|
|
||||||
wakdo_uploads:
|
wakdo_uploads:
|
||||||
# Images produits uploadees par les equipiers depuis le back-office.
|
# Images produits uploadees par les equipiers depuis le back-office.
|
||||||
|
|
@ -113,6 +112,38 @@ services:
|
||||||
retries: 6
|
retries: 6
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
|
|
||||||
|
# =======================================================================
|
||||||
|
# wakdo-migrate : service ONE-SHOT (migrations + seed idempotents)
|
||||||
|
# =======================================================================
|
||||||
|
# Tourne une fois apres que wakdo-db soit healthy, applique le schema puis les
|
||||||
|
# donnees de reference (idempotent via schema_migrations / seeds_applied), et
|
||||||
|
# sort. app/web attendent sa COMPLETION : `docker compose up` rend ainsi la stack
|
||||||
|
# complete + utilisable en UNE commande, sans dependance a l'hote (Cr 7.c.4).
|
||||||
|
wakdo-migrate:
|
||||||
|
image: mariadb:11.4
|
||||||
|
container_name: wakdo-migrate
|
||||||
|
restart: "no"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
DB_HOST: ${DB_HOST}
|
||||||
|
DB_PORT: ${DB_PORT}
|
||||||
|
DB_NAME: ${DB_NAME}
|
||||||
|
# Root : migrations = DDL, seeds = INSERT de reference.
|
||||||
|
DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
# migrations + seeds + le runner, en lecture seule.
|
||||||
|
- ./db:/db:ro
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- wakdo_internal
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
wakdo-db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
entrypoint: ["bash", "/db/migrate-container.sh"]
|
||||||
|
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
# wakdo-app : PHP-FPM 8.3 (execute le code back-office + API)
|
# wakdo-app : PHP-FPM 8.3 (execute le code back-office + API)
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
|
|
@ -171,13 +202,16 @@ services:
|
||||||
|
|
||||||
# Named volume pour les uploads, plus specifique que le bind-mount
|
# Named volume pour les uploads, plus specifique que le bind-mount
|
||||||
# parent : les uploads ne vont pas dans ./src, ils restent dans le
|
# parent : les uploads ne vont pas dans ./src, ils restent dans le
|
||||||
# volume Docker et survivent aux `make down`.
|
# volume Docker et survivent aux `docker compose down`.
|
||||||
- wakdo_uploads:/var/www/html/public/uploads
|
- wakdo_uploads:/var/www/html/public/uploads
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
- wakdo_internal
|
- wakdo_internal
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
|
# Le schema + les donnees de reference sont en place AVANT que l'app serve.
|
||||||
|
wakdo-migrate:
|
||||||
|
condition: service_completed_successfully
|
||||||
wakdo-db:
|
wakdo-db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
|
|
@ -210,6 +244,8 @@ services:
|
||||||
- reverse_proxy
|
- reverse_proxy
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
|
wakdo-migrate:
|
||||||
|
condition: service_completed_successfully
|
||||||
wakdo-app:
|
wakdo-app:
|
||||||
condition: service_started
|
condition: service_started
|
||||||
wakdo-db:
|
wakdo-db:
|
||||||
|
|
|
||||||
|
|
@ -113,13 +113,13 @@ Client Borne (Bloc 1) API (Bloc 2) BDD
|
||||||
|
|
||||||
**Un seul codebase, deux FQDN d'exposition publique.** Le front Bloc 1 et le back Bloc 2 coexistent dans la meme arborescence. Une bascule mode JSON-seuls (Bloc 1 isole) vs mode API-connecte doit rester possible via configuration.
|
**Un seul codebase, deux FQDN d'exposition publique.** Le front Bloc 1 et le back Bloc 2 coexistent dans la meme arborescence. Une bascule mode JSON-seuls (Bloc 1 isole) vs mode API-connecte doit rester possible via configuration.
|
||||||
|
|
||||||
**Pourquoi pas strategie A (deux rendus isoles)** : le Bloc 5 DevOps impose une conteneurisation **unique** qui lance la stack complete avec `make init` en une commande (Cr 7.c.4). Deux codebases isolees seraient incoherentes avec cette exigence.
|
**Pourquoi pas strategie A (deux rendus isoles)** : le Bloc 5 DevOps impose une conteneurisation **unique** qui lance la stack complete avec `docker compose up` en une commande (Cr 7.c.4). Deux codebases isolees seraient incoherentes avec cette exigence.
|
||||||
|
|
||||||
### Compatibilite evaluation par bloc
|
### Compatibilite evaluation par bloc
|
||||||
|
|
||||||
- **Jury Bloc 1** : voit le front seul ; le front peut tomber en fallback sur JSON statiques fournis (`src/public/borne/data/*.json`) si l'API est indisponible.
|
- **Jury Bloc 1** : voit le front seul ; le front peut tomber en fallback sur JSON statiques fournis (`src/public/borne/data/*.json`) si l'API est indisponible.
|
||||||
- **Jury Bloc 2** : voit le back-office + teste l'API via curl/Postman de maniere autonome, sans dependre du front.
|
- **Jury Bloc 2** : voit le back-office + teste l'API via curl/Postman de maniere autonome, sans dependre du front.
|
||||||
- **Jury Bloc 5** : lance `make init` ou `docker compose up`, verifie la CI/CD, les crons, l'archi, les scripts.
|
- **Jury Bloc 5** : lance `docker compose up` ou `docker compose up`, verifie la CI/CD, les crons, l'archi, les scripts.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ Reseaux :
|
||||||
| Reverse proxy | Traefik (deja en place) | existant | `admin_proxy` network |
|
| Reverse proxy | Traefik (deja en place) | existant | `admin_proxy` network |
|
||||||
| TLS | Let's Encrypt via Traefik | auto | `acme.json` existant |
|
| TLS | Let's Encrypt via Traefik | auto | `acme.json` existant |
|
||||||
| Conteneurisation | Docker + docker compose | v2 | Cr 7.c |
|
| Conteneurisation | Docker + docker compose | v2 | Cr 7.c |
|
||||||
| Orchestration locale | Makefile | — | Cr 7.b (script) + Cr 7.c.4 (une commande) |
|
| Orchestration locale | docker compose (service wakdo-migrate) | — | Cr 7.b (script) + Cr 7.c.4 (une commande) |
|
||||||
| CI/CD | Forgejo Actions (act_runner auto-heberge) | — | Cr 7.d |
|
| CI/CD | Forgejo Actions (act_runner auto-heberge) | — | Cr 7.d |
|
||||||
| Versioning | Git + Forgejo auto-heberge (push-mirror GitHub) | — | Cr 4.f (collaboration) |
|
| Versioning | Git + Forgejo auto-heberge (push-mirror GitHub) | — | Cr 4.f (collaboration) |
|
||||||
| Hooks Git | pre-commit + commit-msg | versionnes dans `.githooks/` | Conventional Commits |
|
| Hooks Git | pre-commit + commit-msg | versionnes dans `.githooks/` | Conventional Commits |
|
||||||
|
|
@ -263,14 +263,14 @@ Reseaux :
|
||||||
**IN scope :**
|
**IN scope :**
|
||||||
- Dockerfile custom PHP-FPM avec extensions
|
- Dockerfile custom PHP-FPM avec extensions
|
||||||
- `docker-compose.yml` orchestrant les 4 services (web, app, db, cron)
|
- `docker-compose.yml` orchestrant les 4 services (web, app, db, cron)
|
||||||
- `Makefile` avec cible `make init` qui lance tout en une commande (Cr 7.c.4)
|
- `docker compose up` lance toute la stack (service one-shot `wakdo-migrate` : migrations + seed idempotents) en une commande (Cr 7.c.4)
|
||||||
- Scripts Bash d'automatisation (backup, deploy, migrate)
|
- Scripts Bash d'automatisation (backup, deploy, migrate)
|
||||||
- **Cron tab** avec au moins 3 jobs planifies dans la fenetre de maintenance (01h30-09h30) :
|
- **Cron tab** avec au moins 3 jobs planifies dans la fenetre de maintenance (01h30-09h30) :
|
||||||
- `0 3 * * *` — backup BDD quotidien a 03h00 (entre fin service 01h et ouverture 10h)
|
- `0 3 * * *` — backup BDD quotidien a 03h00 (entre fin service 01h et ouverture 10h)
|
||||||
- `*/15 * * * *` — purge sessions expirees toutes les 15 min (leger, peut tourner en service)
|
- `*/15 * * * *` — purge sessions expirees toutes les 15 min (leger, peut tourner en service)
|
||||||
- `30 4 * * *` — agregation stats commandes a 04h30 sur le **jour de service** ecoule (10h J-1 → 01h J)
|
- `30 4 * * *` — agregation stats commandes a 04h30 sur le **jour de service** ecoule (10h J-1 → 01h J)
|
||||||
- **CI Forgejo Actions** (act_runner auto-heberge) : lint PHP + PHPStan + PHPUnit + secret-scan (gitleaks) sur PR -> dev
|
- **CI Forgejo Actions** (act_runner auto-heberge) : lint PHP + PHPStan + PHPUnit + secret-scan (gitleaks) sur PR -> dev
|
||||||
- **CD Forgejo Actions** : deploy auto sur merge main (SSH + pull + `make rebuild`)
|
- **CD Forgejo Actions** : deploy auto sur merge main (SSH + `docker compose pull && docker compose up -d`)
|
||||||
- `.env.example` documente (parametres securite : argon2id, lockout, seuils throttle, retention RGPD), secrets hors du repo
|
- `.env.example` documente (parametres securite : argon2id, lockout, seuils throttle, retention RGPD), secrets hors du repo
|
||||||
- `php.ini` durci (expose_php off, session cookies httponly/secure/samesite, upload limite)
|
- `php.ini` durci (expose_php off, session cookies httponly/secure/samesite, upload limite)
|
||||||
- Healthcheck Traefik + readiness probes
|
- Healthcheck Traefik + readiness probes
|
||||||
|
|
@ -328,13 +328,13 @@ Reseaux :
|
||||||
| Critere | Libelle court | Feature Wakdo couvrant |
|
| Critere | Libelle court | Feature Wakdo couvrant |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Cr 7.a.1-3 | Analyse infra + securite | Audit code + proposition automatisation documentee |
|
| Cr 7.a.1-3 | Analyse infra + securite | Audit code + proposition automatisation documentee |
|
||||||
| Cr 7.b.1 | Langage de script | Bash (deploy, backup) + Makefile |
|
| Cr 7.b.1 | Langage de script | Bash (db/*.sh migrate/seed, scripts/forgejo-*.sh, entrypoints, backup) |
|
||||||
| Cr 7.b.2 | Automatisation fiabilisee | Makefile avec exit codes, retries, logs |
|
| Cr 7.b.2 | Automatisation fiabilisee | Scripts Bash (set -euo pipefail, exit codes, logs) + service compose wakdo-migrate idempotent |
|
||||||
| Cr 7.b.3 | **Cron tab** | `wakdo-cron` service avec crontab : backup BDD, purge sessions, stats |
|
| Cr 7.b.3 | **Cron tab** | `wakdo-cron` service avec crontab : backup BDD, purge sessions, stats |
|
||||||
| Cr 7.c.1 | VM operationnelle | Serveur existant Acadenice |
|
| Cr 7.c.1 | VM operationnelle | Serveur existant Acadenice |
|
||||||
| Cr 7.c.2 | OS conteneur installe | Docker Engine |
|
| Cr 7.c.2 | OS conteneur installe | Docker Engine |
|
||||||
| Cr 7.c.3 | App conteneurisee complete | 4 services (web, app, db, cron) |
|
| Cr 7.c.3 | App conteneurisee complete | 4 services (web, app, db, cron) |
|
||||||
| Cr 7.c.4 | **Une ligne de commande** | `make init` lance toute la stack + migrate + seed |
|
| Cr 7.c.4 | **Une ligne de commande** | `docker compose up` lance toute la stack + migrate + seed |
|
||||||
| Cr 7.d.1 | Architecture serveur | Traefik reverse + reseaux segmentes documentes |
|
| Cr 7.d.1 | Architecture serveur | Traefik reverse + reseaux segmentes documentes |
|
||||||
| Cr 7.d.2 | Tests avant deploy | CI PHPUnit + PHPStan + secret-scan sur PR (Forgejo Actions) |
|
| Cr 7.d.2 | Tests avant deploy | CI PHPUnit + PHPStan + secret-scan sur PR (Forgejo Actions) |
|
||||||
| Cr 7.d.3 | Integration/deploiement continus | Forgejo Actions deploy automatique sur merge main |
|
| Cr 7.d.3 | Integration/deploiement continus | Forgejo Actions deploy automatique sur merge main |
|
||||||
|
|
@ -439,7 +439,7 @@ Les branches `main` et `dev` sont **protegees** cote Forgejo (push direct interd
|
||||||
| 8 | 2 FQDN | Separation claire borne publique / admin+API interne, defensible jury |
|
| 8 | 2 FQDN | Separation claire borne publique / admin+API interne, defensible jury |
|
||||||
| 9 | API sous `/api` sur le FQDN admin | Simplicite d'exploitation, CORS explicite gere |
|
| 9 | API sous `/api` sur le FQDN admin | Simplicite d'exploitation, CORS explicite gere |
|
||||||
| 10 | Service cron dedie | Cr 7.b.3 explicite + realiste prod |
|
| 10 | Service cron dedie | Cr 7.b.3 explicite + realiste prod |
|
||||||
| 11 | Makefile avec `make init` | Cr 7.c.4 + demonstration DevOps |
|
| 11 | Orchestration `docker compose up` (service wakdo-migrate) | Cr 7.c.4 + demonstration DevOps |
|
||||||
| 12 | Conventional Commits + hooks | Cr 4.f.x + discipline de versioning |
|
| 12 | Conventional Commits + hooks | Cr 4.f.x + discipline de versioning |
|
||||||
| 13 | Branches feat/* -> dev -> main | Pipeline propre pour jury, PR tracee (Forgejo, mirror GitHub) |
|
| 13 | Branches feat/* -> dev -> main | Pipeline propre pour jury, PR tracee (Forgejo, mirror GitHub) |
|
||||||
| 14 | CI/CD Forgejo Actions (act_runner auto-heberge) | Cr 7.d explicite ; forge + CI maitrisees de bout en bout (argument Bloc 5) |
|
| 14 | CI/CD Forgejo Actions (act_runner auto-heberge) | Cr 7.d explicite ; forge + CI maitrisees de bout en bout (argument Bloc 5) |
|
||||||
|
|
@ -490,7 +490,7 @@ Buffer : ~8 h pour imprevus. Cible effective : ~264 h sur 20 semaines = **~13 h/
|
||||||
**Bloc 5 :**
|
**Bloc 5 :**
|
||||||
- `docker-compose.yml` commente
|
- `docker-compose.yml` commente
|
||||||
- Dockerfiles customs commentes
|
- Dockerfiles customs commentes
|
||||||
- `Makefile` avec `make help`
|
- Orchestration via `docker compose` (service one-shot `wakdo-migrate` : migrate + seed)
|
||||||
- `.forgejo/workflows/` avec CI (PHPUnit + PHPStan + secret-scan) + CD
|
- `.forgejo/workflows/` avec CI (PHPUnit + PHPStan + secret-scan) + CD
|
||||||
- Crontab documente
|
- Crontab documente
|
||||||
- Script de backup/restore teste
|
- Script de backup/restore teste
|
||||||
|
|
@ -500,7 +500,7 @@ Buffer : ~8 h pour imprevus. Cible effective : ~264 h sur 20 semaines = **~13 h/
|
||||||
|
|
||||||
- **README.md** synthetique (quick start + liens docs)
|
- **README.md** synthetique (quick start + liens docs)
|
||||||
- **Presentation** (slides ou live) argumentant les choix
|
- **Presentation** (slides ou live) argumentant les choix
|
||||||
- **Demo** live : borne + back-office + API (Postman/curl) + `make init`
|
- **Demo** live : borne + back-office + API (Postman/curl) + `docker compose up`
|
||||||
- **Capacite modification en direct** (Cr 4.a.1) : code structure pour permettre modifs sans casser
|
- **Capacite modification en direct** (Cr 4.a.1) : code structure pour permettre modifs sans casser
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -511,7 +511,7 @@ Buffer : ~8 h pour imprevus. Cible effective : ~264 h sur 20 semaines = **~13 h/
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Sous-estimation temps front (accessibilite RGAA stricte) | Haute | Moyen | 60 h budgetees + tests W3C/axe-core pendant le dev, pas a la fin |
|
| Sous-estimation temps front (accessibilite RGAA stricte) | Haute | Moyen | 60 h budgetees + tests W3C/axe-core pendant le dev, pas a la fin |
|
||||||
| Complexite MCT (statuts commande) mal modelisee | Moyenne | Fort | Valider MCT avec un pair ou prof avant d'implementer Bloc 2 |
|
| Complexite MCT (statuts commande) mal modelisee | Moyenne | Fort | Valider MCT avec un pair ou prof avant d'implementer Bloc 2 |
|
||||||
| Dockerfile PHP extensions manquantes decouvert tard | Moyenne | Faible | Tester `make up` + un vrai appel BDD des P0 |
|
| Dockerfile PHP extensions manquantes decouvert tard | Moyenne | Faible | Tester `docker compose up -d` + un vrai appel BDD des P0 |
|
||||||
| Conflit reseau Docker `wakdo_internal` existant | Faible | Faible | Verifie au setup, fallback nom `wakdo_backend` |
|
| Conflit reseau Docker `wakdo_internal` existant | Faible | Faible | Verifie au setup, fallback nom `wakdo_backend` |
|
||||||
| CORS mal configure bloque la borne | Moyenne | Moyen | Test immediat apres setup 2 FQDN |
|
| CORS mal configure bloque la borne | Moyenne | Moyen | Test immediat apres setup 2 FQDN |
|
||||||
| Performance borne sur ecran tactile reel | Faible | Fort | Optimiser images + lazy loading + tests sur device tactile si possible |
|
| Performance borne sur ecran tactile reel | Faible | Fort | Optimiser images + lazy loading + tests sur device tactile si possible |
|
||||||
|
|
@ -614,7 +614,7 @@ L'auteur peut recourir ponctuellement a d'autres outils IA (completion IDE, assi
|
||||||
- **Choix du scope fonctionnel** : defini par l'auteur a partir du brief RNCP. L'IA n'ajoute ni ne retire de fonctionnalite sans instruction explicite.
|
- **Choix du scope fonctionnel** : defini par l'auteur a partir du brief RNCP. L'IA n'ajoute ni ne retire de fonctionnalite sans instruction explicite.
|
||||||
- **Modelisation Merise** (MCD, MCT, MLD) : formalisation produite par l'IA a partir du dictionnaire de donnees et des user stories ; arbitrage, validation et corrections par l'auteur. Chaque cardinalite, chaque relation et chaque transition de statut est validee par l'auteur avant integration. Le livrable final reflete ses decisions.
|
- **Modelisation Merise** (MCD, MCT, MLD) : formalisation produite par l'IA a partir du dictionnaire de donnees et des user stories ; arbitrage, validation et corrections par l'auteur. Chaque cardinalite, chaque relation et chaque transition de statut est validee par l'auteur avant integration. Le livrable final reflete ses decisions.
|
||||||
- **Validation des livrables** : reservee au jury. L'IA n'emet pas de jugement final sur la conformite RNCP.
|
- **Validation des livrables** : reservee au jury. L'IA n'emet pas de jugement final sur la conformite RNCP.
|
||||||
- **Deploiements** : declenchement humain uniquement, y compris sur `make init` local. Aucune action sur environnement serveur sans instruction explicite.
|
- **Deploiements** : declenchement humain uniquement, y compris sur `docker compose up` local. Aucune action sur environnement serveur sans instruction explicite.
|
||||||
- **Commit en son nom** : aucun trailer `Co-Authored-By: Claude...` n'est appose sur les commits. Voir section 17.7.
|
- **Commit en son nom** : aucun trailer `Co-Authored-By: Claude...` n'est appose sur les commits. Voir section 17.7.
|
||||||
- **Decisions de securite critiques** : tous les choix de type hash mdp, CORS, RBAC, politique sessions sont valides par l'auteur meme si l'IA en propose la mise en oeuvre.
|
- **Decisions de securite critiques** : tous les choix de type hash mdp, CORS, RBAC, politique sessions sont valides par l'auteur meme si l'IA en propose la mise en oeuvre.
|
||||||
|
|
||||||
|
|
|
||||||
88
docs/journal/2026-06-17--makefile-to-compose-migrate.md
Normal file
88
docs/journal/2026-06-17--makefile-to-compose-migrate.md
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
# 2026-06-17 — Du Makefile a `docker compose up` (service wakdo-migrate)
|
||||||
|
|
||||||
|
**Auteur : BYAN.** Remplacement de l'orchestration locale par Makefile par un service
|
||||||
|
compose one-shot. Objectif : que `docker compose up` amene a lui seul une stack
|
||||||
|
complete et utilisable, et retirer un Makefile devenu en partie trompeur.
|
||||||
|
|
||||||
|
## Pourquoi ce changement
|
||||||
|
|
||||||
|
### Le declencheur : le Makefile mentait en partie
|
||||||
|
Un audit du Makefile (24 cibles) a montre trois categories :
|
||||||
|
- **Cibles mortes / trompeuses** : `test`, `test-unit`, `test-integration`, `lint`
|
||||||
|
affichaient *« Pas encore implemente … en P2 »* alors que les tests EXISTENT et
|
||||||
|
tournent (PHPUnit via `.phar`, 263 tests unit + 301/916 en integration ; PHPStan
|
||||||
|
L6 ; tests JS node:test+jsdom). `install-hooks` referencait un `.githooks/` et un
|
||||||
|
`scripts/install-hooks.sh` absents. Une cible qui annonce un faux est pire qu'une
|
||||||
|
cible absente.
|
||||||
|
- **Wrappers fins** : `up/down/logs/shell/...` = une ligne au-dessus de
|
||||||
|
`docker compose`, valeur surtout de decouvrabilite (`make help`).
|
||||||
|
- **Une seule cible reellement porteuse** : `init` (build -> up -> wait-db ->
|
||||||
|
migrate), citee comme la preuve du critere RNCP **Cr 7.c.4** (*« lancer la stack
|
||||||
|
complete avec une seule ligne de commande »*).
|
||||||
|
|
||||||
|
### Le point cle : Cr 7.c.4 parle d'un RESULTAT, pas de `make`
|
||||||
|
Le critere exige *une commande -> stack complete*. Il ne mentionne pas `make` ;
|
||||||
|
`make init` n'etait qu'un choix d'implementation. Or `docker compose up` seul ne
|
||||||
|
suffisait pas : il demarre les conteneurs mais **n'applique pas les migrations**
|
||||||
|
(base vide -> stack non « complete »). C'etait l'unique raison d'etre de `make init`.
|
||||||
|
|
||||||
|
En deplacant migration + seed DANS la stack (un service one-shot qui tourne au
|
||||||
|
boot), c'est `docker compose up` LUI-MEME qui amene la stack complete. Avantages :
|
||||||
|
- **Commande universelle** : `docker compose up`, sans dependance a l'outil `make`
|
||||||
|
sur l'hote (un correcteur n'a pas a installer/connaitre `make`).
|
||||||
|
- **Comportement = documentation** : l'ancien `make init` ne faisait meme PAS le
|
||||||
|
seed (il s'arretait a `migrate`), alors que le README annoncait « migrate + seed ».
|
||||||
|
Le nouveau chemin seed pour de vrai, donc la stack est *loginnable* (admin present)
|
||||||
|
en une commande.
|
||||||
|
- **Plus idiomatique** : faire porter l'init par la couche d'orchestration (compose)
|
||||||
|
plutot que par un outil hote externe.
|
||||||
|
|
||||||
|
## Ce qui a ete fait
|
||||||
|
|
||||||
|
- **`db/migrate-container.sh`** : runner in-container. Applique `db/migrations/*.sql`
|
||||||
|
(suivi `schema_migrations`) PUIS `db/seeds/*.sql` (suivi `seeds_applied`), de
|
||||||
|
maniere idempotente, en se connectant a la base par le reseau compose (DB_HOST).
|
||||||
|
Distinct de `db/migrate.sh` (hote, via `docker exec`), conserve pour l'usage manuel
|
||||||
|
(`--status`) et la CI.
|
||||||
|
- **Service `wakdo-migrate`** (image mariadb, `restart: "no"`) : `depends_on`
|
||||||
|
`wakdo-db: service_healthy`, lance le runner puis sort. `wakdo-app` et `wakdo-web`
|
||||||
|
gagnent `depends_on wakdo-migrate: service_completed_successfully` -> ils ne servent
|
||||||
|
qu'une fois le schema + le seed en place.
|
||||||
|
- **Makefile supprime.** Les commandes equivalentes en clair :
|
||||||
|
`docker compose up -d` (= ex-`make init`/`up`), `docker compose down` (`make down`),
|
||||||
|
`docker compose down -v` (`make clean`), `docker compose build --no-cache && up -d`
|
||||||
|
(`make rebuild`), `docker compose logs -f` (`make logs`),
|
||||||
|
`docker compose exec wakdo-db mariadb -uroot -p"$DB_ROOT_PASSWORD"` (`make shell-db`).
|
||||||
|
Tests : `docker run --rm -v "$PWD":/app -w /app wakdo-wakdo-app php phpunit.phar -c phpunit.xml`
|
||||||
|
(cf. README / SESSION_RESUME).
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
Base MariaDB ephemere et vierge (pour ne pas toucher la dev) :
|
||||||
|
- Run #1 : 2 migrations + 2 seeds appliques.
|
||||||
|
- Run #2 : 0 nouveau (idempotent, tout ignore).
|
||||||
|
- Donnees : 5 roles, 23 permissions, admin `admin@wakdo.local` present ;
|
||||||
|
`schema_migrations`=2, `seeds_applied`=2.
|
||||||
|
|
||||||
|
`docker compose -p wakdo config` valide. La CI n'utilise pas `make` (0 appel) :
|
||||||
|
elle garde sa propre boucle migrate -> non impactee.
|
||||||
|
|
||||||
|
## Mapping Cr 7.c.4 (apres ce changement)
|
||||||
|
*« Le fichier de configuration permet de lancer la stack applicative complete avec
|
||||||
|
une seule ligne de commande »* -> **`docker compose up`** : `docker-compose.yml`
|
||||||
|
decrit la stack, le service `wakdo-migrate` applique schema + donnees, app/web
|
||||||
|
attendent sa completion. Une commande, aucune dependance hote.
|
||||||
|
|
||||||
|
## Note de deploiement (environnements deja seedes)
|
||||||
|
Sur une base existante deja migree ET seedee AVANT l'introduction du suivi
|
||||||
|
(`seeds_applied` absente), le premier `docker compose up` avec le nouveau service
|
||||||
|
tenterait de rejouer les seeds (INSERT non idempotents) -> conflits d'unicite. Pour
|
||||||
|
ces environnements : back-fill une fois la table de suivi
|
||||||
|
(`CREATE TABLE seeds_applied(...)` + INSERT des noms de fichiers seed deja appliques,
|
||||||
|
idem `schema_migrations` si besoin) AVANT le premier up. Les deploiements sur volume
|
||||||
|
VIERGE ne sont pas concernes (le service applique tout proprement, comme verifie).
|
||||||
|
|
||||||
|
## Compromis assumes
|
||||||
|
- migrations + seeds evalues a CHAQUE `up` : cout negligeable (le suivi rend les
|
||||||
|
re-runs sans effet).
|
||||||
|
- `wakdo-migrate` se connecte en root (DDL + INSERT de reference), comme `migrate.sh`.
|
||||||
Loading…
Add table
Reference in a new issue