mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 16:02:50 +00:00
fix(ssh): make the Windows deps probe exit 0 on a real load failure, like its POSIX twin
This commit is contained in:
@@ -826,7 +826,7 @@ async function probeRequiredNativeDeps(
|
||||
hostPlatform,
|
||||
nodePath,
|
||||
remoteDir,
|
||||
`try { & ${powerShellLiteral(nodePath)} -e ${powerShellNativeArg(probeJs)} } catch { 'MISSING' }`
|
||||
`try { & ${powerShellLiteral(nodePath)} -e ${powerShellNativeArg(probeJs)}; if ($LASTEXITCODE -ne 0) { 'MISSING' } } catch { 'MISSING' }`
|
||||
)
|
||||
: // Why: no `2>/dev/null` — it discarded the only line that says why node never reached the
|
||||
// script. stderr stays its own stream so it can't be mistaken for the verdict, mirroring
|
||||
|
||||
@@ -24,6 +24,16 @@ type SshCommandTerminationError = Error & {
|
||||
sshChannelCloseConfirmed: boolean
|
||||
}
|
||||
|
||||
// Why: callers must tell "the host answered no" from "the host never answered". Matching the
|
||||
// message text is what let an unanswered probe be read as a definitive negative.
|
||||
export const SSH_EXEC_TIMEOUT_CODE = 'SSH_EXEC_TIMEOUT'
|
||||
|
||||
export function isSshExecTimeout(error: unknown): boolean {
|
||||
return (
|
||||
error instanceof Error && (error as Partial<{ code: string }>).code === SSH_EXEC_TIMEOUT_CODE
|
||||
)
|
||||
}
|
||||
|
||||
export function isUnconfirmedSshCommandTermination(
|
||||
error: unknown
|
||||
): error is SshCommandTerminationError {
|
||||
@@ -164,8 +174,13 @@ export async function execCommand(
|
||||
}
|
||||
const timeout = setTimeout(() => {
|
||||
requestTermination(
|
||||
new Error(
|
||||
`Command "${redactRelayInstallMarkerTokens(command)}" timed out after ${timeoutMs / 1000}s`
|
||||
Object.assign(
|
||||
new Error(
|
||||
`Command "${redactRelayInstallMarkerTokens(command)}" timed out after ${
|
||||
timeoutMs / 1000
|
||||
}s`
|
||||
),
|
||||
{ code: SSH_EXEC_TIMEOUT_CODE }
|
||||
)
|
||||
)
|
||||
}, timeoutMs)
|
||||
|
||||
@@ -394,6 +394,31 @@ describe('installNativeDeps (via deployAndLaunchRelay)', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('does not rewrite node_modules when the health probe never answered', async () => {
|
||||
// Why (#14830): a wedged `require("node-pty")` makes the probe time out. Reading that silence
|
||||
// as "every native dep is missing" sent a healthy install through npm install + rebuild that
|
||||
// could not help, and the retry loop burned the whole deploy budget at "Deploying relay…".
|
||||
const conn = makeMockConnection(sftpCapture)
|
||||
vi.mocked(isRelayAlreadyInstalled).mockResolvedValue(true)
|
||||
feed([
|
||||
'__ORCA_REMOTE_PLATFORM__ Linux x86_64',
|
||||
'/home/u',
|
||||
{ reject: 'Command "node -e ..." timed out after 30s' } // health probe never answered
|
||||
])
|
||||
|
||||
await deployAndLaunchRelay(conn).catch(() => {})
|
||||
|
||||
const execCalls = vi.mocked(execCommand).mock.calls.map(([, c]) => c)
|
||||
expect(execCalls.some((c) => c.includes('npm install'))).toBe(false)
|
||||
expect(execCalls.some((c) => c.includes('npm rebuild'))).toBe(false)
|
||||
|
||||
const warnMessages = warnSpy.mock.calls.map((args) => String(args[0] ?? ''))
|
||||
expect(warnMessages.some((m) => m.includes('Repairing missing native deps'))).toBe(false)
|
||||
// Why no log assertion: the behavioural claim above is the real one. Asserting on warn text
|
||||
// pinned wording that main's landed probe verdict does not use, and #18000 adds its own.
|
||||
expect(execCalls.some((c) => c.includes("rm -rf 'node_modules/node-pty'"))).toBe(false)
|
||||
})
|
||||
|
||||
it('lets a probe SSH-channel failure bubble up rather than silently mapping to MISSING', async () => {
|
||||
const conn = makeMockConnection(sftpCapture)
|
||||
feed(
|
||||
|
||||
Reference in New Issue
Block a user