merge PR 20045 ssh-relay-orphan-sweep-visibility

This commit is contained in:
Neil
2026-09-11 22:26:56 -07:00
2 changed files with 40 additions and 2 deletions
@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { beforeEach, describe, expect, it, vi, type MockInstance } from 'vitest'
const execCommand = vi.fn()
vi.mock('./ssh-relay-deploy-helpers', () => ({
@@ -43,6 +43,13 @@ function issuedCommands(): string[] {
return execCommand.mock.calls.map((call) => String(call[1]))
}
/** The `beforeEach` spy is reinstalled, not reset, so its calls survive the previous test. */
function warnSpy(): MockInstance<typeof console.warn> {
const spy = vi.spyOn(console, 'warn')
spy.mockClear()
return spy
}
beforeEach(() => {
execCommand.mockReset()
vi.spyOn(console, 'warn').mockImplementation(() => {})
@@ -157,8 +164,21 @@ describe('sweepSupersededRelayEndpoints', () => {
await expect(sweepSupersededRelayEndpoints(CONN, HOST, SWEEP)).resolves.toEqual([])
})
it('records the abandoned pass when the listing fails, so it reads apart from an empty host', async () => {
const warn = warnSpy()
execCommand.mockRejectedValueOnce(new Error('exec failed'))
await sweepSupersededRelayEndpoints(CONN, HOST, SWEEP)
expect(warn.mock.calls.flat().join('\n')).toContain('no pass ran: exec failed')
})
it('does not run against Windows hosts, whose endpoints are named pipes', async () => {
const warn = warnSpy()
await expect(sweepSupersededRelayEndpoints(CONN, WINDOWS_HOST, SWEEP)).resolves.toEqual([])
expect(execCommand).not.toHaveBeenCalled()
// The skip has to leave a trace: a Windows orphan is never listed and never reclaimed, and
// an empty return is otherwise indistinguishable from a host that had nothing to sweep.
const logged = warn.mock.calls.flat().join('\n')
expect(logged).toContain('Superseded relay sweep did not run')
expect(logged).toContain(CURRENT_DIR)
})
})
+19 -1
View File
@@ -118,6 +118,17 @@ export async function sweepSupersededRelayEndpoints(
options: SupersededRelaySweepOptions
): Promise<SupersededRelayFinding[]> {
if (isWindowsRemoteHost(hostPlatform)) {
// No pass runs here: a Windows endpoint is a named pipe with no inode to stat, so the
// `$HOME` glob cannot see it, and `probeRelayEndpointIncumbent` answers `unverifiable` for
// every Windows path anyway — nothing on this host could be classified, let alone reaped.
// The population is real all the same (`relayEndpointForHost` hashes the version dir into
// the pipe name, so an update strands the incumbent exactly as it does on POSIX), and with
// `--grace-time 0` it keeps its PTYs forever. Returning silently was the whole bug: this
// sweep exists to make that population visible, and on Windows it made it invisible.
console.warn(
`[ssh-relay] Superseded relay sweep did not run (Windows named-pipe endpoints are not enumerated); ` +
`orphans from earlier builds are neither listed nor reclaimed: current=${options.currentRelayDir}`
)
return []
}
let listing: string
@@ -126,7 +137,14 @@ export async function sweepSupersededRelayEndpoints(
wrapCommand: true,
signal: options.signal
})
} catch {
} catch (err) {
// Same reason the Windows arm logs: an abandoned pass and an empty host are the same return
// value, and only the log tells them apart.
console.warn(
`[ssh-relay] Superseded relay listing failed; no pass ran: ${
err instanceof Error ? err.message : String(err)
}`
)
return []
}
const sockPaths = listing