Preserve deleted server history
Retain historical server identities, results, and evidence after deletion. Mark archived entries as Deleted and prevent old work from targeting servers that reuse the same name. Fixes #16.
This commit is contained in:
@@ -33,7 +33,7 @@ export async function GET({ params }: { params: { id: string } }) {
|
||||
const events = db().prepare('SELECT id, created_at, message FROM beta_events WHERE beta_id = ? ORDER BY id').all(id);
|
||||
const campaign = db().prepare("SELECT id FROM deployments WHERE beta_id = ? AND action = 'promote' ORDER BY started_at DESC LIMIT 1").get(id) as { id: string } | undefined;
|
||||
const promotion = campaign ? { ...campaign,
|
||||
pending: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND restart_state NOT IN ('done','failed','cancelled')").get(campaign.id) as { n: number }).n,
|
||||
failed: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND restart_state = 'failed'").get(campaign.id) as { n: number }).n } : null;
|
||||
pending: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND server_deleted_at IS NULL AND restart_state NOT IN ('done','failed','cancelled')").get(campaign.id) as { n: number }).n,
|
||||
failed: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND server_deleted_at IS NULL AND restart_state = 'failed'").get(campaign.id) as { n: number }).n } : null;
|
||||
return json({ beta, scripts, servers, events, test: testView(id), promotion });
|
||||
}
|
||||
|
||||
@@ -19,11 +19,12 @@ export async function POST({ params, request }: { params: { id: string }; reques
|
||||
if (!body.server) return json({ ok: false, error: 'server is required' }, { status: 400 });
|
||||
|
||||
const row = db()
|
||||
.prepare('SELECT stage, restarted_at, healthy_at FROM beta_servers WHERE beta_id = ? AND server = ?')
|
||||
.prepare('SELECT stage, restarted_at, healthy_at, server_deleted_at FROM beta_servers WHERE beta_id = ? AND server = ?')
|
||||
.get(betaId, body.server) as
|
||||
| { stage: string; restarted_at: string | null; healthy_at: string | null }
|
||||
| { stage: string; restarted_at: string | null; healthy_at: string | null; server_deleted_at: string | null }
|
||||
| undefined;
|
||||
if (!row) return json({ ok: false, error: 'no such beta_server' }, { status: 404 });
|
||||
if (row.server_deleted_at) return json({ ok: false, error: 'This beta server was deleted; open a new beta for its replacement.' }, { status: 409 });
|
||||
if (row.stage !== 'failed') return json({ ok: false, error: `stage is ${row.stage}, not failed` }, { status: 409 });
|
||||
|
||||
// Best-effort resume point: if we already got past restart, go back to
|
||||
|
||||
@@ -17,6 +17,9 @@ export async function POST({ params, request }: { params: { id: string }; reques
|
||||
if (!['running', 'ready-promote'].includes(beta.state)) return json({ error: 'Beta is closed' }, { status: 409 });
|
||||
try {
|
||||
const body = await request.json();
|
||||
if (db().prepare('SELECT 1 FROM beta_servers WHERE beta_id = ? AND server_deleted_at IS NOT NULL').get(id)) {
|
||||
return json({ ok: false, error: 'A beta server was deleted. Roll back this beta and open a new one to collect fresh evidence.' }, { status: 409 });
|
||||
}
|
||||
const plan = parseBetaPlan(JSON.parse(stored.plan));
|
||||
if (body.action === 'sign-off') {
|
||||
if (!['active', 'passed'].includes(stored.outcome)) throw new Error('Resume or retry the test before signing off');
|
||||
|
||||
@@ -40,12 +40,13 @@ export async function GET({ url }: { url: URL }) {
|
||||
const placeholders = ids.map(() => '?').join(',');
|
||||
const serversByDep = db()
|
||||
.prepare(
|
||||
`SELECT deployment_id, server, files_changed, restart_state, players, checked_at, restarted_at, attempts, error
|
||||
`SELECT deployment_id, server, server_deleted_at, files_changed, restart_state, players, checked_at, restarted_at, attempts, error
|
||||
FROM deployment_servers WHERE deployment_id IN (${placeholders})`
|
||||
)
|
||||
.all(...ids) as Array<{
|
||||
deployment_id: string;
|
||||
server: string;
|
||||
server_deleted_at: string | null;
|
||||
files_changed: number;
|
||||
restart_state: string;
|
||||
players: number | null;
|
||||
@@ -92,7 +93,7 @@ export async function GET({ url }: { url: URL }) {
|
||||
servers: grouped.get(d.id) ?? [],
|
||||
scripts: scriptsByDep.get(d.id) ?? []
|
||||
}))
|
||||
.filter((d) => (activeOnly ? d.servers.some((s) => s.restart_state === 'pending' || s.restart_state === 'failed') : true));
|
||||
.filter((d) => (activeOnly ? d.servers.some((s) => !s.server_deleted_at && (s.restart_state === 'pending' || s.restart_state === 'failed')) : true));
|
||||
|
||||
return json({ deployments: rows });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user