fix(scripts): run publint/tsc via node JS entry, not a shell .cmd shim
shell:true space-joins the executable and args UNESCAPED (Node DEP0190), so an absolute .cmd path breaks whenever the repo path contains spaces and `pnpm run hygiene` fails. Invoke publint's (`node_modules/publint/src/cli.js`) and tsc's (`node_modules/typescript/bin/tsc`) JS entry through process.execPath instead — no shell, extension-agnostic, identical on every platform, matching the pattern already used by doc-typecheck.ts. Addresses ds-review-bot on #324.
This commit is contained in:
@@ -6,17 +6,18 @@ import { promisify } from 'node:util'
|
||||
|
||||
const execFileAsync = promisify(execFile)
|
||||
const CONCURRENCY_ENV = 'DSH_PUBLINT_CONCURRENCY'
|
||||
const isWindows = process.platform === 'win32'
|
||||
|
||||
// Discover harness packages at packages/<group>/<pkg>; group containers,
|
||||
// examples, and private vendored sources are not package targets.
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
const packagesRoot = resolve(root, 'packages')
|
||||
|
||||
// On Windows recent Node (CVE-2024-27980) refuses to launch .cmd/.bat bin
|
||||
// shims without shell:true. Use the absolute path to the .cmd shim so the
|
||||
// subprocess (not a pnpm child — PATH lacks node_modules/.bin) still finds it.
|
||||
const publintBin = resolve(root, `node_modules/.bin/publint${isWindows ? '.cmd' : ''}`)
|
||||
// Run publint's JS CLI through the current node, not the .bin shim: the
|
||||
// extensionless shim isn't spawnable on Windows (CVE-2024-27980) and the .cmd
|
||||
// variant needs shell:true, which space-joins args UNESCAPED (DEP0190) and
|
||||
// breaks when the repo path contains spaces. The JS entry is identical on every
|
||||
// platform (`bin` is `./src/cli.js` per publint's package.json).
|
||||
const publintCli = resolve(root, 'node_modules/publint/src/cli.js')
|
||||
|
||||
type PublintResult =
|
||||
| { path: string; status: 'passed'; stdout: string; stderr: string }
|
||||
@@ -56,11 +57,10 @@ function outputText(value: unknown): string {
|
||||
|
||||
async function runPublint(path: string): Promise<PublintResult> {
|
||||
try {
|
||||
const { stdout, stderr } = await execFileAsync(publintBin, [path], {
|
||||
const { stdout, stderr } = await execFileAsync(process.execPath, [publintCli, path], {
|
||||
cwd: root,
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 10 * 1024 * 1024,
|
||||
shell: isWindows,
|
||||
})
|
||||
return { path, status: 'passed', stdout, stderr }
|
||||
} catch (error: unknown) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import { execFileSync } from 'node:child_process'
|
||||
import { existsSync, globSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
|
||||
const isWindows = process.platform === 'win32'
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
|
||||
interface ExportTarget {
|
||||
@@ -144,13 +143,13 @@ try {
|
||||
.join('\n')
|
||||
writeFileSync(resolve(tmp, 'index.ts'), `${imports}\n`)
|
||||
|
||||
// On Windows the bin shim is a .cmd file; recent Node (CVE-2024-27980)
|
||||
// refuses to launch .cmd/.bat via execFileSync without shell:true.
|
||||
const tscBin = isWindows ? resolve(root, 'node_modules/.bin/tsc.cmd') : resolve(root, 'node_modules/.bin/tsc')
|
||||
execFileSync(tscBin, ['-p', resolve(tmp, 'tsconfig.json'), '--pretty', 'false'], {
|
||||
// tsc's JS entry via the current node, not the .bin shim: the extensionless
|
||||
// shim isn't spawnable on Windows (CVE-2024-27980) and the .cmd variant needs
|
||||
// shell:true, which space-joins args UNESCAPED (DEP0190) — a hazard for the
|
||||
// temp tsconfig path. The JS entry behaves identically on every platform.
|
||||
execFileSync(process.execPath, ['node_modules/typescript/bin/tsc', '-p', resolve(tmp, 'tsconfig.json'), '--pretty', 'false'], {
|
||||
cwd: root,
|
||||
stdio: 'pipe',
|
||||
shell: isWindows,
|
||||
})
|
||||
console.log(`verify-node-next-types: ${packages.length} workspace package declaration surface(s) compile under NodeNext.`)
|
||||
} catch (error: unknown) {
|
||||
|
||||
Reference in New Issue
Block a user