test(#3144): bound the git/worktree cluster onto the process seam (#3152)

* test(#3144): bound the git/worktree cluster onto the process seam

Migrates 180 unbounded sync spawn sites across 19 files. Every previously
unbounded call now carries an explicit timeout with a comment giving the
number and why.

The migration is not a callee swap. execSync and execFileSync throw on a
non-zero exit and the seam never does, so each site was classified first:
sites that rely on the throw route to gitOrThrow, and sites that already read
.status to detect an EXPECTED non-zero -- an intended cherry-pick conflict, a
rev-parse outside a repo driving a skip -- route to the never-throwing runGit
instead, which would otherwise throw on exactly the exit being probed for.

Two same-named git() helpers in worktree-cleanup.test.cjs have different
return contracts, one trimmed and one raw; both are preserved rather than
unified.

Collapses five hand-rolled throw wrappers onto one throwIfFailed in
git-fixture.cjs, which gitOrThrow now also uses so the shape cannot drift.

Allowlist drops 139 to 120; BASELINE lowered to match.

* test(#3144): fix pre-PR review findings

Documents throwIfFailed in the CONTEXT.md glossary and CONTRIBUTING.md --
it became the shared throw mechanism without either doc naming it.

Routes the sixth and seventh hand-rolled copies of the throw shape through
throwIfFailed (worktree-baseref-install, worktree-safety-reap); the first
consolidation missed both.

Converts ci-rebase-check's 8 fixture-setup calls from unchecked runGit to
gitOrThrow so a failed setup step aborts where it fails rather than
surfacing later as a confusing failure against the wrong subject.

Adds 12 direct unit tests for throwIfFailed, which until now was only
exercised transitively.

Splits verify.test.cjs's non-git grep/sed bound off GIT_TIMEOUT_MS.

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-07 10:58:34 -04:00
committed by GitHub
parent cfb37ccdfc
commit 1d208e5af6
26 changed files with 598 additions and 362 deletions

View File

@@ -13,9 +13,12 @@ const { describe, test, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const { createTempGitProject, cleanup, runGsdTools } = require('./helpers.cjs');
const { gitOrThrow } = require('./helpers/git-fixture.cjs');
// 15000ms: git plumbing (add/commit/diff) on a small mkdtemp fixture repo —
// far over any observed duration for that class of call.
const GIT_TIMEOUT_MS = 15000;
describe('commit --files: missing files must not stage deletions (#2014)', () => {
let tmpDir;
@@ -24,8 +27,8 @@ describe('commit --files: missing files must not stage deletions (#2014)', () =>
tmpDir = createTempGitProject();
// Commit STATE.md so it exists in git history
fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n\nInitial state.\n');
execSync('git add .planning/STATE.md', { cwd: tmpDir, stdio: 'pipe' });
execSync('git commit -m "add STATE.md"', { cwd: tmpDir, stdio: 'pipe' });
gitOrThrow(['add', '.planning/STATE.md'], { cwd: tmpDir, timeoutMs: GIT_TIMEOUT_MS });
gitOrThrow(['commit', '-m', 'add STATE.md'], { cwd: tmpDir, timeoutMs: GIT_TIMEOUT_MS });
// Delete STATE.md from disk -- now missing but tracked in git
fs.unlinkSync(path.join(tmpDir, '.planning', 'STATE.md'));
});
@@ -46,7 +49,7 @@ describe('commit --files: missing files must not stage deletions (#2014)', () =>
// git diff HEAD~1 HEAD --name-status shows what changed between commits.
let diffOutput = '';
try {
diffOutput = execSync('git diff HEAD~1 HEAD --name-status', { cwd: tmpDir, encoding: 'utf-8' });
diffOutput = gitOrThrow(['diff', 'HEAD~1', 'HEAD', '--name-status'], { cwd: tmpDir, timeoutMs: GIT_TIMEOUT_MS });
} catch (e) {
// If nothing to commit, there is no HEAD~1 -- that's also acceptable
return;
@@ -70,7 +73,7 @@ describe('commit --files: missing files must not stage deletions (#2014)', () =>
assert.strictEqual(parsed.committed, true, 'should have committed when file exists');
// Verify ROADMAP.md was added in the commit
const diffOutput = execSync('git diff HEAD~1 HEAD --name-status', { cwd: tmpDir, encoding: 'utf-8' });
const diffOutput = gitOrThrow(['diff', 'HEAD~1', 'HEAD', '--name-status'], { cwd: tmpDir, timeoutMs: GIT_TIMEOUT_MS });
assert.ok(
diffOutput.includes('A\t.planning/ROADMAP.md'),
'ROADMAP.md should appear as added in the commit'
@@ -89,7 +92,7 @@ describe('commit --files: missing files must not stage deletions (#2014)', () =>
// The commit must not include a deletion of STATE.md
let diffOutput = '';
try {
diffOutput = execSync('git diff HEAD~1 HEAD --name-status', { cwd: tmpDir, encoding: 'utf-8' });
diffOutput = gitOrThrow(['diff', 'HEAD~1', 'HEAD', '--name-status'], { cwd: tmpDir, timeoutMs: GIT_TIMEOUT_MS });
} catch (e) {
return; // nothing committed is fine
}