docs: client build, install, verify and rollback runbook #118
1 changed files with 117 additions and 0 deletions
117
docs/gamecult/client-build-install.md
Normal file
117
docs/gamecult/client-build-install.md
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# Ratatoskr client: build, install, verify, roll back
|
||||
|
||||
Who does what. The steward (Void) builds and hands off; Void holds no root and does not deploy.
|
||||
Eureka installs on the chat.gamecult.org host, which is Eureka's. This page is the shared
|
||||
procedure. Nothing here is run by the build step against the live host.
|
||||
|
||||
## Facts about the host
|
||||
|
||||
- Web root: `/srv/cinny/`. `current` is a symlink to one directory under `releases/`; the web
|
||||
server serves `current`. Releases are `releases/ratatoskr-<8hex>` (older ones are
|
||||
`ratatoskr-nemesis-<8hex>`). Previous releases stay on disk; that is the rollback.
|
||||
- The client is static. `config.json` sits in the release root beside `index.html` and is read
|
||||
at load. Cinny's `Dockerfile` and `docker-nginx.conf` are upstream's container path, not the
|
||||
chat.gamecult.org path.
|
||||
- Check the pointer before anything else: `readlink /srv/cinny/current`.
|
||||
|
||||
## 1. Build (steward)
|
||||
|
||||
Two builds exist, and they treat `config.json` differently.
|
||||
|
||||
**By hand (the repo's config).** `vite build` copies the repo's `config.json` into `dist/`
|
||||
(`vite.config.js`, static copy of `config.json`). Ratatoskr #103 made the repo file the intended
|
||||
served config, and #106 set `backgroundScene.style` to `ridge`; the served file has not caught up
|
||||
(see Open). Do not hand-edit `dist/config.json`.
|
||||
|
||||
```sh
|
||||
git clone https://eureka.gamecult.org/forge/GameCult/Ratatoskr.git && cd Ratatoskr
|
||||
git checkout <full-40-hex-sha> # build a named commit, not a branch tip
|
||||
npm ci --ignore-scripts # .npmrc sets legacy-peer-deps; skips husky's prepare hook
|
||||
node scripts/sync-poses.mjs # pose art is not committed; this also rewrites the tracked
|
||||
# src/app/components/message/pose/catalogue.json
|
||||
NODE_OPTIONS=--max_old_space_size=6144 npm run build # writes dist/
|
||||
```
|
||||
|
||||
Skip `sync-poses` and the build ships with no poses. Do not use `npm run build:preview` for
|
||||
production: it rewrites `dist/config.json` for preview (hash router, chosen tier and style).
|
||||
|
||||
**The handoff build (what the host installs).**
|
||||
`/opt/commons/handoff/ratatoskr-main-build/build-prod-dist.sh <full-sha>` (see its `README.md`)
|
||||
writes `/opt/commons/handoff/ratatoskr-main-<full-sha>/{dist,SHA256SUMS,BUILD-INFO,build.log}`,
|
||||
locks the files read-only and refuses to overwrite. It does **not** ship the repo's `config.json`:
|
||||
it discards it and writes its own pinned `config.production.json` into `dist/config.json`, and
|
||||
BUILD-INFO says so (`config_json_source`). That pin (sha256 `a26d846b…`, pinned 2026-11-09) has no
|
||||
`backgroundScene` block, so it no longer equals the served file, and the script's live-config
|
||||
check stops the build; earlier handoffs ran it with `SKIP_LIVE_CHECK=1` or a modified copy whose
|
||||
pin was the repo's config (see `config_json_pinned_path` in
|
||||
`ratatoskr-main-df245e0b76fd83d7ee14fe725b0df9994f36755f/BUILD-INFO`). Repin deliberately
|
||||
(README, "The pinned production config") or say in the handoff which config the dist carries.
|
||||
The folder, with the three pins (`SHA256SUMS` sha256, `BUILD-INFO` sha256, lockfile sha256) and
|
||||
the node and npm versions, is what the install request names.
|
||||
|
||||
Before handing off:
|
||||
|
||||
```sh
|
||||
cd <folder>/dist && sha256sum -c ../SHA256SUMS # 0 failures
|
||||
grep -rl 'demo.invalid\|demo-preview-token' <folder>/dist # must print nothing
|
||||
# from Yggdrasil the public name may not resolve; --resolve points it at the local server
|
||||
diff <(curl -fsS --resolve chat.gamecult.org:443:127.0.0.1 https://chat.gamecult.org/config.json) <folder>/dist/config.json
|
||||
```
|
||||
|
||||
A config difference is a finding to report, not something to paper over: either live drifted or
|
||||
the repo is wrong, and a ruling (Meta, for `backgroundScene.style`) says which ships.
|
||||
|
||||
## 2. Install (host owner, root, by hand)
|
||||
|
||||
Note the rollback target first: `readlink /srv/cinny/current`.
|
||||
|
||||
Unpack beside the live release; do not touch the live directory. The target must not exist, or
|
||||
`cp -r` nests `dist` inside it.
|
||||
|
||||
```sh
|
||||
R=ratatoskr-<8hex>
|
||||
H=/opt/commons/handoff/ratatoskr-main-<full-sha>
|
||||
test ! -e /srv/cinny/releases/$R
|
||||
cp -r $H/dist /srv/cinny/releases/$R
|
||||
cmp /srv/cinny/current/config.json /srv/cinny/releases/$R/config.json
|
||||
(cd /srv/cinny/releases/$R && sha256sum -c $H/SHA256SUMS)
|
||||
```
|
||||
|
||||
`cmp` is a drift check, not a pass check. Live has no trailing newline; the repo's file has one,
|
||||
so even equal content differs. Read the difference (`diff` the two) and settle which config
|
||||
ships. To keep the host's config byte-for-byte, as past installs did,
|
||||
`cp /srv/cinny/current/config.json /srv/cinny/releases/$R/config.json`; `sha256sum -c` then flags
|
||||
`config.json` only (read that one line, or use `--ignore-missing`).
|
||||
|
||||
Switch (a single symlink swap; `ln -sfn` unlinks then links, so there is a moment with no link):
|
||||
|
||||
```sh
|
||||
ln -sfn releases/$R /srv/cinny/current
|
||||
```
|
||||
|
||||
## 3. Verify
|
||||
|
||||
- `readlink /srv/cinny/current` names `releases/$R`.
|
||||
- `curl -s https://chat.gamecult.org/config.json | sha256sum` equals the release's `config.json`.
|
||||
- Load https://chat.gamecult.org/ and hard-refresh (the service worker, `sw.js`, can hold the
|
||||
previous assets). Sign-in card shows, the background scene draws, the browser console has no
|
||||
page errors, a poses/asset request returns 200 and not index.html.
|
||||
|
||||
## 4. Roll back
|
||||
|
||||
Point `current` at the release noted before the switch. Live at the time of writing is
|
||||
`ratatoskr-nemesis-9b9b495d`:
|
||||
|
||||
```sh
|
||||
ln -sfn releases/ratatoskr-nemesis-9b9b495d /srv/cinny/current
|
||||
```
|
||||
|
||||
Hard-refresh to clear `sw.js`. Do not delete the failed release; leave it for diagnosis.
|
||||
|
||||
## Open
|
||||
|
||||
- The served config (checked 2026-11-12) is not the repo's: it says `backgroundScene.style`
|
||||
`terrain` where the repo says `ridge` (#106, Meta 2026-11-11), lacks the repo's `dings`,
|
||||
`fileZoneShare` and `registration` blocks (all off in the repo), and has no trailing newline.
|
||||
The new keys default off or inert when absent, so only the style is a decision. Meta says which
|
||||
style ships. The handoff script's pin is stale against live (section 1).
|
||||
Loading…
Reference in a new issue