Initial commit — SvelteKit fleet manager for T5 Plutonium servers
Ports push_scripts.sh (1497 lines of bash) to a SvelteKit + SQLite web app that manages a fleet of T5 Plutonium servers running on Komodo. Same push and beta workflow as the shell script, with a live SSE pipeline view, a !rt-token-gated auth modal that hard-pauses deployments on stale tokens, per-file audit diffs, and a Komodo-container deployment target. - Push/beta engines port the exact filter, held-by-beta, conflict, and stale-backup rules from the shell script - SQLite (better-sqlite3) replaces script_metadata.json; a one-shot importer moves legacy state over on first boot - 16 vitest tests cover push add/update/skip, beta open→rollback, open→promote, conflict guards, sweep frozen/manual branches, and IW4M login/status parsing - docker/ + komodo/stack.toml deploy as a managed container on the same host as the game servers, /root/zombies bind-mounted at the same path the shell script used
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# electric-cherry
|
||||
|
||||
Web app that manages a fleet of T5 Plutonium servers running under Komodo.
|
||||
Successor to `push_scripts.sh` — same job (push shared GSC scripts, run beta
|
||||
tests, restart empty servers, track deployments) with a live UI, real audit
|
||||
diffs, and a hard pause when the IW4MAdmin `!rt` token goes stale.
|
||||
|
||||
## Stack
|
||||
|
||||
- SvelteKit (adapter-node) + TypeScript
|
||||
- SQLite via better-sqlite3 (replaces `script_metadata.json` as the source of
|
||||
truth)
|
||||
- Server-sent events for live pipeline / auth-state / server-status streams
|
||||
- Runs as a single Komodo-managed container on the same host as the game
|
||||
servers, with `/root/zombies` bind-mounted in
|
||||
|
||||
## Layout
|
||||
|
||||
- `src/lib/server/db/` — schema, migrations, better-sqlite3 handle
|
||||
- `src/lib/server/fleet/` — file walking, push/beta engines
|
||||
- `src/lib/server/integrations/` — Komodo, IW4MAdmin, `!rt` token state
|
||||
- `src/lib/server/pipeline/` — sweep loop, event bus, worker singleton
|
||||
- `src/routes/api/` — REST + SSE endpoints
|
||||
- `src/routes/` — UI pages (dashboard, deployments, betas, per-server)
|
||||
- `docker/` — Dockerfile, entrypoint, docker-compose
|
||||
- `komodo/` — Komodo stack definition
|
||||
- `scripts/` — legacy JSON importer, fixture seeder
|
||||
- `tests/` — vitest unit tests
|
||||
|
||||
## Local dev
|
||||
|
||||
Windows or macOS — no `/root/zombies` on disk, so seed a fixture tree first.
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run seed:fixture
|
||||
|
||||
# Point env at the fixture (PowerShell)
|
||||
$env:SHARED_SCRIPTS = "$PWD/test-fixtures/zombies/shared/scripts"
|
||||
$env:SERVERS_ROOT = "$PWD/test-fixtures/zombies/t5"
|
||||
$env:DB_PATH = "$PWD/data/cherry.db"
|
||||
|
||||
npm run dev
|
||||
# open http://localhost:3000
|
||||
```
|
||||
|
||||
The `!rt` modal will block deployments until you paste a valid token. In
|
||||
local dev you can bypass it for exploration by leaving `IW4M_ADDRESS` unset
|
||||
and calling `sweep()` in a test that force-transitions the auth state (see
|
||||
`tests/unit/sweep.test.ts`).
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Covers push (add/update/skip), beta lifecycle (open → rollback, open →
|
||||
promote, conflict blocks), sweep (frozen / manual branches), and IW4M
|
||||
login/status parsing (fetch mocked).
|
||||
|
||||
## Deploy to the Komodo host
|
||||
|
||||
1. Build the image once locally or on the host:
|
||||
|
||||
```bash
|
||||
docker compose -f docker/docker-compose.yml build
|
||||
```
|
||||
|
||||
2. Import the shape of the stack into Komodo using `komodo/stack.toml` (or
|
||||
copy the compose file into a Komodo stack).
|
||||
|
||||
3. First boot triggers the legacy import: if
|
||||
`/root/zombies/script_metadata.json` exists and `/data/cherry.db` is
|
||||
empty, `docker/entrypoint.sh` runs `scripts/import-legacy.ts` before
|
||||
starting the server. The source JSON gets renamed to `.migrated`.
|
||||
|
||||
4. Load the app on the LAN or over tailscale (no web-app auth by design).
|
||||
Paste an `!rt` token to unfreeze the pipeline.
|
||||
|
||||
## What still lives in the shell script
|
||||
|
||||
Nothing that's needed at runtime. Move `push_scripts.sh` to `archive/` once
|
||||
you've run a side-by-side parity check between the shell's dry-run and the
|
||||
app's `POST /api/push { dryRun: true }`.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- **Editing GSC files in-browser.** Do that in your editor of choice; the
|
||||
web app only cares about what's on disk in `SHARED_SCRIPTS`.
|
||||
- **Multi-user auth.** LAN/tailscale scoping is the security model.
|
||||
- **Two-way sync with `script_metadata.json`.** The importer runs once. If
|
||||
the shell script is ever used again after that, it'll write to the JSON
|
||||
file and the web app won't see it.
|
||||
|
||||
## References into the old script
|
||||
|
||||
Every port carries a `// Ports push_scripts.sh:NN` comment pointing back to
|
||||
the original for the parts that had non-obvious behavior. Grep those if a
|
||||
behavior seems wrong — the shell script is the reference implementation
|
||||
until the parity check passes.
|
||||
Reference in New Issue
Block a user