Files
vtube/docs/DEPLOY.md
goboss d59393a608 ADS: VAST has implicit dependency on popunder cooldown
DEPLOY: document custom CDN stale-cache gotcha + recovery

Findings from 8148 production debug session 2026-05-02:

1. VAST gotcha — _decide() mode логіка:
   mode = popActive ? (vastActive || skipPattern ? "none" : "vast") : "pop"
   Тобто VAST loadable ТІЛЬКИ після того як popunder уже спрацював і
   _popRr cooldown set. На свіжій сесії: mode завжди "pop" → VAST SDK
   never loaded → користувач думає "VAST зламаний". Force test через
   ?clearAds=1 → pop fires → refresh → mode=vast.

2. CDN stale-cache — custom CDN кешує `?v=<hex-like>` URLs з
   s-maxage=31536000 (1 рік). Race у deploy: layout.etlua з новим ?v=
   може hit CDN раніше ніж static file → CDN кешує OLD bundle під
   NEW ?v= ключем → застрягає назавжди. Workaround: bump source md5,
   rebuild, новий ?v= ключ.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 21:51:32 +00:00

109 lines
7.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# tubev — Deploy Flow
Як зміна потрапляє з робочого місця → у prod.
## Two-tier model
```
Edit /home/nosfortube/frontend_<port>/ ← work / source-of-truth
├──→ t1.<domain> ← test (instant, IP-allowlist)
└──→ admin panel "site/control" ← prod деплой per-site (юзер натискає)
або через Адміна ← для var.lua / нових файлів
└──→ <domain> ← live, з CDN
```
## Test environment — `t1.<domain>`
- **Доступ:** IP-allowlist (ймовірно nginx-level, не точно). Юзер заходить через VPN щоб мати стабільний IP.
- **Apply:** instant — змінив файл у `frontend_<port>/` → видно на t1.<domain> одразу.
- **Обмеження** (per-site різні): CDN off, compression off, повільніше, comments/ads можуть бути обмежені або тестові.
- **AI-side:** ✅ Claude з сервера **МАЄ доступ** до t1.<domain> (server IP `185.73.222.75` у allowlist). Перевірено 2026-05-01: `curl -I https://t1.atube.sex` → 200 OK, `curl -I https://t1.hdsexvideo.xxx` → 200 OK. Можна робити HTTP probes для health-check, regression smoke, response inspection.
## Prod deploy — три шляхи
### A) Через admin panel "site control" (юзер сам, instant per-site)
`https://rss.g--o.info/admin/site/control` — список усіх сайтів, кнопка викатати оновлення з тесту → прод.
**Покриває:** templates `.etlua`, CSS, JS (звичайні per-site файли).
**Не покриває (потрібен Адмін):**
- `lib/<port>/var.lua` — нові/змінені змінні
- Нові файли (yet not in admin's git)
- Shared `views/static/js/lib/`, `lib2/` (cross-site impact)
### B) Через admin panels (settings / translations / sitemap)
Контент-шар, не код. Самостійно, без Адміна:
- Per-site settings: `https://<domain>/admin/index`, `/admin/settings`
- Languages set: `https://<domain>/moderation/languages/langs`
- Translations (UI strings): `https://<domain>/moderation/languages/translation/`
- Sitemap: `https://rss.g--o.info/admin/site`
Деталі: [ADMINS.md](ADMINS.md).
### C) Через Адміна (Орест / основний програміст)
- Нові файли потрапляють у Адмінів git → kor pull/reload
- `var.lua` зміни → kor reboot
- Mass operations (mirror swaps, multi-site fixes)
Trigger: попросити (чат / задача).
## kor reload
- `lib/<port>/var.lua` зміни → потрібен **kor reboot** щоб env змінні підвантажилися
- Templates `.etlua` — підхоплюються hot (без reboot)
- Static assets — hot, але **CDN cache** може тримати стару версію → потрібен **cache-bust** (через `?v=<md5>` у layout — реалізовано у `~/git-save-all.sh`)
## CDN
- **Custom CDN** для більшості сайтів (наявний; провайдер невідомий поки)
- **Cloudflare** на двох сайтах (наприклад **8081**) — додаткове edge кешування
- **При оновленні prod** для Cloudflare-сайтів: треба **purge cache** + враховувати у логіці що зміни не миттєві (cache TTL до purge)
- Cache-bust через `?v=<md5>` у `layout.etlua` працює для обох (custom + CF)
### ⚠️ Stale-cache gotcha (custom CDN, 8148 confirmed 2026-05-02)
Custom CDN serve-ить різні `cache-control` залежно від виду query string:
| Pattern URL | s-maxage | Поведінка |
|-------------|----------|-----------|
| `?v=<hex-like-7-chars>` (md5 prefix) | **31536000 (1 рік)** | "Content-addressed asset" — immutable, edge cache aggressive |
| `?v=<short>` (число, ZZZZ etc.) | 10 sec | Швидко refresh-иться |
| (no query) | ~ | Звичайний cache |
**Race condition при deploy:**
1. Template (layout.etlua) deploy-иться з новим `?v=<new_md5>` reference
2. До того як static (`ad-bundle.min.js`) сам file deploy-иться — браузер/crawler hit-ить `<host>/ad-bundle.min.js?v=<new_md5>`
3. CDN cache-miss → origin ще має OLD bundle → CDN кешує OLD під новим `?v=` ключем
4. Static deploy-иться з NEW bundle, але **CDN cache stuck на 1 рік** з OLD content
**Симптом:** `curl <host>/ad-bundle.min.js` → NEW. `curl <host>/ad-bundle.min.js?v=<deployed_md5>` → OLD. Live site поломаний.
**Рішення:**
- Bump bundle md5 (тривіальна зміна у source — додаткова line, build stamp): `git-save-all.sh` rebuilds → новий md5 → новий ?v= → нова cache entry → fresh
- Або **purge CDN cache** (через адмін / hostiserver)
- Краще довгостроково: змінити cache-bust scheme у `git-save-all.sh` щоб включав timestamp (`?v=<md5>-<unix>`) → завжди унікально
Перевірка чи це сталося: `curl -sI <host>/<file>?v=<md5> | grep s-maxage` — якщо `31536000`, кеш заблокувався на рік.
## git-save-all.sh — git-snapshot для backup_<port>/
`~/git-save-all.sh "msg"` ітерує `/home/w4/backup_*/`:
1. **`sync.sh` per backup** — копіює з prod (`/home/nosfortube/frontend_<port>/`) у backup. **Tracked subset** (whitelist у sync.sh): templates (`layout.etlua`, `id_index.etlua`, `video.etlua`, banner modules), ad orchestration JS (`ad-config.js`, `ad-core.js`, `vast-preroll.js`, `ad-bundle.min.js`), player files, тести, robots.txt. Решта prod-коду — поза git.
2. **Auto-rebuild ad-bundle:** якщо будь-який з 5 source JS (`ad-config.js`, `ad-core.js`, `ad-mute.js`, `vast-preroll.js`, `ad-bootstrap.js`) новіший за `ad-bundle.min.js` → запуск `bash build-ad-bundle.sh` (terser concat+minify).
3. **Cache-bust:** md5sum bundle → перші 7 hex → `sed -i ?v=...` у `views/layout.etlua`. Idempotent (однаковий контент = однаковий хеш).
4. **Commit per backup:** message формат `YYYY-MM-DD_HH:MM - <msg> [backup_<port>]`. Кожен backup repo окремо — N changed sites = N commits у різних repos.
**Призначення:** git-tracking для recovery / audit / blame. **Не deploy mechanism.**
## Open questions
- [ ] CDN — який провайдер (Cloudflare / BunnyCDN / Fastly)? Per-site чи unified?
- [ ] Backup_<port>/ покриття — чому 14 із 94 сайтів? Поширити чи це історичний субсет? (open-разом з юзером)
- [ ] Headless browser (Puppeteer / Playwright) на сервері для visual regression / ad-render check — варто setup-нути на потребу?