Files
app/docs/release.md
BOHA 5c9ebddf50 docs: consolidate CLAUDE.md (merge audit sections, dedupe, fix stale facts); runbooks to docs/release.md
Applied the two-review consolidation: merged the duplicate 2026-06-06/06-09 'Conventions (enforced)' sections into one canonical block (query-invalidation rule stated once instead of three times, Zod-helper 'tracked follow-up' vs 'MANDATORY' contradiction resolved, seed-is-dev-only stated once); removed stale-by-design facts (version pins, test counts, file counts, React 18 typo) and migration-era storytelling; fixed prisma migrate diff flags (--from-url removed in Prisma 7) and documented the non-interactive migration recipe; added the new rules earned this week (@db.Date UTC-truncation, document business rules incl. VAT-only-on-invoices and PO suppliers, document-platform conventions, shared-module reuse list, dashboard invalidation, app_test migrate step). Release/hotfix/drift/baseline runbooks moved to docs/release.md with a pointer (keeps prod details out of every-turn context). Also dropped the db:push npm script - it contradicted the golden rule. CLAUDE.md: 570 -> ~390 lines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 18:07:39 +02:00

3.7 KiB

Release & deployment runbook — boha-app-ts

Referenced from CLAUDE.md. Never deploy to production or restart services without explicit user confirmation.

Standard release

  1. Run the full gates locally: npx vitest run (all green), npx tsc -b --noEmit, npm run lint (0 errors).

  2. Bump version: npm version X.Y.Z --no-git-tag-version (the user picks the number).

  3. npm run build

  4. Commit and tag: git tag -a vX.Y.Z

  5. Push to Gitea: git push origin master && git push origin vX.Y.Z

  6. Create tarball:

    tar -czf app-ts-X.Y.Z.tar.gz dist dist-client prisma prisma.config.ts package.json package-lock.json scripts
    

    ⚠️ prisma.config.ts is REQUIRED — Prisma 7 keeps the datasource URL there; without it, prisma generate/migrate deploy on prod have no datasource.

  7. Deploy via SSH to production (boha_admin@192.168.50.100, path /var/www/app-ts):

    scp app-ts-X.Y.Z.tar.gz boha_admin@192.168.50.100:/tmp/
    ssh boha_admin@192.168.50.100
    cd /var/www/app-ts
    rm -rf dist dist-client prisma prisma.config.ts scripts package.json package-lock.json
    tar -xzf /tmp/app-ts-X.Y.Z.tar.gz
    npm install --omit=dev
    npx prisma generate        # MANDATORY — see below
    npx prisma migrate deploy
    pm2 restart app-ts --update-env
    

    npx prisma generate is mandatory. npm install skips client regeneration when dependencies didn't change, leaving a stale client that still selects dropped/renamed columns → P2022 500s in prod (this caused the v2.4.0 incident: every issued-orders query failed until generate ran).

  8. Verify: pm2 list (status online, correct version, restart counter not climbing), npx prisma migrate status ("up to date"), curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3001/ → 200, and grep logs for errors from the CURRENT pid only (the out log keeps old errors from prior pids).

  9. Clean up tarballs locally and in /tmp/ on the server.

Risky releases (framework jumps, FK/constraint-altering migrations) get a read-only pre-flight first: prisma migrate status on prod, verify FK constraint names the migration DROPs, check no data violates new UNIQUE/RESTRICT constraints — and confirm with the user before the irreversible steps. The prod DB is backed up by a cron job (no manual mysqldump needed).

Hotfixing a migration added after the tarball was built

A migration folder created after the release tarball shipped is not on prod, so prisma migrate deploy reports "No pending migrations". Ship just the migration folder (still tracked in git — this is NOT raw SQL on prod):

# Local
cd prisma/migrations
tar -czf /tmp/<name>_migration.tar.gz <timestamp>_<name>/
scp /tmp/<name>_migration.tar.gz boha_admin@192.168.50.100:/tmp/

# On prod
ssh boha_admin@192.168.50.100
cd /var/www/app-ts/prisma/migrations
tar -xzf /tmp/<name>_migration.tar.gz
cd /var/www/app-ts
npx prisma migrate deploy
pm2 restart app-ts --update-env

Drift check / preview before deploy

# Preview what SQL would bring the dev DB (per prisma.config.ts) to the local schema
npx prisma migrate diff --from-config-datasource --to-schema prisma/schema.prisma --script

Empty output = no diff. (Prisma 7 removed --from-url; diffs against another DB need its URL in a config/env override.) If drift includes DROPs, investigate before touching production.

Baselining a database that has no migrations

If a database was synced without migration history (no _prisma_migrations table): create the initial migration locally, copy prisma/migrations to the server, then mark it applied without running SQL:

npx prisma migrate resolve --applied <migration_name>