fix(workflow): forward the tsconfig pin only in the unbuilt worker

This commit is contained in:
Huanqi Cao
2026-08-12 15:11:05 +08:00
committed by Chinesezjc
parent 095fde4ffd
commit 7593842ccf
2 changed files with 21 additions and 16 deletions

View File

@@ -38,18 +38,21 @@ interface ChildRecord {
* The unbuilt shape additionally forwards `TSX_TSCONFIG_PATH` for path * The unbuilt shape additionally forwards `TSX_TSCONFIG_PATH` for path
* resolution. * resolution.
* @param platform - host platform; overridable so tests exercise both peer arms. * @param platform - host platform; overridable so tests exercise both peer arms.
* @param tsconfigPath - the tsconfig pin to forward; only the unbuilt caller
* passes one, so the built worker never observes the host's pin.
* @returns the scrubbed worker environment object. * @returns the scrubbed worker environment object.
*/ */
export function workerSpawnEnv(platform: NodeJS.Platform = process.platform): NodeJS.ProcessEnv { export function workerSpawnEnv(
platform: NodeJS.Platform = process.platform,
tsconfigPath: string | undefined = undefined,
): NodeJS.ProcessEnv {
const env: NodeJS.ProcessEnv = {} const env: NodeJS.ProcessEnv = {}
if (platform === 'win32') { if (platform === 'win32') {
const tmp = tmpdir() const tmp = tmpdir()
env.TMP = tmp env.TMP = tmp
env.TEMP = tmp env.TEMP = tmp
} }
if (process.env.TSX_TSCONFIG_PATH !== undefined) { if (tsconfigPath !== undefined) env.TSX_TSCONFIG_PATH = tsconfigPath
env.TSX_TSCONFIG_PATH = process.env.TSX_TSCONFIG_PATH
}
return env return env
} }
@@ -81,7 +84,7 @@ function resolveWorkerSpawn(init: WorkerInit): { entry: string | URL; options: W
entry: new URL(`data:text/javascript,${encodeURIComponent(bootstrap)}`), entry: new URL(`data:text/javascript,${encodeURIComponent(bootstrap)}`),
options: { options: {
workerData: init, workerData: init,
env: workerSpawnEnv(), env: workerSpawnEnv(undefined, process.env.TSX_TSCONFIG_PATH),
execArgv: [], execArgv: [],
}, },
} }

View File

@@ -570,6 +570,11 @@ describe('dsh-workflow-worker-thread', () => {
// inside the worker resolves instead of degrading to a cwd-relative // inside the worker resolves instead of degrading to a cwd-relative
// `undefined\temp` (tsx writes its transform cache there). // `undefined\temp` (tsx writes its transform cache there).
process.env.WORKFLOW_ENV_CANARY = 'leak me' process.env.WORKFLOW_ENV_CANARY = 'leak me'
// The unbuilt worker forwards TSX_TSCONFIG_PATH (a path pin, not a
// credential); clear it so this test observes the empty ambient case
// regardless of the parent's environment.
const tsconfigPath = process.env.TSX_TSCONFIG_PATH
delete process.env.TSX_TSCONFIG_PATH
try { try {
const result = await run(ctx, parent, scripted(` const result = await run(ctx, parent, scripted(`
const proc = ${ESCAPE} const proc = ${ESCAPE}
@@ -579,6 +584,8 @@ describe('dsh-workflow-worker-thread', () => {
const expectedKeys = process.platform === 'win32' ? ['TEMP', 'TMP'] : [] const expectedKeys = process.platform === 'win32' ? ['TEMP', 'TMP'] : []
expect(result.value).toEqual({ canary: null, keys: expectedKeys }) expect(result.value).toEqual({ canary: null, keys: expectedKeys })
} finally { } finally {
if (tsconfigPath === undefined) delete process.env.TSX_TSCONFIG_PATH
else process.env.TSX_TSCONFIG_PATH = tsconfigPath
delete process.env.WORKFLOW_ENV_CANARY delete process.env.WORKFLOW_ENV_CANARY
} }
}) })
@@ -591,17 +598,12 @@ describe('dsh-workflow-worker-thread', () => {
it('workerSpawnEnv forwards TSX_TSCONFIG_PATH when the snapshot harness pins it', () => { it('workerSpawnEnv forwards TSX_TSCONFIG_PATH when the snapshot harness pins it', () => {
const tsconfig = fileURLToPath(new URL('../../../../tsconfig.json', import.meta.url)) const tsconfig = fileURLToPath(new URL('../../../../tsconfig.json', import.meta.url))
vi.stubEnv('TSX_TSCONFIG_PATH', tsconfig) expect(workerSpawnEnv('linux', tsconfig)).toEqual({ TSX_TSCONFIG_PATH: tsconfig })
try { expect(workerSpawnEnv('win32', tsconfig)).toEqual({
expect(workerSpawnEnv('linux')).toEqual({ TSX_TSCONFIG_PATH: tsconfig }) TMP: tmpdir(),
expect(workerSpawnEnv('win32')).toEqual({ TEMP: tmpdir(),
TMP: tmpdir(), TSX_TSCONFIG_PATH: tsconfig,
TEMP: tmpdir(), })
TSX_TSCONFIG_PATH: tsconfig,
})
} finally {
vi.unstubAllEnvs()
}
}) })
it('the unbuilt worker forwards exactly TSX_TSCONFIG_PATH through the scrub: the paths-map pin survives, secrets do not', async () => { it('the unbuilt worker forwards exactly TSX_TSCONFIG_PATH through the scrub: the paths-map pin survives, secrets do not', async () => {