Files
app/docs/release.md
2026-06-16 20:44:47 +02:00

4.4 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.

nginx is NOT part of a normal release. nginx is only a reverse proxy in front of the pm2 app (proxy_pass127.0.0.1:3001); a code release changes app code, which pm2 restart app-ts picks up — nginx has nothing new to read. Do not run sudo nginx -t && sudo systemctl reload nginx every deploy. Run it ONLY when you actually edit nginx config (/etc/nginx/…server_name, ports, proxy_pass upstream, TLS cert paths, locations/redirects/headers, client_max_body_size, rate limits, etc.). When you do change it, always nginx -t first (validates syntax, changes nothing) THEN systemctl reload nginx (graceful re-read, keeps active connections; a bad config on reload is rejected and the old one keeps running).

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>