ADR-012: именованные сборки (zip) рядом с номерными — /sol/; ^~ для служебных путей; два дефекта сборки фронтендера

This commit is contained in:
Porfiry
2026-09-15 19:29:54 +03:00
parent d66c5f8893
commit b9799bf091
5 changed files with 175 additions and 17 deletions
+46
View File
@@ -293,3 +293,49 @@ no-store`; `/api/state`,`/api/price`,`/solana-rpc/` → 200; сквозная с
(`/Build/WebGL.wasm`, полученные до этого фикса), один раз может получить старый билд — URL теперь
`no-store`, так что после первой перезагрузки браузер сходит на сервер и получит свежее. Новые
версии этой проблемы не имеют вовсе.
## ADR-012 — Именованные сборки (zip от фронтендера) рядом с номерными: `/sol/` (2026-09-15)
**Контекст.** Фронтендер прислал готовый Unity-WebGL-билд **zip-архивом** — вне релизного цикла Gitea
(не через CI, без образа в реестре, без номера сборки). Владелец: «создай там сам папку и выложи».
**Решение.** Каталоги на nginx теперь двух видов, живут рядом:
- `/opt/game/releases/<N>/` — номерные релизы из CI/реестра (`1`, `2`, … `29`);
- `/opt/game/releases/<имя>/` — именованные сборки из zip (`sol`).
**Именованные сборки АКТИВНУЮ не трогают**: `current` остаётся на номере, корень по-прежнему
редиректит на `/29/`. Именованная доступна только явной ссылкой `/<имя>/`.
**Изменения в nginx** (`game.nginx.conf`):
- regex-локейшн сборок расширен с чисел до имён: `^/(?<build>[a-zA-Z0-9][a-zA-Z0-9_-]*)(?<subpath>/.*)?$`;
- ⚠️ служебные пути получили префикс **`^~`** (`location ^~ /api`, `^~ /ws`, `^~ /solana-rpc/`).
Без этого расширенный regex перехватывал бы `/api/...` как «сборку с именем api» — regex-локейшн
в nginx приоритетнее обычного префиксного. `^~` подавляет проверку regex для этого префикса.
**Это была реальная регрессия на первом применении: после расширения шаблона `/api/state` начал
уходить в файловый резолвер.**
- маска `immutable` осталась **только для номерных** каталогов (`~^/[0-9]+/…`): именованную папку
могут перезалить тем же именем, поэтому кэшировать её ассеты на 7 суток нельзя. Добавлено
расширение `unityweb` (сборки фронтендера используют `.unityweb`-ассеты).
- новый скрипт `tools/proxmox-nginx/publish-zip.sh <имя> <путь.zip>` — распаковка, подъём
единственной вложенной папки, раскладка, reload, проверка.
**Приёмка (живой домен):** `/sol/` и все его ассеты (`Build.loader.js`, `Build.wasm.unityweb`,
`Build.data.unityweb`, `Build.framework.js.unityweb`, `TemplateData/*`) → **200**; `/` → 302 на `/29/`;
`/27/`,`/28/`,`/29/` живы; `/api/state`,`/api/price`,`/solana-rpc/` → 200; `testfront` цел.
**⚠️ Что нашли в присланной сборке (отдать фронтендеру, не наш блокер):**
1. **Двойной префикс API.** Игра зовёт `GET https://smart-updown.binom.pw/api/api/state` → **404**.
Причина в исходниках: `SmartUpdownConfig.ApiBase()` для WebGL возвращает `Origin() + "/api"`,
а `BackendClient.HttpGetAsync("/api/state")` добавляет путь целиком → `…/api` + `/api/state`.
В сборке 29 тот же код, но она до этого места не доходила (в headless падала раньше).
2. **`ReferenceError: getProvider is not defined`** — падение на `_SolanaBridgeConnect` при подключении
кошелька. В собранном `framework.js` есть **вызовы** `getProvider()`, `errMsg()`, `loadWeb3()`,
но **нет их определений** (в `SolanaBridge.jslib` они объявлены как функции внутри IIFE, а в
библиотеку через `mergeInto(LibraryManager.library, {...})` экспортированы только
`SolanaBridge*`-методы). Ошибка воспроизводится и в сборке 29 — то есть это **не регресс от
переезда на nginx**, а дефект jslib-обвязки, который просто не был виден раньше.
Файл — `Assets/Plugins/WebGL/SolanaBridge.jslib` (коммит `090ebf1`).
⚠️ Что **подтверждено** этим билдом: игра в браузере **стартует и доходит до игрового цикла**
(`[BinaryRocket] Phase -> Idle` → `Phase -> Approach`), чего в headless-окружении не делала ни одна
предыдущая сборка. То есть статика с nginx отдаётся корректно.