d5fbaa3034
CI / changes (push) Successful in 1s
CI / unit (push) Successful in 9s
CI / integration (push) Successful in 15s
CI / ui (push) Successful in 1m2s
CI / conformance (push) Successful in 9s
CI / gate (push) Successful in 0s
CI / deploy (push) Successful in 1m42s
The finished-game export (GCG + a new PNG of the final position) is one signed, short-lived relative URL (game.export_url; HMAC-SHA256, 10-min TTL, BACKEND_EXPORT_SIGN_KEY) resolved against the client's own origin and delivered by the best affordance each platform has (five on-device review rounds): - TG Android/desktop: native showPopup chooser -> native downloadFile dialog (bridge-only chain, activation-safe). - TG iOS: app-modal chooser -> OS share sheet with the fetched file (a popup callback cannot supply the activation the sheet needs). - VK iOS: VKWebAppDownloadFile for both formats. - VK Android: the PNG opens in VK's native image viewer, the GCG copies to the clipboard (the VK Android downloader hangs on any download, Content-Length/Range notwithstanding). - VK desktop iframe / desktop browsers: plain anchor downloads. - Mobile browsers: the OS share sheet (fetch-then-share). - Legacy TG (< Bot API 8.0): app modal + GCG clipboard, no image option. The PNG is rasterized on demand by the new internal `renderer` sidecar (node:22-slim + skia-canvas + baked Liberation/Noto Color Emoji fonts) executing the SAME ui/src/lib/gameimage.ts the ui project unit-tests; the backend rebuilds the render payload from the journal + engine.AlphabetTable, and the device date locale, IANA time zone and localized non-play labels ride the signed URL. Nothing is stored — the artifact re-derives from the immutable journal on each GET. The gateway forwards /dl/* (caddy @gateway matcher extended) behind the per-IP public rate limiter and serves bytes via http.ServeContent. Deploy: renderer service in compose + prod overlay + rolling order + prod push list; TEST_/PROD_EXPORT_SIGN_KEY secrets; the sidecar smoke runs in the ui CI job. Docs: ARCHITECTURE, FUNCTIONAL(+_ru), UI_DESIGN, TESTING, deploy/README, renderer/README.
106 lines
2.6 KiB
YAML
106 lines
2.6 KiB
YAML
# Production main-host overlay, applied on top of docker-compose.yml on the main host:
|
|
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
|
#
|
|
# It (1) publishes caddy 80/443 — there is no host caddy in prod, so the contour caddy
|
|
# owns the edge and does its own ACME on CADDY_SITE_ADDRESS — and the gateway bot-link
|
|
# :9443 the remote bot dials in over mTLS; and (2) retunes the baseline limits down for the
|
|
# 2 vCPU / 1.9 GiB host (GOMAXPROCS=2, smaller memory caps, shorter Prometheus
|
|
# retention). The contour launches deliberately undersized at zero players; the added
|
|
# node_exporter + Grafana watch host memory so it can be resized at Selectel when
|
|
# traffic arrives.
|
|
#
|
|
# The bot + its VPN sidecar are absent here (the telegram-local profile is not
|
|
# activated); the prod bot runs on its own host from docker-compose.bot.yml.
|
|
|
|
services:
|
|
caddy:
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 96M
|
|
|
|
gateway:
|
|
# Prod pulls the pushed image by tag instead of building locally; the base
|
|
# build: section stays dormant because the deploy always pulls first.
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-gateway:${TAG:?set TAG}
|
|
ports:
|
|
- "9443:9443"
|
|
environment:
|
|
# 2 vCPU host: align the Go scheduler with the cgroup quota (the baseline's 3-core gateway needs 3 cores).
|
|
GOMAXPROCS: "2"
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: "2.0"
|
|
memory: 384M
|
|
|
|
backend:
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-backend:${TAG:?set TAG}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 384M
|
|
|
|
postgres:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 384M
|
|
|
|
renderer:
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-renderer:${TAG:?set TAG}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 160M
|
|
|
|
validator:
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-telegram-validator:${TAG:?set TAG}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 96M
|
|
|
|
landing:
|
|
image: ${REGISTRY:?set REGISTRY}/scrabble-landing:${TAG:?set TAG}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 64M
|
|
|
|
otelcol:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
|
|
prometheus:
|
|
command:
|
|
- --config.file=/etc/prometheus/prometheus.yml
|
|
- --storage.tsdb.retention.time=7d
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
|
|
tempo:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 384M
|
|
|
|
grafana:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
|
|
postgres_exporter:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 64M
|