Files
msd-core/tests/branch-no-track-guard.test.cjs
Tom Boucher c2b498e452 fix(#2498): pass --no-track when branching off origin/$DEFAULT_BRANCH (#2628)
* test(#2498): guard branch-creation uses --no-track (all workflows)

* fix(#2498): pass --no-track when branching off origin/$DEFAULT_BRANCH

* chore(#2498): backfill changeset pr to 2628
2026-07-24 22:49:29 -04:00

57 lines
2.4 KiB
JavaScript

// allow-test-rule: structural-regression-guard see #2498
// Guards the --no-track fix: any workflow that creates a branch from a remote-tracking
// ref (origin/$DEFAULT_BRANCH / origin/$<ENV>_BRANCH) MUST pass --no-track. Without it,
// the default branch.autoSetupMerge=true wires branch.<name>.merge to
// refs/heads/$DEFAULT_BRANCH, so a GUI sync (GitHub Desktop, VS Code) pushes the
// branch's commits straight onto origin/$DEFAULT_BRANCH, bypassing PR review entirely
// (#2498 — caused a 7-plan phase's commits to land on origin/master in a real project).
// Scans ALL workflow .md files so a newly-added workflow reintroducing the pattern is
// caught, not just the two originally-fixed ones.
'use strict';
const { test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const ROOT = path.resolve(__dirname, '..');
const WORKFLOWS_DIR = path.join(ROOT, 'gsd-core', 'workflows');
function collectMdFiles(dir) {
const results = [];
if (!fs.existsSync(dir)) return results;
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
results.push(...collectMdFiles(full));
} else if (entry.isFile() && entry.name.endsWith('.md')) {
results.push(full);
}
}
return results;
}
test('#2498: branch creation from a remote-tracking ref uses --no-track', () => {
const violations = [];
for (const file of collectMdFiles(WORKFLOWS_DIR)) {
const rel = path.relative(ROOT, file).replace(/\\/g, '/');
const lines = fs.readFileSync(file, 'utf8').split(/\r?\n/);
lines.forEach((line, i) => {
const isCheckoutFromRemoteRef =
/git\s+checkout\s+-b\b/.test(line) &&
/origin\/\$[A-Z_]+_?BRANCH|origin\/\$DEFAULT_BRANCH/.test(line);
if (isCheckoutFromRemoteRef && !/--no-track/.test(line)) {
violations.push(`${rel}:${i + 1}: ${line.trim()}`);
}
});
}
assert.equal(
violations.length,
0,
`Found ${violations.length} \`git checkout -b\` from a remote-tracking ref ` +
`(origin/$<BRANCH>) without --no-track (#2498). Default branch.autoSetupMerge would ` +
`wire the branch upstream to origin/$<BRANCH>, so a GUI sync pushes commits onto it, ` +
`bypassing PR review. Add --no-track. Violations:\n${violations.join('\n')}`,
);
});