10 KiB
Deploy dev → prod (release runbook)
Step-by-step guide for promoting the development version of Gallery to production. Covers code, database schema, database data, and image files.
Default is dev. This runbook is for a scheduled release (~weekly, or when you explicitly decide to ship). Day-to-day work stays on dev — see environments.md. If the one-time prod install is not done yet, follow environments.md → One-time setup and infra/docker/DEPLOY-truenas.md first.
| Dev (source) | Prod (target) | |
|---|---|---|
| Database | gallery_dev |
gallery_prod |
| Images | repo data/images/ |
/mnt/BasePool/Applications/Gallery/data/images (SMB share Gallery) |
| App | npm run dev:web on dev PC :5173 |
gallery-web container on TrueNAS :5173 |
| URL | https://devgallery.mysuperlab.netcraze.pro | https://gallery.mysuperlab.netcraze.pro |
| Env file | root .env (gallery_dev) |
infra/docker/.env.prod (gallery_prod) |
All commands run on the dev PC from the repo root (C:\Users\SNAP\Nextcloud\Personal\Repo\Gallery) unless a step says TrueNAS.
What changed → which steps to run
Run only the steps that match what you changed. Steps are independent except that code needs a rebuilt image and schema changes must be applied before a data restore.
| You changed… | Required steps |
|---|---|
| Application code (client/server) | 0 → 1 → 6 → 7 → 8 |
DB schema (new db/migrate-*.sql, schema.sql) |
0 → 1 → 2 → 3 → (4 if data too) → 7 → 8 |
| Catalog data (movements, artists, paintings, influences, bios) | 0 → 2 → 4 → 8 |
| Image files (new/replaced paintings, portraits, thumbs) | 0 → 5 → 8 |
| Everything (typical weekly release) | 0 → 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 |
Prerequisites (per release)
-
Prod already installed once on TrueNAS (
gallery-webapp exists). -
Docker Desktop running on the dev PC; logged in:
docker login gitea.mysuperlab.netcraze.pro. -
Prod env file present:
infra/docker/.env.prodwithDB_NAME=gallery_prod(copy from.env.prod.exampleif missing). -
SMB share mapped for image sync (per Windows session):
net use \\192.168.10.122\Gallery /user:YOUR_TRUENAS_USER
Step 0 — Validate on dev
Where: Dev PC + browser
-
Make sure the change works on https://devgallery.mysuperlab.netcraze.pro (or
http://localhost:5173). -
Build the client to catch type/compile errors before shipping:
npm run prod:build -
Sanity-check the dev API:
curl.exe -sk https://devgallery.mysuperlab.netcraze.pro/api/bounds
Do not proceed until dev is correct — prod is a copy of dev.
Step 1 — Commit and push code
Where: Dev PC
Commit the release so prod is reproducible and the Docker build ships the intended code.
git status
git add .
git commit -m "Release: <summary of changes>"
git push origin main
Step 2 — Back up the dev database
Where: Dev PC
Creates a data-only dump (INSERT statements) under db/DataBackup/.
npm run dev:db:backup
Output (note the exact path — you pass it to Step 4):
Backup written: db/DataBackup/gallery_dev_data_YYYYMMDD_HHMMSS.txt
Archive written: db/DataBackup/gallery_dev_data_YYYYMMDD_HHMMSS.zip
Also back up prod before overwriting it (optional but recommended):
npm run prod:db:backup→db/DataBackup/gallery_prod_data_*.txt. Keep it as a rollback point (see Rollback).
Step 3 — Apply schema changes to prod (only if schema changed)
Where: Dev PC
The data restore in Step 4 only inserts rows — it does not create tables or add columns. If this release added a migration (db/migrate-*.sql) or changed db/schema.sql, the prod schema must be updated first so the new columns/tables exist.
server/migrate.js is idempotent (schema and migrations use IF NOT EXISTS / additive ALTERs). Point it at prod for one run by overriding DB_NAME (all other credentials come from .env; the gallery user has rights to both databases):
$env:DB_NAME = "gallery_prod"
npm run dev:migrate
Remove-Item Env:\DB_NAME # restore dev default so later commands hit gallery_dev
Expect schema.sql + each migrate-*.sql to log OK. Re-running is safe.
If you prefer not to override env, temporarily set
DB_NAME=gallery_prodin a scratch shell only — never edit the committed root.envto point at prod.
Step 4 — Restore dev data into prod (only if data/DB changed)
Where: Dev PC
Loads the Step 2 backup into gallery_prod. This TRUNCATES all public tables in prod first, then inserts dev's rows — prod becomes an exact copy of dev's data.
npm run devtoprod:db:restore -- --file db/DataBackup/gallery_dev_data_YYYYMMDD_HHMMSS.txt
Type yes at the confirmation prompt (or set CONFIRM_PROD=1 to skip it in automation).
Caveats — prod tables are replaced by dev's contents:
usersandcurator_audit_logare overwritten. The dev curator account and password become the prod login, and prod audit history is replaced. Make sure the dev curator credentials are the ones you want in prod.- The
sessiontable is truncated, so any active prod curator sessions are logged out. - The target is guarded: the restore refuses to run unless the database name ends with
_prodand only readsinfra/docker/.env.prod.
Step 5 — Sync images to prod (only if image files changed)
Where: Dev PC (SMB share mapped — see Prerequisites)
Copies data/images/ (paintings, portraits, and thumbs/) from the repo to the TrueNAS volume.
npm run devtoprod:images
Type yes when prompted. Robocopy exit codes 0–7 = success. Destination: \\192.168.10.122\Gallery\data\images.
Thumbnails are files, generated on dev (
npm run dev:regenerate-thumbnails/dev:regenerate-portrait-thumbs) and shipped here — prod does not regenerate them. Regenerate on dev before this step if needed.
Step 6 — Build and push the Docker image (only if code changed)
Where: Dev PC — PowerShell as Administrator, Docker Desktop running
Builds the Express API + freshly built client SPA and pushes to Gitea.
docker login gitea.mysuperlab.netcraze.pro
npm run prod:docker:publish
- Already built and only need to push:
npm run prod:docker:push-only - Image tag:
gitea.mysuperlab.netcraze.pro/danilka/gallery-web:latest - No registry / offline:
.\infra\docker\save-for-truenas.ps1→ copygallery-web.tarvia theGallerySMB share → on TrueNASsudo bash infra/docker/truenas-load-image.sh /path/to/gallery-web.tar.
Step 7 — Restart gallery-web on TrueNAS (after code or schema changes)
Where: TrueNAS — Web UI
- Apps → gallery-web → Restart (pulls
:latestwhenpull_policy: always, otherwise redeploy to force a pull). - Wait for status Running.
Data-only or image-only releases (no new image) do not require a restart, but a restart is harmless.
Step 8 — Verify production
Where: Dev PC / browser
Bypass the router first (should return JSON instantly), then check the public URL:
curl.exe -s http://192.168.10.122:5173/api/bounds
curl.exe -sk https://gallery.mysuperlab.netcraze.pro/api/bounds
Then open https://gallery.mysuperlab.netcraze.pro/ and confirm:
- Timeline + movement flow load; portraits appear.
- Click a portrait / movement → 3D hall renders with painting images (
/images/paintings/...). - Curator login (top-right) works with the intended credentials.
Optional on TrueNAS shell: bash infra/docker/truenas-verify.sh.
Rollback
| Problem | Action |
|---|---|
| Bad data release | Re-run Step 4 with the pre-release prod backup: npm run devtoprod:db:restore -- --file db/DataBackup/gallery_prod_data_<pre-release>.txt |
| Bad code release | Rebuild from the last good commit: git checkout <good-commit>, npm run prod:docker:publish, restart gallery-web |
| Bad images | Re-sync from a known-good dev copy, or pull prod back to dev with npm run prodto:dev:images to compare |
Keep at least the most recent gallery_prod_data_*.txt from Step 2 so a data rollback is always possible.
Command quick reference
| Step | Command | Runs on |
|---|---|---|
| 0 Validate | npm run prod:build |
Dev PC |
| 1 Ship code | git add . ; git commit -m "…" ; git push origin main |
Dev PC |
| 2 Backup dev | npm run dev:db:backup |
Dev PC |
| 2 Backup prod (rollback point) | npm run prod:db:backup |
Dev PC |
| 3 Migrate prod schema | $env:DB_NAME="gallery_prod"; npm run dev:migrate; Remove-Item Env:\DB_NAME |
Dev PC |
| 4 Restore data → prod | npm run devtoprod:db:restore -- --file <dev backup>.txt |
Dev PC |
| 5 Sync images → prod | npm run devtoprod:images |
Dev PC (SMB) |
| 6 Build + push image | npm run prod:docker:publish |
Dev PC (Admin) |
| 7 Restart app | Apps → gallery-web → Restart | TrueNAS UI |
| 8 Verify | curl.exe -sk https://gallery.mysuperlab.netcraze.pro/api/bounds |
Dev PC |
Safety guards (built in)
- Prod DB scripts read only
infra/docker/.env.prod; dev scripts refuse_proddatabase names. - Prod restore/backup require typing
yes(orCONFIRM_PROD=1). npm run dev:migratetargets whateverDB_NAMEis set — alwaysRemove-Item Env:\DB_NAMEafter Step 3 so later commands stay on dev.
Related docs
| Document | Contents |
|---|---|
| environments.md | Full dev/prod walkthrough, one-time setup, Keenetic |
| infra/docker/DEPLOY-truenas.md | TrueNAS container install and troubleshooting |
| FAC.md | Command cheat sheet |
| data-and-images.md | Catalog and image pipeline |