corentin_wakdo/db/seed.sh
Imugiii db83df251e
All checks were successful
CI / secret-scan (push) Successful in 20s
CI / php-lint (push) Successful in 31s
CI / static-tests (push) Successful in 1m15s
CI / js-tests (push) Successful in 46s
CI / secret-scan (pull_request) Successful in 25s
CI / php-lint (pull_request) Successful in 37s
CI / static-tests (pull_request) Successful in 1m19s
CI / js-tests (pull_request) Successful in 47s
fix(db): unifie le suivi des seeds (seeds_applied) + idempotence DDL 4 migrations + doc trou 0004
2026-06-25 08:49:53 +00:00

79 lines
3.1 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Wakdo - seed runner (hote, via `docker exec`).
#
# Applique les fichiers db/seeds/*.sql dans l'ordre lexicographique, de maniere
# idempotente : la table seeds_applied enregistre les fichiers deja charges.
# Les seeds doivent etre joues APRES les migrations (les tables doivent exister).
#
# Contrepartie hote de db/migrate.sh : meme role que la phase seed du service de
# boot wakdo-migrate (db/migrate-container.sh), mais lance manuellement depuis
# l'hote. Le suivi DOIT utiliser la MEME table que le runner conteneur
# (seeds_applied) pour que les deux interoperent : rejouer l'un apres l'autre ne
# replaye RIEN. Auparavant ce script suivait une table distincte (seed_history),
# ce qui lui faisait re-jouer des seeds deja charges par wakdo-migrate (INSERT
# bruts -> echec sur contrainte UNIQUE).
#
# Cible : le service docker-compose `wakdo-db`. Identifiants lus dans .env.
#
# Usage :
# bash db/seed.sh # charge les seeds en attente
# bash db/seed.sh --status # liste l'etat sans rien charger
#
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
ENV_FILE="$ROOT/.env"
CONTAINER="${WAKDO_DB_CONTAINER:-wakdo-db}"
SEEDS_DIR="$ROOT/db/seeds"
[ -f "$ENV_FILE" ] || { echo "ERREUR : .env introuvable ($ENV_FILE)" >&2; exit 1; }
DB_NAME="$(grep -E '^DB_NAME=' "$ENV_FILE" | cut -d= -f2- | tr -d '[:space:]')"
DB_ROOT_PASSWORD="$(grep -E '^DB_ROOT_PASSWORD=' "$ENV_FILE" | cut -d= -f2-)"
: "${DB_NAME:?DB_NAME absent de .env}"
: "${DB_ROOT_PASSWORD:?DB_ROOT_PASSWORD absent de .env}"
db() { docker exec -i "$CONTAINER" mariadb -uroot -p"$DB_ROOT_PASSWORD" "$@"; }
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
echo "[seed] aucun repertoire db/seeds/ - rien a charger"
exit 0
fi
# Meme schema de suivi que db/migrate-container.sh (seeds_applied) : nom de table
# et colonnes identiques, pour que les deux runners partagent le meme journal.
db "$DB_NAME" -e "CREATE TABLE IF NOT EXISTS seeds_applied (
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
files=("$SEEDS_DIR"/*.sql)
[ ${#files[@]} -gt 0 ] || { echo "[seed] aucun fichier seed dans $SEEDS_DIR"; exit 0; }
if [ "${1:-}" = "--status" ]; then
echo "[seed] etat des seeds (base $DB_NAME) :"
for f in "${files[@]}"; do
base="$(basename "$f")"
n="$(db "$DB_NAME" -N -s -e "SELECT COUNT(*) FROM seeds_applied WHERE filename='$base';")"
[ "$n" = "0" ] && echo " PENDING $base" || echo " loaded $base"
done
exit 0
fi
loaded=0
for f in "${files[@]}"; do
base="$(basename "$f")"
n="$(db "$DB_NAME" -N -s -e "SELECT COUNT(*) FROM seeds_applied WHERE filename='$base';")"
if [ "$n" = "0" ]; then
echo "[seed] chargement de $base ..."
db "$DB_NAME" < "$f"
db "$DB_NAME" -e "INSERT INTO seeds_applied (filename) VALUES ('$base');"
loaded=$((loaded + 1))
else
echo "[seed] $base deja charge, ignore"
fi
done
echo "[seed] termine ($loaded nouveau(x) seed(s) charge(s))."