test(wireup): make gbrain-missing PATH fixture hermetic

The gbrain-missing test appended the host PATH (and a hardcoded /opt/homebrew/bin) to the fixture PATH, so on any machine with a real gbrain installed the 'missing' case saw it, exited 0 instead of 2, and could never fail where the bug exists — a false green for a whole machine class. The fixture now keeps only root-owned OS dirs on the child PATH, and a new determinism check plants a host-like gbrain to prove it is unreachable.

Absorbed from PR #2615 with authorship preserved; the PR-thread liveness screenshot (docs/images/gstack-pr-liveness-2255.png) is dropped — referenced by nothing in the tree.

Fixes #2255

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
This commit is contained in:
Som Samantray
2026-08-22 01:54:19 +00:00
committed by Garry Tan
co-authored by CommandCodeBot
parent 85fd9db554
commit 2010b345e6
+57 -9
View File
@@ -20,6 +20,18 @@ const ROOT = path.resolve(import.meta.dir, '..');
const BIN_DIR = path.join(ROOT, 'bin');
const WIREUP_BIN = path.join(BIN_DIR, 'gstack-gbrain-source-wireup');
// Hermetic PATH base (#2255). The missing-gbrain fixtures must not see a
// user-installed gbrain on the host (e.g. macOS /opt/homebrew/bin), or the
// "missing" case exits 0 instead of 2. Base is root-owned OS dirs only
// (/usr/bin:/bin:/usr/sbin:/sbin — where git/python3/jq/coreutils resolve on
// macOS and Linux) plus BUN_ONLY_DIR, so no user-installed gbrain can be
// present. The scratch dir holds only a bun symlink, mirroring
// gbrain-detect-install.test.ts so spawned children can resolve bun on CI
// regardless of install dir.
const BUN_ONLY_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'wireup-bun-only-'));
fs.symlinkSync(process.execPath, path.join(BUN_ONLY_DIR, 'bun'));
const HERMETIC_PATH = `/usr/bin:/bin:/usr/sbin:/sbin:${BUN_ONLY_DIR}`;
let tmpHome: string;
let gstackHome: string;
let worktreeDir: string;
@@ -113,7 +125,7 @@ function run(
opts: { env?: Record<string, string> } = {}
) {
const env = {
PATH: `${fakeBinDir}:${process.env.PATH || '/usr/bin:/bin:/opt/homebrew/bin'}`,
PATH: `${fakeBinDir}:${HERMETIC_PATH}`,
HOME: tmpHome,
GSTACK_HOME: gstackHome,
GSTACK_BRAIN_WORKTREE: worktreeDir,
@@ -229,14 +241,52 @@ describe('gstack-gbrain-source-wireup — wireup mode', () => {
test('--strict + gbrain missing on PATH: exits 2', () => {
setupGstackRepo('git@github.com:user/gstack-brain-user.git');
// Don't make a fake gbrain — fakeBinDir is empty. Keep system dirs on PATH
// so basic commands (git, awk, sed, etc.) work; only `gbrain` is absent.
const r = run(['--strict'], {
env: { PATH: `${fakeBinDir}:/usr/bin:/bin:/opt/homebrew/bin` },
});
// Don't make a fake gbrain — fakeBinDir is empty. run() applies the
// hermetic PATH base; only `gbrain` is absent.
const r = run(['--strict']);
expect(r.status).toBe(2);
});
test('--strict + gbrain present in controlled dir: exits 0 (positive control)', () => {
setupGstackRepo('git@github.com:user/gstack-brain-user.git');
// Positive control for hermeticity: a gbrain stub in the test-controlled
// fakeBinDir (first on the hermetic PATH) IS found, so --strict proceeds
// (exit 0). This proves the fixture CAN supply gbrain when present; the
// determinism test below proves the host cannot leak one in (#2255).
makeFakeGbrain({});
const r = run(['--strict'], { env: { GSTACK_BRAIN_NO_SYNC: '1' } });
expect(r.status).toBe(0);
expect(gbrainCalls().some((c) => c.startsWith('gbrain sources add'))).toBe(true);
});
test('--strict + gbrain present in a host-like dir: still exits 2 (determinism)', () => {
setupGstackRepo('git@github.com:user/gstack-brain-user.git');
// Determinism check (#2255, plan TS2): plant a real-looking gbrain stub in
// a dir that the OLD fixture would have leaked via process.env.PATH or the
// hardcoded /opt/homebrew/bin list. The root-owned-only hermetic base
// excludes user-writable dirs, so the child never sees the stub and the
// missing case stays deterministic across dev machines. This test fails on
// the unpatched fixture (stub found -> exit 0) and passes on the fixed one.
const hostLikeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'wireup-host-like-'));
fs.writeFileSync(
path.join(hostLikeDir, 'gbrain'),
'#!/bin/bash\necho "gbrain 0.18.2"\n',
{ mode: 0o755 }
);
// No env PATH override: run() applies the hermetic base. The stub exists
// only in a user-writable dir the base excludes.
const r = run(['--strict']);
expect(r.status).toBe(2);
// Sanity: the stub IS visible to a shell using the host-like PATH, so this
// test would catch the old leak if the base ever regressed.
const check = spawnSync('bash', ['-c', `command -v gbrain && gbrain --version`], {
env: { PATH: `${hostLikeDir}:${process.env.PATH || '/usr/bin:/bin'}` },
encoding: 'utf-8',
});
expect(check.status).toBe(0);
expect(check.stdout).toContain('gbrain 0.18.2');
});
test('source-id derived from origin URL', () => {
setupGstackRepo('git@github.com:user/gstack-brain-alice.git');
makeFakeGbrain({});
@@ -388,9 +438,7 @@ describe('gstack-gbrain-source-wireup — uninstall mode', () => {
expect(fs.existsSync(worktreeDir)).toBe(true);
// Now remove the fake gbrain so uninstall sees gbrain missing
fs.rmSync(path.join(fakeBinDir, 'gbrain'), { force: true });
const r = run(['--uninstall'], {
env: { PATH: `${fakeBinDir}:/usr/bin:/bin:/opt/homebrew/bin` },
});
const r = run(['--uninstall']);
expect(r.status).toBe(0); // best-effort, never fails on gbrain absence
expect(fs.existsSync(worktreeDir)).toBe(false); // worktree still cleaned up
});