Release: <summary of changes>
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
# 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](environments.md#development-first-workflow-default). If the one-time prod install is not done yet, follow [environments.md → One-time setup](environments.md#one-time-setup-full-walkthrough) and [infra/docker/DEPLOY-truenas.md](../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`](../.env) (`gallery_dev`) | [`infra/docker/.env.prod`](../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-web` app exists).
|
||||
- **Docker Desktop** running on the dev PC; logged in: `docker login gitea.mysuperlab.netcraze.pro`.
|
||||
- Prod env file present: [`infra/docker/.env.prod`](../infra/docker/.env.prod) with `DB_NAME=gallery_prod` (copy from [`.env.prod.example`](../infra/docker/.env.prod.example) if missing).
|
||||
- SMB share mapped for image sync (per Windows session):
|
||||
|
||||
```powershell
|
||||
net use \\192.168.10.122\Gallery /user:YOUR_TRUENAS_USER
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 0 — Validate on dev
|
||||
|
||||
**Where:** Dev PC + browser
|
||||
|
||||
1. Make sure the change works on https://devgallery.mysuperlab.netcraze.pro (or `http://localhost:5173`).
|
||||
2. Build the client to catch type/compile errors before shipping:
|
||||
|
||||
```powershell
|
||||
npm run prod:build
|
||||
```
|
||||
|
||||
3. Sanity-check the dev API:
|
||||
|
||||
```powershell
|
||||
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.
|
||||
|
||||
```powershell
|
||||
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/`.
|
||||
|
||||
```powershell
|
||||
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](#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 `ALTER`s). 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):
|
||||
|
||||
```powershell
|
||||
$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_prod` in a scratch shell only — **never** edit the committed root `.env` to 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.
|
||||
|
||||
```powershell
|
||||
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:**
|
||||
|
||||
- `users` and `curator_audit_log` are 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 `session` table 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 `_prod` and only reads `infra/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.
|
||||
|
||||
```powershell
|
||||
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.
|
||||
|
||||
```powershell
|
||||
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` → copy `gallery-web.tar` via the `Gallery` SMB share → on TrueNAS `sudo 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
|
||||
|
||||
1. **Apps** → **gallery-web** → **Restart** (pulls `:latest` when `pull_policy: always`, otherwise redeploy to force a pull).
|
||||
2. 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:
|
||||
|
||||
```powershell
|
||||
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 `_prod` database names.
|
||||
- Prod restore/backup require typing `yes` (or `CONFIRM_PROD=1`).
|
||||
- `npm run dev:migrate` targets whatever `DB_NAME` is set — always `Remove-Item Env:\DB_NAME` after Step 3 so later commands stay on dev.
|
||||
|
||||
## Related docs
|
||||
|
||||
| Document | Contents |
|
||||
|----------|----------|
|
||||
| [environments.md](environments.md) | Full dev/prod walkthrough, one-time setup, Keenetic |
|
||||
| [infra/docker/DEPLOY-truenas.md](../infra/docker/DEPLOY-truenas.md) | TrueNAS container install and troubleshooting |
|
||||
| [FAC.md](FAC.md#promote-dev--prod-scheduled-release) | Command cheat sheet |
|
||||
| [data-and-images.md](data-and-images.md) | Catalog and image pipeline |
|
||||
Reference in New Issue
Block a user