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:
@@ -100,8 +100,10 @@ export async function rollbackPromoteDeployment(promoteId: string): Promise<Roll
|
||||
|
||||
const fileRows = db()
|
||||
.prepare(
|
||||
`SELECT id, server, verb, rel_path, sha256_before, sha256_after, content_before, content_after
|
||||
FROM deployment_files WHERE deployment_id = ? ORDER BY server, rel_path`
|
||||
`SELECT f.id, f.server, f.verb, f.rel_path, f.sha256_before, f.sha256_after, f.content_before, f.content_after
|
||||
FROM deployment_files f JOIN deployment_servers ds ON ds.deployment_id = f.deployment_id AND ds.server = f.server
|
||||
JOIN servers s ON s.name = f.server
|
||||
WHERE f.deployment_id = ? AND ds.server_deleted_at IS NULL AND s.destroyed_at IS NULL ORDER BY f.server, f.rel_path`
|
||||
)
|
||||
.all(promoteId) as FileRow[];
|
||||
|
||||
@@ -148,20 +150,27 @@ export async function rollbackPromoteDeployment(promoteId: string): Promise<Roll
|
||||
|
||||
const affectedServers: string[] = [];
|
||||
const perServerFailures = new Map<string, string>();
|
||||
const active = (server: string) => !!db().prepare(`SELECT 1 FROM deployment_servers ds JOIN servers s ON s.name = ds.server
|
||||
WHERE ds.deployment_id = ? AND ds.server = ? AND ds.server_deleted_at IS NULL AND s.destroyed_at IS NULL`).get(promoteId, server);
|
||||
|
||||
for (const [server, files] of perServer) {
|
||||
if (!active(server)) continue;
|
||||
try {
|
||||
for (const f of files) {
|
||||
if (!active(server)) break;
|
||||
const kind = kindForRelPath(f.rel_path);
|
||||
const dest = destOfKind(server, kind);
|
||||
const abs = join(dest, f.rel_path);
|
||||
await mkdir(join(dest, dirname(f.rel_path)), { recursive: true });
|
||||
if (!active(server)) break;
|
||||
const owningScript = scriptByTarget.get(f.rel_path);
|
||||
if (f.verb === 'added') {
|
||||
if (existsSync(abs)) await rm(abs, { force: true });
|
||||
if (!active(server)) break;
|
||||
removeScript(server, f.rel_path);
|
||||
} else if (f.verb === 'updated' && f.content_before) {
|
||||
await writeFile(abs, f.content_before);
|
||||
if (!active(server)) break;
|
||||
const priorVer = owningScript?.prior_version_id
|
||||
? getVersion(owningScript.prior_version_id)
|
||||
: null;
|
||||
@@ -175,10 +184,11 @@ export async function rollbackPromoteDeployment(promoteId: string): Promise<Roll
|
||||
);
|
||||
} else if (f.verb === 'removed' && f.content_before) {
|
||||
await writeFile(abs, f.content_before);
|
||||
if (!active(server)) break;
|
||||
recordScript(server, f.rel_path, null, f.sha256_before!, f.content_before.byteLength, `rollback:${newDepId}`);
|
||||
}
|
||||
}
|
||||
affectedServers.push(server);
|
||||
if (active(server)) affectedServers.push(server);
|
||||
} catch (err) {
|
||||
perServerFailures.set(server, (err as Error).message);
|
||||
}
|
||||
@@ -220,6 +230,7 @@ export async function rollbackPromoteDeployment(promoteId: string): Promise<Roll
|
||||
);
|
||||
}
|
||||
for (const [server, files] of perServer) {
|
||||
if (!active(server)) continue;
|
||||
if (perServerFailures.has(server)) {
|
||||
insertDepServer.run(newDepId, server, 0, 'failed', perServerFailures.get(server)!);
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user