import { spawnSync } from 'node:child_process' import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { dirname, join, resolve } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' const root = resolve(import.meta.dirname, '..') const script = resolve(root, 'scripts/build-exe-for-python-sdk.ts') const temporaryDirectories: string[] = [] afterEach(() => { for (const directory of temporaryDirectories.splice(0)) { rmSync(directory, { recursive: true, force: true }) } }) function run(env: NodeJS.ProcessEnv, ...args: string[]) { return spawnSync(process.execPath, ['--import', 'tsx/esm', script, ...args], { cwd: root, encoding: 'utf8', env: isolatedPnpmEnvironment(env), }) } describe('Python runtime executable builder CLI', () => { it('runs pnpm through its JavaScript entrypoint without a command shell', () => { const result = run( { npm_execpath: 'C:\\tools\\pnpm.cjs' }, '--skip-build', '--dry-run', '--targets=node24-macos-arm64', ) expect(result.status).toBe(0) expect(result.stdout).toContain(`${process.execPath} C:\\tools\\pnpm.cjs run verify-runtime-closure`) expect(result.stdout).toContain(`${process.execPath} C:\\tools\\pnpm.cjs --filter dsh-python-runtime-closure deploy`) expect(result.stdout).toContain(`${process.execPath} C:\\tools\\pnpm.cjs dlx @yao-pkg/pkg@6.21.0`) expect(result.stdout).not.toMatch(/pnpm\.cmd/i) }) it('resolves the pnpm package behind a Windows command shim', () => { const setup = mkdtempSync(join(tmpdir(), 'dsh-pnpm-home-')) temporaryDirectories.push(setup) const home = join(setup, 'node_modules', '.bin') const entrypoint = join(setup, 'node_modules', 'pnpm', 'bin', 'pnpm.mjs') mkdirSync(home, { recursive: true }) mkdirSync(dirname(entrypoint), { recursive: true }) writeFileSync(entrypoint, '') const result = run( { npm_execpath: 'C:\\tools\\pnpm.cmd', PNPM_HOME: home }, '--skip-build', '--dry-run', '--targets=node24-macos-arm64', ) expect(result.status).toBe(0) expect(result.stdout).toContain(`${process.execPath} ${entrypoint} run verify-runtime-closure`) expect(result.stdout).not.toMatch(/pnpm\.cmd/i) }) it('rejects a Windows arm64 product before any build step', () => { const result = run( { npm_execpath: 'C:\\tools\\pnpm.cjs' }, '--skip-build', '--dry-run', '--targets=node24-win-arm64', ) expect(result.status).not.toBe(0) expect(result.stderr).toContain('Windows supports x64 only') expect(result.stdout).toBe('') }) }) function isolatedPnpmEnvironment(overrides: NodeJS.ProcessEnv): NodeJS.ProcessEnv { const environment = Object.fromEntries( Object.entries(process.env).filter(([key]) => !['npm_execpath', 'pnpm_home'].includes(key.toLowerCase())), ) return { ...environment, ...overrides } }