feat: add provisioning lifecycle actions

Rename Deployments to Provisioning with compatible redirects and APIs. Add durable Start, Restart, Stop, and Rebuild operations alongside Create and Destroy; rebuild wipes the instance and recreates it in the same slot and port.

Add lifecycle, migration, recovery, and Komodo command tests. Type checks and production build pass; the full suite retains a telemetry assertion failure reproduced on the unchanged branch.

Refs #39
This commit is contained in:
2026-09-27 14:20:04 -04:00
parent 0b0e5b5bdb
commit cfed584614
42 changed files with 886 additions and 108 deletions
+6 -1
View File
@@ -13,6 +13,10 @@
import ListFooter from '$ui/components/primitives/ListFooter.svelte';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import LifecycleDialog from '$ui/components/LifecycleDialog.svelte';
import { runtimeActions, actionLabels, type RuntimeAction } from '$lib/provisioning.js';
let lifecycleOpen = $state(false);
let lifecycleAction = $state<RuntimeAction>('start');
import DestroyServerModal from '$ui/components/DestroyServerModal.svelte';
import { telemetryByServer, uiNow } from '$ui/stores/servers.js';
import type { RosterPlayer, Health, RconEndpoint, RconFailure } from '$ui/stores/servers.js';
@@ -225,6 +229,7 @@
</script>
<svelte:head><title>{serverTitle(name)} · {activeTab.charAt(0).toUpperCase() + activeTab.slice(1)} · Electric Cherry</title></svelte:head>
<LifecycleDialog bind:open={lifecycleOpen} initialServer={name} initialAction={lifecycleAction} />
<DestroyServerModal bind:open={destroyOpen} {name} players={effectivePlayers} />
{#if server}
@@ -236,7 +241,7 @@
<Breadcrumbs items={[{ label: 'Fleet', href: '/' }, { label: serverTitle(name) }]} />
{/snippet}
{#snippet actions()}
<details class="server-actions"><summary>Server actions</summary><Button variant="danger" onclick={() => destroyOpen = true}>Queue server removal</Button></details>
<details class="server-actions"><summary>Server actions</summary>{#each runtimeActions as action}<Button onclick={() => { lifecycleAction = action; lifecycleOpen = true; }}>{actionLabels[action]}</Button>{/each}<Button variant="danger" onclick={() => destroyOpen = true}>Queue server removal</Button></details>
{/snippet}
</SectionHeader>