3fb15d6282
- Make .env the single source of truth for runtime config. Remove all
`env:` blocks from SREBOT/ecosystem.config.js and TSSBOT/ecosystem.config.js
so values can't silently shadow .env. Both ecosystem files load .env via
`require('dotenv').config()` and PM2 inherits the resolved environment.
- Rename SREBOT_STORAGE_VOL_PATH → STORAGE_VOL_PATH across all readers
(BOT/utils.py, BOT/receiver_bridge.py, BOT/render_recap.py, server.js,
web/server.js, dateindex.js, scripts/*, srebot.service, tests/, README,
and both .env files). STORAGE is shared between SREBOT and TSSBOT, so the
variable shouldn't carry one bot's prefix.
- Rename per-process PORT env vars to disambiguated names so .env can be
the source of truth without collisions:
PORT (api) → SREBOT_API_PORT (server.js)
PORT (web) → SREBOT_WEB_PORT (web/server.js)
WEBHOOK_PORT → SREBOT_WEBHOOK_PORT (github_webhook_updater.py)
SREBOT_EXTERNAL_HOST/PORT/UPSTREAM_URL were already uniquely named;
they just move from ecosystem env to .env.
- TSSBOT/.env: drop GITHUB_WEBHOOK_SECRET (only srebot-webhook consumes it)
and the stale SREBOT_DEPLOY_PATH. SREBOT/.env: also drop the obsolete
SREBOT_DEPLOY_PATH (ecosystem now hardcodes __dirname).
- ecosystem.config.js no longer references SREBOT_DEPLOY_PATH; deploy path
is always __dirname of the ecosystem file.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
82 lines
2.3 KiB
Python
82 lines
2.3 KiB
Python
"""
|
|
Smoke test for BOT/render_recap.py in --mode player.
|
|
|
|
Usage:
|
|
source .venv/bin/activate && python BOT/tests/smoke_player_recap.py
|
|
"""
|
|
|
|
import sqlite3
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
_storage_env = os.environ.get("STORAGE_VOL_PATH", "").strip()
|
|
if not _storage_env:
|
|
raise RuntimeError("STORAGE_VOL_PATH must be set")
|
|
STORAGE = Path(_storage_env)
|
|
SEASON_START = "1772348400"
|
|
SEASON_END = "1777852799"
|
|
SEASON = "2026-II"
|
|
|
|
|
|
def pick_uid() -> str:
|
|
conn = sqlite3.connect(f"file:{STORAGE/'sq_battles.db'}?mode=ro", uri=True)
|
|
cur = conn.execute(
|
|
"SELECT UID FROM player_games_hist "
|
|
"WHERE endtime_unix BETWEEN ? AND ? "
|
|
"GROUP BY UID ORDER BY COUNT(*) DESC LIMIT 1",
|
|
(int(SEASON_START), int(SEASON_END)),
|
|
)
|
|
row = cur.fetchone()
|
|
conn.close()
|
|
return row[0] if row else ""
|
|
|
|
|
|
def run_smoke(uid: str, theme: str = "dark", lang: str = "en") -> int:
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
out = Path(tmp) / f"player-{theme}-{lang}.png"
|
|
cmd = [
|
|
sys.executable,
|
|
"BOT/render_recap.py",
|
|
"--mode", "player",
|
|
"--uid", uid,
|
|
"--season", SEASON,
|
|
"--season-start", SEASON_START,
|
|
"--season-end", SEASON_END,
|
|
"--theme", theme,
|
|
"--lang", lang,
|
|
"--out", str(out),
|
|
]
|
|
print("Running:", " ".join(cmd))
|
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
print("stdout:", result.stdout)
|
|
print("stderr:", result.stderr)
|
|
if result.returncode != 0:
|
|
print(f"FAIL: exit={result.returncode}")
|
|
return result.returncode
|
|
size = out.stat().st_size if out.exists() else 0
|
|
if size < 10_000:
|
|
print(f"FAIL: suspicious size {size} bytes at {out}")
|
|
return 1
|
|
print(f"OK: wrote {size} bytes ({theme}/{lang})")
|
|
return 0
|
|
|
|
|
|
def main() -> int:
|
|
uid = pick_uid()
|
|
if not uid:
|
|
print("FAIL: no UID with season activity available for smoke test")
|
|
return 1
|
|
print(f"Using UID {uid}")
|
|
code = 0
|
|
for theme in ("light", "dark"):
|
|
for lang in ("en", "ru"):
|
|
code |= run_smoke(uid, theme=theme, lang=lang)
|
|
return code
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|