mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 16:02:15 +00:00
test(orcad): skip the live-terminal runtime hand-over across a protocol bump (#24429)
* test(orcad): skip the Bun-to-Node live-terminal hand-over across a protocol bump The last Bun orcad's daemon reports protocol 38 forever, so asserting the adopted daemon matches this checkout's PROTOCOL_VERSION failed every bump. Ask the Bun slot's daemon for its protocol once, run the hand-over when it matches, and skip with the two versions named when it does not: a daemon at another protocol is never adopted across an update. * test(orcad): clean up the Bun protocol probe even when its launch fails The probe's cleanup ran only after a successful launch, so a launch that timed out or threw left its orcad and daemon running. One finally now stops the orcad, kills what it launched, and kills any daemon named by a pid file in the probe's data root.
This commit is contained in:
@@ -125,8 +125,8 @@ jobs:
|
||||
pnpm build:orcad-prebuilds --smoke
|
||||
- run: pnpm build:orcad
|
||||
# Design D7 upgrade and rollback: the last Bun orcad, built from a main commit that shipped
|
||||
# it at this PROTOCOL_VERSION, beside this checkout's Node slot. Same lockfile, so its build
|
||||
# reuses this checkout's node_modules.
|
||||
# it, beside this checkout's Node slot; the live-terminal hand-over skips once PROTOCOL_VERSION
|
||||
# moves past the Bun daemon's. Same lockfile, so its build reuses this checkout's node_modules.
|
||||
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||
if: runner.os == 'Linux'
|
||||
with:
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
orcadNodeRuntimeRelativePath
|
||||
} from '../../shared/orcad-artifacts'
|
||||
import { removeTreeSync } from '../../shared/windows-transient-lock-removal'
|
||||
import { readDaemonPidRecord } from '../daemon/daemon-endpoint-incarnation'
|
||||
import { PROTOCOL_VERSION } from '../daemon/types'
|
||||
import type { ServeReadiness } from '../server/serve-readiness'
|
||||
import {
|
||||
@@ -91,6 +92,7 @@ const missing = [
|
||||
let root = ''
|
||||
let client = ''
|
||||
let backupDriver = ''
|
||||
let bunProtocolVersion = 0
|
||||
const launched = new Set<number>()
|
||||
|
||||
/** Without Vitest's markers: daemon-entry.js does not start its server under VITEST. */
|
||||
@@ -254,6 +256,40 @@ async function backUpProfile(slot: Slot, runtime: string, userDataDir: string):
|
||||
expect(JSON.parse(result.stdout.trim().split('\n').at(-1) ?? '')).toEqual({ ok: true })
|
||||
}
|
||||
|
||||
function killLaunched(): void {
|
||||
for (const pid of launched) {
|
||||
try {
|
||||
process.kill(pid, 'SIGKILL')
|
||||
} catch {}
|
||||
}
|
||||
launched.clear()
|
||||
}
|
||||
|
||||
/** The protocol the Bun slot's own daemon reports, read from a throwaway launch. */
|
||||
async function probeBunDaemonProtocol(): Promise<number> {
|
||||
const probeRoot = mkdtempSync(join(root, 'bun-probe-'))
|
||||
const slot = installSlot(probeRoot, 'Bun', bunSlotSource!)
|
||||
const userDataDir = join(probeRoot, 'data')
|
||||
try {
|
||||
const daemon = (await launch(slot, userDataDir)).health!.terminalDaemon
|
||||
expect(daemon).toMatchObject({ state: 'live', protocolVersion: expect.any(Number) })
|
||||
return daemon.protocolVersion!
|
||||
} finally {
|
||||
await stop(slot).catch(() => {})
|
||||
killLaunched()
|
||||
// Even after a failed launch: the daemon outlives orcad, and only its pid file names it.
|
||||
const daemonDir = join(userDataDir, 'daemon')
|
||||
for (const name of existsSync(daemonDir) ? readdirSync(daemonDir) : []) {
|
||||
const pid = /^daemon-v\d+\.pid$/.test(name)
|
||||
? readDaemonPidRecord(join(daemonDir, name))?.pid
|
||||
: undefined
|
||||
if (pid && isAlive(pid)) {
|
||||
process.kill(pid, 'SIGKILL')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Windows has no orcad launch path (POSIX-only, orcad-remote-host-support.ts), so no inputs.
|
||||
const skip = skipForMissingInputs('cross-runtime', posix ? missing : [])
|
||||
|
||||
@@ -321,27 +357,28 @@ worker.on('error', (error) => { console.error(error); process.exitCode = 1 })
|
||||
outfile: client,
|
||||
logLevel: 'silent'
|
||||
})
|
||||
})
|
||||
bunProtocolVersion = await probeBunDaemonProtocol()
|
||||
}, 180_000)
|
||||
|
||||
afterEach(() => {
|
||||
for (const pid of launched) {
|
||||
try {
|
||||
process.kill(pid, 'SIGKILL')
|
||||
} catch {}
|
||||
}
|
||||
launched.clear()
|
||||
})
|
||||
afterEach(killLaunched)
|
||||
|
||||
afterAll(() => {
|
||||
removeTreeSync(root)
|
||||
})
|
||||
|
||||
it.each([
|
||||
it.for([
|
||||
['Bun', 'Node'],
|
||||
['Node', 'Bun']
|
||||
] as const)(
|
||||
'%s orcad hands its daemon and profile to the %s orcad',
|
||||
async (from: Runtime, to: Runtime) => {
|
||||
{ timeout: 240_000 },
|
||||
async ([from, to], context) => {
|
||||
// A daemon at another protocol is never adopted across an update, so there is no hand-over.
|
||||
if (bunProtocolVersion !== PROTOCOL_VERSION) {
|
||||
context.skip(
|
||||
`the Bun orcad's daemon speaks protocol ${bunProtocolVersion}, this checkout ${PROTOCOL_VERSION}`
|
||||
)
|
||||
}
|
||||
const caseRoot = mkdtempSync(join(root, `${from}-${to}-`))
|
||||
const userDataDir = join(caseRoot, 'data')
|
||||
const { slots, nodeRuntime } = installSlots(caseRoot)
|
||||
@@ -426,7 +463,6 @@ worker.on('error', (error) => { console.error(error); process.exitCode = 1 })
|
||||
process.kill(daemonPid, 'SIGKILL')
|
||||
}
|
||||
}
|
||||
},
|
||||
240_000
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user