Add configurable beta test plans and staged rollout

This commit is contained in:
2026-09-17 21:35:28 -04:00
parent 5b5266da3a
commit a50eae9d21
26 changed files with 1518 additions and 44 deletions
+8 -15
View File
@@ -1,4 +1,6 @@
<script lang="ts">
import BetaPlanBuilder from "$ui/components/BetaPlanBuilder.svelte";
import { defaultPlan, parseBetaPlan } from "$lib/beta-plan.js";
import { onMount, onDestroy } from 'svelte';
import { goto } from '$app/navigation';
import Card from '$ui/components/primitives/Card.svelte';
@@ -12,6 +14,7 @@
interface BetaListRow {
id: number;
state: 'running' | 'ready-promote' | 'promoted' | 'rolled-back';
testOutcome: string | null;
wait_for_health: number;
wait_for_match: number;
opened_at: string;
@@ -45,6 +48,7 @@
let nextKey = 0;
let picks = $state<Pick[]>([{ key: nextKey++, scriptId: null, versionId: null }]);
let pickedServers = $state<Set<string>>(new Set());
let testPlan = $state(defaultPlan());
let waitForHealth = $state(true);
let waitForMatch = $state(false);
let openingBeta = $state(false);
@@ -175,6 +179,7 @@
body: JSON.stringify({
scripts: picks.map((p) => ({ scriptId: p.scriptId!, scriptVersionId: p.versionId! })),
servers: [...pickedServers],
testPlan: parseBetaPlan(testPlan),
waitForHealth,
waitForMatch
})
@@ -185,7 +190,7 @@
return;
}
if (body.result) await goto(`/betas/${body.result.betaId}`);
} finally {
} catch (error) { flash = (error as Error).message; } finally {
openingBeta = false;
}
}
@@ -298,18 +303,7 @@
</div>
</Field>
<Field label="Options">
<div class="opts">
<label class="chk">
<input type="checkbox" bind:checked={waitForHealth} />
<span>Wait for server start healthy</span>
</label>
<label class="chk">
<input type="checkbox" bind:checked={waitForMatch} />
<span>Wait for server match</span>
</label>
</div>
</Field>
<BetaPlanBuilder bind:plan={testPlan} />
<div class="form-actions">
<Button
@@ -341,7 +335,7 @@
<a class="beta-row" href="/betas/{b.id}">
<span class="beta-id">#{b.id}</span>
<span class="beta-script">{summarizeScripts(b)}</span>
<Badge variant={betaStateVariant(b.state)} size="sm" uppercase>{b.state}</Badge>
<Badge variant={betaStateVariant(b.state)} size="sm" uppercase>{b.testOutcome && b.state === 'running' ? b.testOutcome : b.state}</Badge>
<span class="beta-servers">{b.servers.length} server{b.servers.length === 1 ? '' : 's'}</span>
</a>
{/each}
@@ -455,7 +449,6 @@
}
.chk input { accent-color: var(--accent-primary); cursor: pointer; }
.opts { display: flex; flex-wrap: wrap; gap: var(--space-6); }
.form-actions { display: flex; align-items: center; gap: var(--space-4); }
.flash { color: var(--state-danger); font-family: var(--font-mono); font-size: var(--text-xs); }