Defer promotion snapshots to campaign activation
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
sha256_before: string | null; sha256_after: string | null;
|
||||
size_before: number | null; size_after: number | null;
|
||||
apply_state: 'pending' | 'applying' | 'applied' | 'cancelled';
|
||||
snapshot_pending: number;
|
||||
}
|
||||
interface ServerRow {
|
||||
deployment_id: string; server: string; server_deleted_at?: string | null; files_changed: number;
|
||||
@@ -97,7 +98,7 @@
|
||||
diffOpen = true; diffLoading = true; diffError = ''; openFile = null;
|
||||
try {
|
||||
const response = await fetch('/api/campaigns/' + id + '/file/' + f.id);
|
||||
if (!response.ok) throw new Error(response.status === 410 ? 'File contents expired under the retention policy.' : 'Could not load this file comparison. Close and select it again to retry.');
|
||||
if (!response.ok) throw new Error(response.status === 410 ? 'File contents expired under the retention policy.' : response.status === 409 ? 'The rollback snapshot is not available yet. Refresh after activation to compare files.' : 'Could not load this file comparison. Close and select it again to retry.');
|
||||
const body = await response.json();
|
||||
if (id === $page.params.id && current === diffRequest) openFile = {id:f.id, ...body};
|
||||
} catch (error) { if (id === $page.params.id && current === diffRequest) diffError = (error as Error).message; }
|
||||
@@ -144,7 +145,7 @@
|
||||
|
||||
<section class="outcome" aria-label="Campaign outcome">
|
||||
<h2>{completed} / {detail.servers.length} servers activated{unresolved ? ` · ${unresolved} unresolved` : ''}{withdrawn ? ` · ${withdrawn} withdrawn` : ''}{deletedIncomplete ? ` · ${deletedIncomplete} deleted before activation` : ''}</h2>
|
||||
<p>{detail.watchdogIncidentId ? 'Maintenance repairs drift by deleting the existing instance files and rebuilding with the latest promoted setup after verifying a safe server state.' : 'File changes wait for an empty server and restart capacity. They are applied immediately before restart, then server health is verified.'}</p>
|
||||
<p>{detail.watchdogIncidentId ? 'Maintenance repairs drift by deleting the existing instance files and rebuilding with the latest promoted setup after verifying a safe server state.' : 'File changes wait for an empty server and restart capacity. The campaign captures rollback snapshots immediately before applying files, then restarts the server and verifies health. Tested servers keep their original pre-beta snapshots.'}</p>
|
||||
{#if unresolved || deletedIncomplete}<p>Review the recorded results below.{#if deletedIncomplete} Deleted servers retain their last recorded progress.{/if}{#if unresolved} Diagnose connectivity or inspect startup logs from the affected row.{/if}</p>
|
||||
{:else if withdrawn}<p>Withdrawn changes will not be activated by this campaign.</p>
|
||||
{:else}<p>Every recorded server completed activation.</p>{/if}
|
||||
@@ -211,8 +212,9 @@
|
||||
<h3><HistoricalServerIdentity name={srv} deletedAt={detail.servers.find(server => server.server === srv)?.server_deleted_at} /></h3>
|
||||
<div class="file-rows">
|
||||
{#each files as f (f.id)}
|
||||
<button class="file-row" disabled={detail.fileContentsExpired} onclick={() => loadDiff(f)}>
|
||||
<Badge variant={verbVariant(f.verb)} size="sm" uppercase>{f.verb}</Badge>
|
||||
<button class="file-row" disabled={detail.fileContentsExpired || !!f.snapshot_pending} onclick={() => loadDiff(f)}>
|
||||
{#if f.snapshot_pending}<Badge variant="neutral" size="sm">{f.apply_state === 'cancelled' ? 'Snapshot not captured' : 'Snapshot pending'}</Badge>
|
||||
{:else}<Badge variant={verbVariant(f.verb)} size="sm" uppercase>{f.verb}</Badge>{/if}
|
||||
{#if f.apply_state !== 'applied'}<Badge variant="neutral" size="sm">{f.apply_state === 'pending' ? 'Queued' : f.apply_state === 'applying' ? 'Needs inspection' : 'Cancelled'}</Badge>{/if}
|
||||
<span class="path">{f.rel_path}</span>
|
||||
<span class="sizes">
|
||||
@@ -228,7 +230,7 @@
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<OperationHistory steps={campaignFlow(detail.servers, Boolean(detail.deployment.finished_at))} events={detail.events} active={detail.servers.some(s => !s.server_deleted_at && (s.restart_state === 'pending' || s.restart_state === 'failed'))} />
|
||||
<OperationHistory steps={campaignFlow(detail.servers, Boolean(detail.deployment.finished_at), detail.files)} events={detail.events} active={detail.servers.some(s => !s.server_deleted_at && (s.restart_state === 'pending' || s.restart_state === 'failed'))} />
|
||||
<Dialog bind:open={diffOpen} title={openFile?.relPath ?? 'File comparison'} wide>
|
||||
{#if diffError}<p class="ui-error" role="alert">{diffError}</p><Button onclick={() => { if (retryFile) void loadDiff(retryFile); }}>Retry comparison</Button>
|
||||
{:else if diffLoading}<EmptyState title="Loading comparison…" />
|
||||
|
||||
Reference in New Issue
Block a user