mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 22:14:25 +01:00
* fix(windows): shell bins pass NUL as Bun's empty config when MSYS path conversion is off (#3415) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(windows): detect Git Bash/MSYS2/Cygwin from OSTYPE, as gstack-doctor does, so uname stubs in setup fixtures stay untouched Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (#3415) - Choose NUL only when cygpath is also on PATH, so an OSTYPE=msys inherited by a POSIX bash keeps /dev/null instead of a cwd-relative NUL file. - gstack-developer-profile --log-session reports a Bun failure instead of skipping it as invalid input, like gstack-timeline-log. - learnings-injection tests check that their anchored bun -e block exists. - CHANGELOG names the callers this fix does not cover; curation reason fixed. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes, cycle 2 (#3415) - timeline-log and developer-profile validators print their verdict; any non-zero Bun exit is a reported failure (a Bun crash on Windows exits 3). - timeline-log keeps the original event when ts stamping fails. - The definition ratchet scopes a local GSTACK_BUN_CONFIG to its function. - The shell-bins fixture clears its preload marker per test. - CHANGELOG states the callers that discard the report and the Bun 1.3.x case. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: CHANGELOG notes Bun 1.3.10 evidence and remaining literal /dev/null callers (#3415) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
59 lines
2.7 KiB
TypeScript
59 lines
2.7 KiB
TypeScript
/**
|
|
* How gstack starts Bun (GSTA-56). Bun configures itself from the directory it
|
|
* starts in: `.env`, `.env.local` and `.env.<NODE_ENV>` become environment
|
|
* variables, and a `bunfig.toml` preload runs code before the entry point.
|
|
* gstack runs inside the user's repository, so that directory belongs to the
|
|
* code under review. Every Bun gstack starts passes --no-env-file and an empty
|
|
* --config: shebangs and skill prose spell it
|
|
* `bun --no-env-file --config=/dev/null`, shipped shell files spell
|
|
* `--config="${GSTACK_BUN_CONFIG:-/dev/null}"` (NUL when OSTYPE is msys or
|
|
* cygwin and cygpath is on PATH, #3415), TypeScript spawns use
|
|
* bunIsolationArgs().
|
|
* test/bun-entry-isolation.test.ts holds every entry point to that form.
|
|
*
|
|
* POSIX passes /dev/null. Native Windows has no /dev/null and `--config=NUL`
|
|
* panicked Bun 1.3.10 while parsing the flag (#3085), so a TypeScript spawn on
|
|
* Windows gets an empty bunfig in a fixed directory under the per-user temp
|
|
* root, re-checked to be a zero-byte regular file before each spawn; anything
|
|
* else is replaced, so the file cannot become a preload vector. The file is
|
|
* never removed: a detached child (the timeline hook's repair) reads it after
|
|
* the parent that named it has exited.
|
|
* browse/src/bun-child-config.ts keeps its own copy of emptyBunConfig(): the
|
|
* Windows native cookie qualification binds that file's bytes and bundles it
|
|
* without lib/.
|
|
*/
|
|
import * as fs from 'fs';
|
|
import * as os from 'os';
|
|
import * as path from 'path';
|
|
|
|
function isEmptyRegularFile(file: string): boolean {
|
|
try {
|
|
const stat = fs.lstatSync(file);
|
|
return stat.isFile() && stat.size === 0;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function emptyBunConfig(platform: NodeJS.Platform = process.platform): string {
|
|
if (platform !== 'win32') return '/dev/null';
|
|
const dir = path.join(os.tmpdir(), 'gstack-empty-bunfig');
|
|
const file = path.join(dir, 'bunfig.toml');
|
|
if (isEmptyRegularFile(file)) return file;
|
|
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
if (!fs.lstatSync(dir).isDirectory()) throw new Error(`empty Bun config directory ${dir} is not a directory`);
|
|
fs.rmSync(file, { recursive: true, force: true });
|
|
try {
|
|
fs.closeSync(fs.openSync(file, 'wx', 0o600));
|
|
} catch (err) {
|
|
if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;
|
|
}
|
|
if (!isEmptyRegularFile(file)) throw new Error(`empty Bun config ${file} is not a zero-byte file`);
|
|
return file;
|
|
}
|
|
|
|
/** The flags that keep a spawned Bun from reading the working directory's .env and bunfig.toml. */
|
|
export function bunIsolationArgs(platform: NodeJS.Platform = process.platform): string[] {
|
|
return ['--no-env-file', `--config=${emptyBunConfig(platform)}`];
|
|
}
|