Rework as scripts-centric, upload-only, gated beta lifecycle
Scripts become first-class: named, versioned, uploaded via the UI, optionally scoped to a game or map. Any change that would land on scope-matched servers (marking-required or new version of a scoped script) must first pass a beta. The beta runs a per-server state machine — deploy -beta.gsc → wait empty → Komodo restart → wait healthy → optionally wait for a real match end (games_sp.log 'ExitLevel: executed') — before it's eligible for promotion. Rollback is always available and restores from .OLD. The shared/scripts mirror and its betas/ staging folder are gone. Every server now has a tracked script inventory (server_scripts table), populated only by explicit upload flows. New: /scripts, /scripts/[id], /betas/[id] UI; /api/scripts + /api/betas + /api/servers/[name]/scripts endpoints; scripts.ts, inventory.ts, beta.ts (rewritten), beta-runner.ts, match-log.ts, komodoInspectHealthy(). Removed: push.ts, /api/push, BetaPanel, legacy importer. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { db } from '../db/index.js';
|
||||
|
||||
export interface ServerScriptRow {
|
||||
server: string;
|
||||
rel_path: string;
|
||||
script_version_id: number | null;
|
||||
sha256: string;
|
||||
size: number;
|
||||
updated_at: string;
|
||||
source: string | null;
|
||||
}
|
||||
|
||||
// Upsert an inventory row for a file that just landed on a server. Called from
|
||||
// every writer (beta open, beta update, promote, rollback) so the DB tracks
|
||||
// exactly what's on-disk in each server's sp/ directory.
|
||||
export function recordScript(
|
||||
server: string,
|
||||
relPath: string,
|
||||
scriptVersionId: number | null,
|
||||
sha256: string,
|
||||
size: number,
|
||||
source: string
|
||||
): void {
|
||||
db()
|
||||
.prepare(
|
||||
`INSERT INTO server_scripts (server, rel_path, script_version_id, sha256, size, updated_at, source)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(server, rel_path) DO UPDATE SET
|
||||
script_version_id = excluded.script_version_id,
|
||||
sha256 = excluded.sha256,
|
||||
size = excluded.size,
|
||||
updated_at = excluded.updated_at,
|
||||
source = excluded.source`
|
||||
)
|
||||
.run(server, relPath, scriptVersionId, sha256, size, new Date().toISOString(), source);
|
||||
}
|
||||
|
||||
export function removeScript(server: string, relPath: string): void {
|
||||
db().prepare('DELETE FROM server_scripts WHERE server = ? AND rel_path = ?').run(server, relPath);
|
||||
}
|
||||
|
||||
export function getServerScript(server: string, relPath: string): ServerScriptRow | undefined {
|
||||
return db()
|
||||
.prepare('SELECT * FROM server_scripts WHERE server = ? AND rel_path = ?')
|
||||
.get(server, relPath) as ServerScriptRow | undefined;
|
||||
}
|
||||
|
||||
export function listServerScripts(server: string): ServerScriptRow[] {
|
||||
return db()
|
||||
.prepare('SELECT * FROM server_scripts WHERE server = ? ORDER BY rel_path')
|
||||
.all(server) as ServerScriptRow[];
|
||||
}
|
||||
|
||||
export function listAllScripts(): ServerScriptRow[] {
|
||||
return db()
|
||||
.prepare('SELECT * FROM server_scripts ORDER BY server, rel_path')
|
||||
.all() as ServerScriptRow[];
|
||||
}
|
||||
Reference in New Issue
Block a user