fix(tests): scrub GIT_* env vars leaking from the pre-commit hook into git-fixture tests

server/lib/update-check.js's execGit() and two test helpers
(lanes-cli.test.js, update-check.test.js) shelled out to git with an
explicit `cwd` but no `env` override. A parent git hook process (this
repo's own .husky/pre-commit, which runs `npm run test:server`) sets
GIT_DIR/GIT_INDEX_FILE in its own environment; those leak to every
child process and take precedence over `cwd` for repo discovery, so
every git command these tests ran against their throwaway tmp repos
was silently redirected at the real repo running the hook instead —
reproduced firsthand as four foreign "init"/"fixture" commits
overwriting a worktree branch mid pre-commit run. Fixes it the same
way server/lib/worktree.js already documented and did for its own git
calls: strip the GIT_* vars before exec.
This commit is contained in:
2026-08-12 09:24:03 +07:00
parent 7357070fb9
commit dfea1a99d6
3 changed files with 64 additions and 4 deletions
+21 -1
View File
@@ -19,13 +19,33 @@ const DEFAULT_ROOT = path.join(__dirname, "..", "..");
// never make the update checker report commits from somebody else's repo.
const REMOTE_PRIORITY = ["origin"];
// Scrub git hook environment variables (GIT_DIR, GIT_INDEX_FILE, etc.) that
// leak from a parent git hook process — e.g. this repo's own pre-commit
// hook, which runs `npm run test:server` and therefore this module too.
// Without this, every git call below silently targets the OUTER repo (the
// hook's) instead of `cwd`, since GIT_DIR takes precedence over cwd-based
// discovery. Same scrub `server/lib/worktree.js` already applies.
const GIT_ENV = { ...process.env };
delete GIT_ENV.GIT_DIR;
delete GIT_ENV.GIT_WORK_TREE;
delete GIT_ENV.GIT_INDEX_FILE;
delete GIT_ENV.GIT_COMMON_DIR;
delete GIT_ENV.GIT_OBJECT_DIRECTORY;
delete GIT_ENV.GIT_ALTERNATE_OBJECT_DIRECTORIES;
delete GIT_ENV.GIT_PREFIX;
delete GIT_ENV.GIT_NAMESPACE;
delete GIT_ENV.GIT_CONFIG_PARAMETERS;
for (const name of Object.keys(GIT_ENV)) {
if (/^GIT_CONFIG_(COUNT|KEY_\d+|VALUE_\d+|GLOBAL|SYSTEM)$/.test(name)) delete GIT_ENV[name];
}
function execGit(cwd, args, opts = {}) {
const timeout = opts.timeout ?? 120_000;
return new Promise((resolve, reject) => {
execFile(
"git",
args,
{ cwd, timeout, maxBuffer: 2_000_000, encoding: "utf8" },
{ cwd, timeout, maxBuffer: 2_000_000, encoding: "utf8", env: GIT_ENV },
(err, stdout) => {
if (err) reject(err);
else resolve(String(stdout).trim());