Beta #{id} | Electric Cherry {#if loadError}{/if} {#if loading} {:else if !beta && !loadError} {:else if beta}
{#snippet crumbs()}{/snippet} {#snippet actions()}{/snippet}

{closed ? beta.state === 'promoted' ? 'Version promoted' : 'Beta rolled back' : `${passed} / ${servers.length} servers passed`}

{#if test}{coverageSummary(test.plan)}{/if}

{nextAction}

{#if test?.reason}

{test.reason}

{/if}
Started {#if deadline && !closed}Ends · {deadlineText}{/if} {#if beta.closed_at}Finished {$timeFormat.dateTime(beta.closed_at)}{/if}
{#if !closed && test}

Waiting for empty servers uses this window. Pausing or retrying does not extend the deadline.

{/if}
{#if !closed}{/if} {#if closed}{/if} {#if promotion}{/if}
{#if promotion}

{promotion.pending} servers awaiting activation · {promotion.failed} need attention. Promoting a version does not mean it is already running everywhere.

{/if} {#if flash}{/if} {#if success}

{success}

{/if}
{#if !closed && waiting.length}

Outstanding conditions

{#each waiting as server}

{server.error ?? (server.server_deleted_at ? 'This server was deleted. Recorded progress is retained.' : outstanding(server.server))}

{#if server.error && !server.server_deleted_at}Diagnose{:else if test}View checks{/if}
{/each}
{/if} {#if test}
server.error?.startsWith('deploy:')) ? 'Deployment was incomplete. Roll back before opening a fresh beta.' : undefined} onUpdate={load} />
{/if}
Files and versions ({scripts.length})
{#each scripts as file}
{file.name}{artifactVersionLabel(file.version)}{file.target_rel_path}{file.version?.sha256.slice(0,12)}
{/each}
Deployment progress ({servers.length} servers)
{#each ranked as server}

Files {server.deployed_at ? 'installed' : 'pending'} · Restart {server.restarted_at ? 'submitted' : 'pending'}{#if beta.wait_for_health} · Health {server.healthy_at ? 'verified' : 'pending'}{/if}{#if beta.wait_for_match} · Match {server.match_seen_at ? 'observed' : 'pending'}{/if}

{#if server.provisioning_id}View provisioning{/if}{#if server.error}

{server.error}

{/if}{#if server.stage === 'failed' && !server.server_deleted_at && !test && !closed}{/if}
{/each}
{/if} {#if acting === 'preview'}

Preparing promotion impact…

{/if} {#if reviewError}{/if} {#if preview}

{preview.servers.filter(server => server.tested).length} tested servers and {preview.servers.filter(server => !server.tested).length} additional eligible servers.

Files are installed when you confirm. Tested servers have already restarted. Additional servers restart when empty, then their health is checked. Eligibility is determined by each file's current scope.

Reviewed {$timeFormat.dateTime(preview.createdAt)}. If targets, versions, or composed settings change, you must review again.

{#each preview.blockers as blocker}{/each}
{#each preview.files as file}
{file.name} · {artifactVersionLabel(file)} · {file.servers.length} servers

{file.path} · {file.scope} · SHA {file.sha256.slice(0,12)}

    {#each file.servers as name}
  • {preview.servers.find(server => server.name === name)?.tested ? 'Already tested' : 'Additional target · restart when empty'}
  • {/each}
{/each}
{#if preview.configWrites.length}
Composed configuration files ({preview.configWrites.length}){#each preview.configWrites as write}

{write.server} · {write.path} · {write.sha256?.slice(0,12) ?? write.error}

{/each}
{/if} {:else if acting !== 'preview'}{/if} {#snippet actions()}{#if preview}{/if}{/snippet}