From 11a0a9b4ac75951334759e17fb5000bc9e7072f8 Mon Sep 17 00:00:00 2001 From: aifllow Date: Mon, 18 May 2026 15:49:38 +0800 Subject: [PATCH] fix(build): stamp .version files from a script, not Bun-hostile subshell redirects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bun's shell (which runs npm scripts on Windows, where there is no /bin/sh) cannot parse `( cmd ) > file` — it errors "Subshells with redirections are currently not supported" on every Bun version (oven-sh/bun#11124, open). The build script's three `( git rev-parse HEAD 2>/dev/null || true ) > */dist/.version` stamps made `bun run build` abort at parse time on Windows, which blocked `/gstack-upgrade` for every Windows user. Move the stamping into scripts/gen-version-files.ts (Bun.write, no shell); output is byte-identical to the old form. Rewrite the second case of build-script-shell-compat.test.ts: the old assertion required a subshell redirect (built on the false premise that `( ) > file` is Bun-safe), the new one asserts no `>.version` shell redirect remains and that stamping is delegated to the script. macOS/Linux behaviour is unchanged. Fixes #1537 --- package.json | 2 +- scripts/gen-version-files.ts | 39 ++++++++++++++++++++++++++ test/build-script-shell-compat.test.ts | 35 +++++++++++++++++------ 3 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 scripts/gen-version-files.ts diff --git a/package.json b/package.json index 3851a78bd7..3074b01fde 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "make-pdf": "./make-pdf/dist/pdf" }, "scripts": { - "build": "bun run vendor:xterm && bun run gen:skill-docs --host all; bun build --compile browse/src/cli.ts --outfile browse/dist/browse && bun build --compile browse/src/find-browse.ts --outfile browse/dist/find-browse && bun build --compile design/src/cli.ts --outfile design/dist/design && bun build --compile make-pdf/src/cli.ts --outfile make-pdf/dist/pdf && bun build --compile bin/gstack-global-discover.ts --outfile bin/gstack-global-discover && bash browse/scripts/build-node-server.sh && ( git rev-parse HEAD 2>/dev/null || true ) > browse/dist/.version && ( git rev-parse HEAD 2>/dev/null || true ) > design/dist/.version && ( git rev-parse HEAD 2>/dev/null || true ) > make-pdf/dist/.version && chmod +x browse/dist/browse browse/dist/find-browse design/dist/design make-pdf/dist/pdf bin/gstack-global-discover && (rm -f .*.bun-build || true)", + "build": "bun run vendor:xterm && bun run gen:skill-docs --host all; bun build --compile browse/src/cli.ts --outfile browse/dist/browse && bun build --compile browse/src/find-browse.ts --outfile browse/dist/find-browse && bun build --compile design/src/cli.ts --outfile design/dist/design && bun build --compile make-pdf/src/cli.ts --outfile make-pdf/dist/pdf && bun build --compile bin/gstack-global-discover.ts --outfile bin/gstack-global-discover && bash browse/scripts/build-node-server.sh && bun run scripts/gen-version-files.ts && chmod +x browse/dist/browse browse/dist/find-browse design/dist/design make-pdf/dist/pdf bin/gstack-global-discover && (rm -f .*.bun-build || true)", "vendor:xterm": "mkdir -p extension/lib && cp node_modules/xterm/lib/xterm.js extension/lib/xterm.js && cp node_modules/xterm/css/xterm.css extension/lib/xterm.css && cp node_modules/xterm-addon-fit/lib/xterm-addon-fit.js extension/lib/xterm-addon-fit.js", "dev:make-pdf": "bun run make-pdf/src/cli.ts", "dev:design": "bun run design/src/cli.ts", diff --git a/scripts/gen-version-files.ts b/scripts/gen-version-files.ts new file mode 100644 index 0000000000..e2a8d6f518 --- /dev/null +++ b/scripts/gen-version-files.ts @@ -0,0 +1,39 @@ +#!/usr/bin/env bun +// gen-version-files — stamp the current git SHA into each dist/.version file. +// +// This exists because Bun's shell (which runs npm scripts on Windows, where +// there is no /bin/sh) cannot parse `( cmd ) > file`: it errors with +// "Subshells with redirections are currently not supported" on every Bun +// version (oven-sh/bun#11124, open). The build script previously stamped the +// three .version files with `( git rev-parse HEAD 2>/dev/null || true ) > +// path`, so `bun run build` aborted at parse time on Windows and blocked +// `/gstack-upgrade` for every Windows user (gstack#1537). Doing the writes +// from a Bun script sidesteps the shell entirely and is platform-agnostic. +// +// Semantics preserved from the old shell form: on success each file holds +// the HEAD SHA, newline-terminated, byte-identical to `git rev-parse HEAD`; +// if git is absent or this is not a repo, the file is created empty (the +// old `2>/dev/null || true` discarded the error and produced an empty file). + +const TARGETS = [ + "browse/dist/.version", + "design/dist/.version", + "make-pdf/dist/.version", +]; + +function gitHead(): string { + try { + const r = Bun.spawnSync(["git", "rev-parse", "HEAD"], { + stdout: "pipe", + stderr: "ignore", + }); + return r.exitCode === 0 ? r.stdout.toString().trim() : ""; + } catch { + return ""; + } +} + +const sha = gitHead(); +const content = sha ? `${sha}\n` : ""; + +await Promise.all(TARGETS.map((target) => Bun.write(target, content))); diff --git a/test/build-script-shell-compat.test.ts b/test/build-script-shell-compat.test.ts index ee13fb709e..bc89321ded 100644 --- a/test/build-script-shell-compat.test.ts +++ b/test/build-script-shell-compat.test.ts @@ -13,9 +13,9 @@ function stripSingleQuoted(s: string): string { return s.replace(/'[^']*'/g, "''"); } -describe('package.json build scripts — POSIX shell compat (D-1460)', () => { - // Bun's Windows shell parser doesn't grok bash brace groups `{ cmd; }`. - // Subshells `( cmd )` are POSIX-universal. This test prevents regression. +describe('package.json build scripts — Bun shell compat (D-1460, #11124)', () => { + // Bun's shell parser (used by `bun run