Release: <summary of changes>

This commit is contained in:
Danila Khodjaef
2026-07-07 14:30:38 +03:00
parent a86fdcce1b
commit ac1ae5794f
4 changed files with 254 additions and 2 deletions
+2 -1
View File
@@ -289,7 +289,7 @@ Expect JSON with `min_year` / `max_year`. HTML shell only from `curl` on `/` is
## Promote dev → prod (scheduled release)
~Weekly (or when explicitly releasing to prod). Not part of daily dev.
~Weekly (or when explicitly releasing to prod). Not part of daily dev. Full runbook with per-change decision matrix and rollback: [deploy-dev-to-prod.md](deploy-dev-to-prod.md).
1. Test on https://devgallery.mysuperlab.netcraze.pro
2. `npm run dev:db:backup`
@@ -331,6 +331,7 @@ Remote: https://gitea.mysuperlab.netcraze.pro/Danilka/Art-gallery
| Document | Contents |
|----------|----------|
| [deploy-dev-to-prod.md](deploy-dev-to-prod.md) | Step-by-step release runbook (code, DB, data, images) |
| [environments.md](environments.md) | Full dev/prod walkthrough |
| [setup.md](setup.md) | Install, env vars, troubleshooting |
| [data-and-images.md](data-and-images.md) | Catalog and image pipeline |
+1
View File
@@ -428,6 +428,7 @@ See [API.md](API.md#authentication) and [data-and-images.md](data-and-images.md#
| Document | Contents |
|----------|----------|
| [setup.md](setup.md) | Install, database, npm scripts |
| [deploy-dev-to-prod.md](deploy-dev-to-prod.md) | Release runbook: promote dev → prod |
| [DB_structure.md](DB_structure.md) | Tables and relationships |
| [API.md](API.md) | REST endpoints |
| [data-and-images.md](data-and-images.md) | Image pipeline and seeding |
+250
View File
@@ -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 **07** = 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 |
+1 -1
View File
@@ -305,7 +305,7 @@ See also [Drunkmeyou gitea-https-keenetic-npm-setup.md](../../Drunkmeyou/Documen
## Promote dev → prod (scheduled release)
Run this when you are ready to ship dev to production — **not** after every small change. Typical cadence: **about once a week**.
Run this when you are ready to ship dev to production — **not** after every small change. Typical cadence: **about once a week**. Detailed step-by-step runbook (per-change decision matrix, schema migration, rollback): [deploy-dev-to-prod.md](deploy-dev-to-prod.md).
**Where:** Dev PC unless noted