db(cards): baseline migration + drizzle-tracking bootstrap script
Some checks are pending
CI / validate (push) Waiting to run
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>
This commit is contained in:
parent
5a29dd9a8c
commit
4bb1390180
7 changed files with 3523 additions and 5 deletions
|
|
@ -363,10 +363,16 @@ Bisher gar nicht in dieser Liste behandelt, aber Cards ist live:
|
|||
E2E-Smoke"; ein `playwright.config.ts` existiert im Repo nicht.
|
||||
Bei Live-App mit Marketplace-Forks die schmerzhafteste
|
||||
Regressions-Quelle.
|
||||
- **Drizzle-Migrationen versionieren** — `drizzle.config.ts` zeigt
|
||||
auf `out: './src/db/migrations'`, der Ordner existiert aber nicht
|
||||
(nur `db:push`). Mit Prod-Daten ein Risiko; Wechsel auf
|
||||
`drizzle-kit generate` + versionierte Migrationen.
|
||||
- **Drizzle-Migrationen versionieren — Repo-Setup gebaut 2026-05-12,
|
||||
Prod-Bootstrap offen.** `0000_baseline.sql` (355 Zeilen, 25 Tabellen
|
||||
+ 5 Enums) festgefrostet. `apps/api/scripts/bootstrap-drizzle-tracking.ts`
|
||||
+ `pnpm drizzle:bootstrap-tracking` markiert die Baseline auf der
|
||||
Live-DB als „bereits angewandt", ohne SQL re-auszuführen. Lokal
|
||||
verifiziert: idempotent + `drizzle:migrate` erkennt die Migration
|
||||
danach als bekannt. Playbook in
|
||||
`docs/playbooks/DRIZZLE_MIGRATIONS_BOOTSTRAP.md`. Nächster Schritt
|
||||
beim User: einmalig auf der Prod-Box ausführen, danach ist `push
|
||||
--force` Tabu.
|
||||
- **Storybook / Histoire für `lib/components/`** — 20+ Svelte-
|
||||
Komponenten ohne isolierte Vorschau; Lost-Pixel-Theming-Strategie
|
||||
würde davon doppelt profitieren.
|
||||
|
|
|
|||
155
docs/playbooks/DRIZZLE_MIGRATIONS_BOOTSTRAP.md
Normal file
155
docs/playbooks/DRIZZLE_MIGRATIONS_BOOTSTRAP.md
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue