Some checks are pending
CI / validate (push) Waiting to run
Schließt die Ops-Lücke „kein versioniertes Schema-Tracking" aus FEATURE_IDEAS.md. * apps/api/src/db/migrations/0000_baseline.sql — Drizzle-generierte Baseline-Migration, 355 Zeilen, 25 Tabellen + 5 Enums (cards- und marketplace-Schema). Eingefrostet auf den Live-Stand 2026-05-12. * apps/api/scripts/bootstrap-drizzle-tracking.ts — neues Script, markiert die Baseline in einer bestehenden DB als „bereits angewandt", ohne SQL erneut auszuführen. Verwendet sha256 wie drizzle-orm/migrator (Hash 312d67ba1aeb…), idempotent. * package.json: drizzle:migrate + drizzle:bootstrap-tracking npm-scripts. * docs/playbooks/DRIZZLE_MIGRATIONS_BOOTSTRAP.md — Hand-Over für Prod (Bootstrap einmalig, dann normaler Workflow: schema → generate → commit → migrate, kein push --force mehr). Lokal verifiziert: 17/104 Tests grün, bootstrap idempotent, drizzle-kit migrate erkennt die Baseline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
155 lines
4.8 KiB
Markdown
155 lines
4.8 KiB
Markdown
# Drizzle-Migrationen — Bootstrap und Workflow
|
|
|
|
Stand: 2026-05-12.
|
|
|
|
Cards hat bis 2026-05-12 alle Schema-Änderungen über
|
|
`drizzle-kit push --force` gefahren — Schema-Sync ohne versionierte
|
|
Migrationen. Live ist das gefährlich: kein Audit-Trail, keine
|
|
sichere Rollback-Story, schwer reviewable.
|
|
|
|
Ab Commit `<dieser>` gibt es eine **versionierte Migration-Welt** mit
|
|
einer Baseline (`0000_baseline.sql`), die das bestehende Schema
|
|
festfriert.
|
|
|
|
---
|
|
|
|
## Was lokal schon passiert ist
|
|
|
|
1. `pnpm drizzle:generate` → `apps/api/src/db/migrations/0000_baseline.sql`
|
|
(25 Tabellen, 5 Enums, alle FKs/Indizes — das gesamte cards- und
|
|
marketplace-Schema, eingefroren auf den Stand 2026-05-12).
|
|
2. `apps/api/scripts/bootstrap-drizzle-tracking.ts` (neues npm-script
|
|
`pnpm drizzle:bootstrap-tracking`) — markiert in einer existierenden
|
|
Live-DB die Baseline als „bereits angewandt", ohne SQL erneut
|
|
auszuführen.
|
|
3. Lokal verifiziert: Bootstrap ist idempotent, `pnpm drizzle:migrate`
|
|
erkennt die Migration danach als bekannt.
|
|
|
|
---
|
|
|
|
## Was du auf der Prod-Box machen musst (einmalig)
|
|
|
|
```bash
|
|
ssh mana-server
|
|
cd ~/projects/cards
|
|
git pull --ff-only origin main
|
|
```
|
|
|
|
### 1. Bootstrap auf der Live-DB ausführen
|
|
|
|
```bash
|
|
# DATABASE_URL aus der env-Datei lesen, nicht hart codieren.
|
|
DB_PW=$(grep CARDS_DB_PASSWORD infrastructure/.env.production | cut -d= -f2-)
|
|
docker exec -e DATABASE_URL="postgresql://cards:${DB_PW}@cards-postgres:5432/cards" \
|
|
cards-api node /app/apps/api/scripts/bootstrap-drizzle-tracking.ts
|
|
```
|
|
|
|
…**oder** wenn das im Container-Image-Setup nicht klappt (Script ist
|
|
TypeScript, der API-Container kommt mit Bun):
|
|
|
|
```bash
|
|
# Alternative: vom Host aus über Container-Network ausführen.
|
|
# Mac Mini hat Bun installiert.
|
|
cd ~/projects/cards/apps/api
|
|
DATABASE_URL="postgresql://cards:${DB_PW}@127.0.0.1:5436/cards" \
|
|
bun run scripts/bootstrap-drizzle-tracking.ts
|
|
```
|
|
|
|
**Erwartete Ausgabe:**
|
|
|
|
```
|
|
MARKED 0000_baseline (hash 312d67ba1aeb…)
|
|
|
|
Tracking-Tabelle hat jetzt 1 Eintrag/Einträge.
|
|
```
|
|
|
|
Wenn statt `MARKED` schon `SKIP` kommt: jemand hat das Script bereits
|
|
gelaufen lassen. Idempotent → kein Problem.
|
|
|
|
### 2. Verifizieren
|
|
|
|
```bash
|
|
docker exec cards-postgres psql -U cards -d cards -c \
|
|
"SELECT * FROM drizzle.__drizzle_migrations;"
|
|
```
|
|
|
|
Erwartete Antwort: eine Zeile mit Hash `312d67ba1aeb…` und
|
|
`created_at = 1778604624860`.
|
|
|
|
### 3. Smoke-Test
|
|
|
|
```bash
|
|
cd ~/projects/cards/apps/api
|
|
DATABASE_URL="postgresql://cards:${DB_PW}@127.0.0.1:5436/cards" \
|
|
bun x drizzle-kit migrate
|
|
```
|
|
|
|
Erwartet: `[✓] migrations applied successfully!` ohne dass das
|
|
Schema wirklich angefasst wird (es kommt nur ein NOTICE
|
|
„relation '__drizzle_migrations' already exists, skipping").
|
|
|
|
---
|
|
|
|
## Künftiger Workflow
|
|
|
|
### Neue Schema-Änderung
|
|
|
|
1. **Editiere das Schema** in `apps/api/src/db/schema/**.ts`.
|
|
2. **Generiere die Migration** lokal:
|
|
```bash
|
|
cd apps/api
|
|
pnpm drizzle:generate --name <kurz_beschreibend>
|
|
```
|
|
3. **Inspiziere** das generierte SQL in `src/db/migrations/0001_<name>.sql`
|
|
(oder höher) — bei destruktiven Änderungen (DROP COLUMN, ALTER
|
|
TYPE) ggf. von Hand patchen, damit Daten nicht verloren gehen.
|
|
4. **Commit** Schema-Files + Migration-Files + Journal zusammen:
|
|
```bash
|
|
git add apps/api/src/db/schema apps/api/src/db/migrations
|
|
git commit -m "db(cards): <was>"
|
|
```
|
|
5. **Test lokal**:
|
|
```bash
|
|
DATABASE_URL="postgresql://cards:cards@localhost:5435/cards" \
|
|
pnpm drizzle:migrate
|
|
```
|
|
|
|
### Deploy
|
|
|
|
1. `git push` auf Forgejo.
|
|
2. Auf der Box: `git pull --ff-only`.
|
|
3. **Migration anwenden** (kein push --force mehr!):
|
|
```bash
|
|
cd ~/projects/cards/apps/api
|
|
DATABASE_URL="postgresql://cards:${DB_PW}@127.0.0.1:5436/cards" \
|
|
bun x drizzle-kit migrate
|
|
```
|
|
4. Erst danach Container rebuilden + restarten, wenn der neue Code
|
|
auf das neue Schema angewiesen ist.
|
|
|
|
---
|
|
|
|
## Tabu
|
|
|
|
- **`drizzle-kit push --force` auf Prod nie wieder.** Das Script
|
|
bleibt in `package.json` als Dev-Convenience, aber für Prod ist
|
|
nur `drizzle-kit migrate` der Weg.
|
|
- **Migration-Files nicht nachträglich umschreiben**, sobald sie
|
|
in einem Prod-Pull-Stand sind — der Hash würde sich ändern und
|
|
Drizzle würde sie erneut anwenden wollen.
|
|
- **Wenn du das Schema lokal mit `push` schon „weiter" als die
|
|
Migration hast**, ist das ein Drift-Bug. Lösung: lokal die DB
|
|
rückbauen (`drop schema cards cascade; drop schema marketplace cascade`),
|
|
dann Migrationen frisch anwenden. Niemals diesen Drift in einen
|
|
Commit hineinwachsen lassen.
|
|
|
|
---
|
|
|
|
## Bei Problemen
|
|
|
|
- `pnpm drizzle:migrate` schmeißt „relation already exists" und
|
|
bricht ab? Bootstrap-Script ist nie gelaufen — Schritt 1 oben.
|
|
- Hash-Mismatch (Migration angeblich „neu" trotz Bootstrap)? Das
|
|
Migration-File wurde nach dem Bootstrap noch ediert. Entweder
|
|
Edit rückgängig oder den Tracking-Eintrag von Hand auf den neuen
|
|
Hash bringen — ausschließlich nach Code-Review.
|