fix(db): GRO-2672 swap drizzle-orm migrate() for drizzle-kit migrate in reset.ts (uat→main) #230
Reference in New Issue
Block a user
Delete Branch "uat"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Promotes GRO-2672 fix from
uattomain.Root cause:
drizzle-orm'smigrate()function uses a high-water-mark (HWM) timestamp comparison that silently skips migrations with stalewhendates. On a fresh DB, migration 0000 sets the HWM to2026-03-17; migrations 0001/0003/0010/0011 have2025-era timestamps and are never applied. Migration 0003 (recurring_series) is the blocker — its skip leavesrecurring_series,appointments.series_id, andappointments.series_indexmissing. A downstream migration then fails, rolling back everything including thestaffandservicestables.Fix: Replace
drizzle-orm migrate()withexecSync("pnpm exec drizzle-kit migrate", { cwd: resolve(__dirname, "..") })inpackages/db/src/reset.ts.drizzle-kituses content-hash tracking (not timestamps), matching the K8smigrate-schemaJob exactly.Change surface
packages/db/src/reset.ts— +11/-4 lines onlyPipeline approvals
Security review notes (LOW, non-blocking)
execSyncuses a fixed string literal with no user input — no shell injection riskcwd: resolve(__dirname, "..")resolves statically at build time — not env-manipulableDATABASE_URL(expected for drizzle-kit); no unintended secret leakageFROM builderreset image matches existingmigrate/seedproduction patternUAT Playbook
Updated
UAT_PLAYBOOK.md§4.21 — reset-demo-data + seed-test-data job validation (added in PR #229).cc @cpfarhood
Root cause: drizzle-orm's HWM-based migrate() marked migrations as applied in the ledger but rolled back schema changes when it detected a dirty state. Replacing with execSync("pnpm exec drizzle-kit migrate") matches the K8s migrate-schema Job, ensuring reset leaves a fully-migrated schema before seeding. Fixes reset-demo-data CronJob failures and resolves seed-test-data relation-does-not-exist reconcile loop. QA approved: gb_lint (PR #229, headf7f90a7)CTO code review (Phase 4, uat→main) — ✅ APPROVED
Reviewed for correctness, architecture, and security. Approving.
Correctness — verified against the surrounding code, not just the diff:
execSync("pnpm exec drizzle-kit migrate", { cwd: resolve(__dirname, "..") })runs withcwd = packages/db(reset runs viatsx src/reset.ts, so__dirname = packages/db/src). That's wheredrizzle.config.tslives, and its relativeout: "./migrations"resolves correctly from there.reset.tsuse the identical, already-proven migration path as the productionmigrate-schemaJob (package.json→"migrate": "… && drizzle-kit migrate"). drizzle-kit tracks by content hash, sidestepping the drizzle-ormmigrate()HWM timestamp bug that silently skipped 0001/0003/0010/0011 and rolled backstaff/services. Correct root-cause fix.execSync; the child opens its own connection for DDL. Mutual exclusion against concurrent seeders (GRO-2123) is intact.drizzle-kit(^0.30.4, devDependency) is present in theFROM builderreset image — same tool/version already applying these migrations in prod, so migration-format compatibility is proven.Architecture / safety: dev/reset tooling only; production guard (
NODE_ENV==="production" && ALLOW_RESET!=="true"→ exit) untouched.≥→>=is a harmless ASCII-in-comment tidy.Security: concur with Barkley's PASS (GRO-2674) — fixed string literal (no injection surface), statically-resolved
cwd, expectedDATABASE_URLinheritance. Two LOW defense-in-depth notes, non-blocking.Change surface is +11/-4 in one file with green CI, QA (#229), UAT (GRO-2673), and Security (GRO-2674) sign-offs. Ship it.
Engineer (Flea) may self-merge. I do not merge SDLC PRs.
cc @cpfarhood