db: Prisma-Migrations-System statt db push (datenerhaltend)
`db push --accept-data-loss` konnte bei Schema-Änderungen still Daten verlieren (Renames, Type-Changes, NOT NULL ohne Default). Umstellung auf versionierte Migrations: - 0_init aus aktuellem Schema generiert (alte gedriftete Migrations entfernt) - entrypoint: Auto-Baseline für bestehende DBs ohne `_prisma_migrations`, dann `migrate deploy` (idempotent, kein Daten-Loss) - npm run schema:sync: legt automatisch eine Migration mit Zeitstempel an (`prisma migrate dev --name auto_<ts>`) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
#!/bin/sh
|
||||
# Beim Container-Start: Schema in DB pushen (idempotent) + (optional) seed.
|
||||
# RUN_SEED=true beim ersten Start setzen, danach wieder auf false.
|
||||
# Container-Start:
|
||||
# 1) Auf DB warten
|
||||
# 2) Auto-Baseline für bestehende DBs (db-push-Ära ohne _prisma_migrations)
|
||||
# 3) `prisma migrate deploy` (idempotent, datenerhaltend)
|
||||
# 4) Auto-Seed bei leerer User-Tabelle (oder RUN_SEED=true)
|
||||
# Neue Schema-Änderung anlegen (lokal, im Dev): npm run schema:sync
|
||||
set -e
|
||||
|
||||
# DATABASE_URL aus DB_*-Komponenten bauen, falls nicht explizit gesetzt.
|
||||
@@ -21,10 +25,16 @@ if [ -z "$DATABASE_URL" ] && [ -n "$DB_USER" ] && [ -n "$DB_PASSWORD" ] && [ -n
|
||||
fi
|
||||
|
||||
echo "[entrypoint] Warte auf Datenbank…"
|
||||
# Prisma versucht selbst Connect; einfacher Retry-Loop um Race-Bedingungen
|
||||
# beim parallelen Container-Start abzufangen.
|
||||
# Erst auf DB-Verfügbarkeit warten via einfachem Connect-Check.
|
||||
# Wir nutzen Prisma's interne Engine, kein extra mysql-client nötig.
|
||||
TRIES=30
|
||||
until npx prisma db push --skip-generate --accept-data-loss 2>/dev/null; do
|
||||
until node -e "
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const p = new PrismaClient();
|
||||
p.\$queryRaw\`SELECT 1\`
|
||||
.then(() => p.\$disconnect().then(() => process.exit(0)))
|
||||
.catch(() => process.exit(1));
|
||||
" 2>/dev/null; do
|
||||
TRIES=$((TRIES - 1))
|
||||
if [ "$TRIES" -le 0 ]; then
|
||||
echo "[entrypoint] DB nicht erreichbar – Abbruch"
|
||||
@@ -33,7 +43,51 @@ until npx prisma db push --skip-generate --accept-data-loss 2>/dev/null; do
|
||||
echo "[entrypoint] DB noch nicht bereit – retry in 2s ($TRIES Versuche übrig)"
|
||||
sleep 2
|
||||
done
|
||||
echo "[entrypoint] DB-Schema synced"
|
||||
echo "[entrypoint] DB erreichbar"
|
||||
|
||||
# Auto-Baseline: Wenn die DB Anwendungs-Tabellen enthält (z.B. User), aber noch
|
||||
# keine _prisma_migrations-Tabelle, dann ist es eine "alte" DB, die früher mit
|
||||
# `prisma db push` synced wurde. Wir markieren 0_init als bereits angewendet,
|
||||
# damit `migrate deploy` nicht versucht, alle Tabellen nochmal anzulegen.
|
||||
NEEDS_BASELINE=$(node -e "
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const p = new PrismaClient();
|
||||
(async () => {
|
||||
try {
|
||||
const dbName = process.env.DB_NAME;
|
||||
const tables = await p.\$queryRawUnsafe(
|
||||
\`SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?\`,
|
||||
dbName
|
||||
);
|
||||
const names = tables.map(t => t.TABLE_NAME);
|
||||
const hasMigrations = names.includes('_prisma_migrations');
|
||||
const hasUserTable = names.includes('User');
|
||||
// Existing DB (User da) ohne Migrations-Tracking => Baseline nötig
|
||||
if (hasUserTable && !hasMigrations) process.stdout.write('yes');
|
||||
else process.stdout.write('no');
|
||||
} catch (e) {
|
||||
process.stdout.write('no');
|
||||
} finally {
|
||||
await p.\$disconnect();
|
||||
}
|
||||
})();
|
||||
" 2>/dev/null)
|
||||
|
||||
if [ "$NEEDS_BASELINE" = "yes" ]; then
|
||||
echo "[entrypoint] Bestehende DB ohne Migrations-Tracking erkannt – markiere 0_init als angewendet (Baseline)"
|
||||
npx prisma migrate resolve --applied 0_init || echo "[entrypoint] Baseline fehlgeschlagen – fahre trotzdem fort"
|
||||
fi
|
||||
|
||||
# Migrations anwenden (idempotent: bereits angewendete werden übersprungen).
|
||||
# Im Gegensatz zu `db push` löscht `migrate deploy` keine Daten — Schema-
|
||||
# Änderungen werden über versionierte Migrations-Files unter prisma/migrations/
|
||||
# eingespielt. Neue Migration anlegen mit: npm run schema:sync (lokal, dev).
|
||||
echo "[entrypoint] Wende Migrations an…"
|
||||
if ! npx prisma migrate deploy; then
|
||||
echo "[entrypoint] migrate deploy fehlgeschlagen – Abbruch"
|
||||
exit 1
|
||||
fi
|
||||
echo "[entrypoint] DB-Schema aktuell"
|
||||
|
||||
# Auto-Seed: wenn die User-Tabelle leer ist (= Erstinstallation), automatisch seeden.
|
||||
# RUN_SEED=true erzwingt Seed auch bei nicht-leerer DB (z.B. nach Reset).
|
||||
|
||||
Reference in New Issue
Block a user