test(git): verify native Windows exited-child termination guard

This commit is contained in:
Neil
2026-09-14 04:16:01 -07:00
parent ded8c7c26d
commit fcc4bbac99
2 changed files with 49 additions and 0 deletions
@@ -0,0 +1,22 @@
name: Git command termination runtime
on:
pull_request:
paths:
- 'src/main/git/command-runner/spawned-command-tree-kill*'
- '.github/workflows/git-command-termination-runtime.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
windows-exit:
runs-on: windows-latest
timeout-minutes: 20
env:
ORCA_BACKGROUND_LAUNCH: '1'
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: ./.github/actions/install-node-dependencies
- name: Verify exited native child does not trigger taskkill
run: node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts src/main/git/command-runner/spawned-command-tree-kill.test.ts
@@ -1,4 +1,6 @@
import { ChildProcess } from 'node:child_process'
import { once } from 'node:events'
import { spawnProcess } from '../../../shared/child-process/run-process'
import type * as NodeChildProcess from 'node:child_process'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
@@ -92,4 +94,29 @@ describe('Git command tree termination', () => {
expect(child.kill).toHaveBeenCalledOnce()
expect(spawnMock).not.toHaveBeenCalled()
})
it.skipIf(originalPlatform !== 'win32').each([0, 128])(
'does not taskkill an actual native Windows child after exit %i',
async (exitCode) => {
const original = await vi.importActual<typeof NodeChildProcess>('node:child_process')
spawnMock.mockImplementation((program, args, options) => {
if (program !== process.execPath) {
throw new Error('Unexpected external process in native exit probe')
}
return original.spawn(program, args, options)
})
const child = spawnProcess({
program: process.execPath,
args: ['-e', `process.exit(${exitCode})`]
})
const closed = once(child, 'close')
await once(child, 'exit')
expect(child.exitCode).toBe(exitCode)
expect(child.pid).toBeGreaterThan(0)
spawnMock.mockClear()
await killSpawnedCommandTree(child)
expect(spawnMock).not.toHaveBeenCalled()
expect(admitMock).not.toHaveBeenCalled()
await closed
}
)
})