Files
orca/src/shared/managed-orcad-ssh-owner.ts
T
OrcaWinandm4air bcc50483bb fix(vm): a recipe VM's SSH root runs on a managed Orca server (#27366)
* fix(vm): a recipe VM's SSH root runs on a managed Orca server

A recipe VM's hidden SSH target was counted as owned by another runtime, so
every connect refused to deploy a managed server and fell back to the relay.
Its runtime owner only records when the VM is created and destroyed, so it no
longer blocks the deploy. The VM's workspace then lives on that server: the
server adopts the provisioned root as its main worktree, and removing the
project destroys the VM and forgets its server.

* fix(vm): release the server of a relay-era VM that converted on connect

* fix(vm): resume reconnects an SSH VM's server; removal stays on its own VM

* fix(vm): removal and the remove dialog find a VM's server before the catalog loads

* fix(vm): a catalog refresh failure never blocks a VM create

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-10 21:39:23 -07:00

36 lines
1.4 KiB
TypeScript

import type { SshTarget } from './ssh-types'
/** The runtime id phase-3 builds wrote into `owner` before the fence moved to `orcadFence`. */
const LEGACY_MANAGED_ORCAD_RUNTIME_ID_PREFIX = 'managed-orcad:'
type SshTargetOwner = NonNullable<SshTarget['owner']>
/** The managed Orca server this host serves, or null for a direct SSH host. */
export function getManagedOrcadFenceEnvironmentId(
target: Pick<SshTarget, 'orcadFence'> | undefined
): string | null {
return target?.orcadFence?.environmentId || null
}
/** Reads a legacy `owner` fence, only to migrate it to `orcadFence` on load. */
export function getLegacyManagedOrcadOwnerEnvironmentId(
owner: SshTargetOwner | undefined
): string | null {
if (!owner?.runtimeId.startsWith(LEGACY_MANAGED_ORCAD_RUNTIME_ID_PREFIX)) {
return null
}
return owner.runtimeId.slice(LEGACY_MANAGED_ORCAD_RUNTIME_ID_PREFIX.length) || null
}
export function isEphemeralRuntimeSshOwner(owner: SshTargetOwner | undefined): boolean {
return (
owner?.type === 'on-demand-runtime' && getLegacyManagedOrcadOwnerEnvironmentId(owner) === null
)
}
/** Every VM a recipe makes shares its label, so the runtime id keeps their server names unique. */
export function managedOrcadServerName(target: Pick<SshTarget, 'label' | 'owner'>): string {
const runtimeId = isEphemeralRuntimeSshOwner(target.owner) ? target.owner?.runtimeId : undefined
return runtimeId ? `${target.label} VM ${runtimeId.slice(-8)}` : target.label
}