From 0c10f9a6d34bb74b761f52c7565df0ce301a6063 Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Fri, 5 Jun 2026 17:42:58 -0400 Subject: [PATCH] docs(03): track follow-up to adopt drizzle generate+migrate workflow --- .../adopt-drizzle-migrations-workflow.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .planning/todos/pending/adopt-drizzle-migrations-workflow.md diff --git a/.planning/todos/pending/adopt-drizzle-migrations-workflow.md b/.planning/todos/pending/adopt-drizzle-migrations-workflow.md new file mode 100644 index 0000000..46b5192 --- /dev/null +++ b/.planning/todos/pending/adopt-drizzle-migrations-workflow.md @@ -0,0 +1,43 @@ +--- +title: Adopt drizzle generate+migrate workflow (retire db:push on MariaDB) +date: 2026-06-05 +priority: high +--- + +# Adopt drizzle generate+migrate workflow (retire db:push on MariaDB) + +`drizzle-kit push` produces a FALSE destructive diff against the populated MariaDB and +must not be used for incremental schema changes. Root cause: drizzle-kit 0.31.10 (latest) +has no `mariadb` dialect; `drizzle.config.ts` uses `dialect: 'mysql'` against MariaDB 11.8 +(collation `utf8mb4_uca1400_ai_ci`). Live-DB introspection through the mysql lens misreads +MariaDB metadata (timestamp defaults as `current_timestamp()`, undetected PKs), so push +schedules `MODIFY COLUMN` no-ops, bogus `ADD PRIMARY KEY`, and `truncate`/recreate. + +Observed during Phase 3 / plan 03-01 Task 5: a plain "add calendar_outbox + object_url" +push emitted `truncate table calendars/calendar_events/users` (would have wiped 503 events). +Worked around by hand-applying the additive DDL directly. push only ever worked because the +first run was against an empty DB. + +## Goal + +Move schema changes onto `drizzle-kit generate` → `drizzle-kit migrate`. `generate` diffs +schema.ts against drizzle's JSON snapshots (`apps/api/src/db/migrations`), never the live DB, +so the introspection bug can't fire. Generated `CREATE TABLE`/`ADD COLUMN`/`CREATE INDEX` SQL +is MariaDB-compatible. + +## Tasks + +- [ ] Confirm live DB matches schema.ts exactly (it does as of 2026-06-05: calendar_outbox + + object_url were hand-applied; all 5 tables present). +- [ ] Run `pnpm --filter @familysync/api run db:generate` once to produce the baseline + migration + `meta/_journal.json` + `0000_*.sql` snapshot. +- [ ] Seed the `__drizzle_migrations` table so the baseline is marked applied (the live DB + already matches it — `migrate` must NOT re-run the CREATE statements). +- [ ] Repoint workflow off push: change/remove the `db:push` script in `apps/api/package.json`; + make `db:generate` + `db:migrate` the canonical path. +- [ ] Update CLAUDE.md (drizzle/migration guidance) and the GSD plan/SUMMARY conventions that + currently assume `db:push`. +- [ ] Verify end-to-end with a throwaway additive column change: generate → migrate → confirm + only the delta runs, no truncate. + +See memory: drizzle-mariadb-push-unsafe.