multi script beta
This commit is contained in:
@@ -2,9 +2,9 @@ import { json } from '@sveltejs/kit';
|
||||
import {
|
||||
listBetas,
|
||||
listBetaServers,
|
||||
listBetaScripts,
|
||||
openBeta,
|
||||
BetaError,
|
||||
type BetaTriggerKind
|
||||
BetaError
|
||||
} from '$lib/server/fleet/beta.js';
|
||||
import { getScript, getVersion } from '$lib/server/fleet/scripts.js';
|
||||
import { kick } from '$lib/server/pipeline/worker.js';
|
||||
@@ -17,53 +17,63 @@ export async function GET({ url }: { url: URL }) {
|
||||
| 'rolled-back'
|
||||
| null;
|
||||
const rows = listBetas(stateFilter ?? undefined).map((b) => {
|
||||
const script = getScript(b.script_id);
|
||||
const version = getVersion(b.script_version_id);
|
||||
const scripts = listBetaScripts(b.id).map((bs) => {
|
||||
const script = getScript(bs.script_id);
|
||||
const version = getVersion(bs.script_version_id);
|
||||
return {
|
||||
id: bs.script_id,
|
||||
name: script?.name ?? '(deleted)',
|
||||
target_rel_path: script?.target_rel_path ?? '',
|
||||
version: version
|
||||
? { id: version.id, version: version.version, sha256: version.sha256 }
|
||||
: null
|
||||
};
|
||||
});
|
||||
return {
|
||||
...b,
|
||||
script: script ? { id: script.id, name: script.name, target_rel_path: script.target_rel_path } : null,
|
||||
version: version ? { id: version.id, version: version.version, sha256: version.sha256 } : null,
|
||||
scripts,
|
||||
servers: listBetaServers(b.id)
|
||||
};
|
||||
});
|
||||
return json({ betas: rows });
|
||||
}
|
||||
|
||||
// POST body: { scriptId, scriptVersionId, servers[], waitForHealth, waitForMatch, triggerKind, notes? }
|
||||
// POST body: { scripts: [{ scriptId, scriptVersionId }], servers[], waitForHealth, waitForMatch, notes? }
|
||||
export async function POST({ request }: { request: Request }) {
|
||||
const body = (await request.json().catch(() => ({}))) as {
|
||||
scriptId?: number;
|
||||
scriptVersionId?: number;
|
||||
scripts?: Array<{ scriptId?: number; scriptVersionId?: number }>;
|
||||
servers?: string[];
|
||||
waitForHealth?: boolean;
|
||||
waitForMatch?: boolean;
|
||||
triggerKind?: BetaTriggerKind;
|
||||
notes?: string;
|
||||
};
|
||||
|
||||
if (
|
||||
typeof body.scriptId !== 'number' ||
|
||||
typeof body.scriptVersionId !== 'number' ||
|
||||
!Array.isArray(body.servers)
|
||||
) {
|
||||
if (!Array.isArray(body.scripts) || body.scripts.length === 0 || !Array.isArray(body.servers)) {
|
||||
return json(
|
||||
{ ok: false, error: 'scriptId, scriptVersionId, and servers[] are required' },
|
||||
{ ok: false, error: 'scripts[] (non-empty) and servers[] are required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
if (body.servers.length === 0) {
|
||||
return json({ ok: false, error: 'at least one server is required' }, { status: 400 });
|
||||
}
|
||||
const triggerKind: BetaTriggerKind = body.triggerKind ?? 'unscoped';
|
||||
const normalized: Array<{ scriptId: number; scriptVersionId: number }> = [];
|
||||
for (const s of body.scripts) {
|
||||
if (typeof s.scriptId !== 'number' || typeof s.scriptVersionId !== 'number') {
|
||||
return json(
|
||||
{ ok: false, error: 'each scripts[] entry needs scriptId and scriptVersionId' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
normalized.push({ scriptId: s.scriptId, scriptVersionId: s.scriptVersionId });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await openBeta({
|
||||
scriptId: body.scriptId,
|
||||
scriptVersionId: body.scriptVersionId,
|
||||
scripts: normalized,
|
||||
servers: body.servers,
|
||||
waitForHealth: body.waitForHealth ?? true,
|
||||
waitForMatch: body.waitForMatch ?? false,
|
||||
triggerKind,
|
||||
notes: body.notes
|
||||
});
|
||||
void kick();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { getBeta, listBetaServers } from '$lib/server/fleet/beta.js';
|
||||
import { getBeta, listBetaServers, listBetaScripts } from '$lib/server/fleet/beta.js';
|
||||
import { getScript, getVersion } from '$lib/server/fleet/scripts.js';
|
||||
|
||||
function parseId(raw: string): number | null {
|
||||
@@ -13,9 +13,19 @@ export async function GET({ params }: { params: { id: string } }) {
|
||||
const beta = getBeta(id);
|
||||
if (!beta) return json({ ok: false, error: 'not found' }, { status: 404 });
|
||||
|
||||
const script = getScript(beta.script_id);
|
||||
const version = getVersion(beta.script_version_id);
|
||||
const scripts = listBetaScripts(id).map((bs) => {
|
||||
const script = getScript(bs.script_id);
|
||||
const version = getVersion(bs.script_version_id);
|
||||
return {
|
||||
id: bs.script_id,
|
||||
name: script?.name ?? '(deleted)',
|
||||
target_rel_path: script?.target_rel_path ?? '',
|
||||
version: version
|
||||
? { id: version.id, version: version.version, sha256: version.sha256 }
|
||||
: null
|
||||
};
|
||||
});
|
||||
const servers = listBetaServers(id);
|
||||
|
||||
return json({ beta, script, version, servers });
|
||||
return json({ beta, scripts, servers });
|
||||
}
|
||||
|
||||
@@ -57,8 +57,35 @@ export async function GET({ url }: { url: URL }) {
|
||||
grouped.set(s.deployment_id, arr);
|
||||
}
|
||||
|
||||
const scriptRows = db()
|
||||
.prepare(
|
||||
`SELECT ds.deployment_id, ds.script_id, s.name AS script_name,
|
||||
sv.version AS script_version, pv.version AS prior_version
|
||||
FROM deployment_scripts ds
|
||||
LEFT JOIN scripts s ON s.id = ds.script_id
|
||||
LEFT JOIN script_versions sv ON sv.id = ds.script_version_id
|
||||
LEFT JOIN script_versions pv ON pv.id = ds.prior_version_id`
|
||||
)
|
||||
.all() as Array<{
|
||||
deployment_id: string;
|
||||
script_id: number;
|
||||
script_name: string | null;
|
||||
script_version: number | null;
|
||||
prior_version: number | null;
|
||||
}>;
|
||||
const scriptsByDep = new Map<string, typeof scriptRows>();
|
||||
for (const s of scriptRows) {
|
||||
const arr = scriptsByDep.get(s.deployment_id) ?? [];
|
||||
arr.push(s);
|
||||
scriptsByDep.set(s.deployment_id, arr);
|
||||
}
|
||||
|
||||
const rows = deployments
|
||||
.map((d) => ({ ...d, servers: grouped.get(d.id) ?? [] }))
|
||||
.map((d) => ({
|
||||
...d,
|
||||
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));
|
||||
|
||||
return json({ deployments: rows });
|
||||
|
||||
@@ -24,5 +24,19 @@ export async function GET({ params }: { params: { id: string } }) {
|
||||
)
|
||||
.all(params.id);
|
||||
|
||||
return json({ deployment: dep, servers, files });
|
||||
const scripts = db()
|
||||
.prepare(
|
||||
`SELECT ds.script_id, s.name AS script_name, s.target_rel_path,
|
||||
ds.script_version_id, sv.version AS script_version,
|
||||
ds.prior_version_id, pv.version AS prior_version
|
||||
FROM deployment_scripts ds
|
||||
LEFT JOIN scripts s ON s.id = ds.script_id
|
||||
LEFT JOIN script_versions sv ON sv.id = ds.script_version_id
|
||||
LEFT JOIN script_versions pv ON pv.id = ds.prior_version_id
|
||||
WHERE ds.deployment_id = ?
|
||||
ORDER BY ds.script_id`
|
||||
)
|
||||
.all(params.id);
|
||||
|
||||
return json({ deployment: dep, servers, files, scripts });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user