fix(release): pin max-lines debt to branch merge base

This commit is contained in:
Peter Steinberger
2026-07-15 00:53:47 +01:00
parent bac7744233
commit 5fa348f3ed
2 changed files with 82 additions and 13 deletions

View File

@@ -276,19 +276,31 @@ function readBaselineAtRef(root, ref) {
function resolveDefaultBase(root, staged) {
const candidates = staged ? ["HEAD"] : ["origin/main", "HEAD"];
return (
candidates.find((ref) => {
try {
execFileSync("git", ["rev-parse", "--verify", ref + "^{commit}"], {
cwd: root,
stdio: "ignore",
});
return true;
} catch {
return false;
}
}) ?? null
);
const resolved = candidates.find((ref) => {
try {
execFileSync("git", ["rev-parse", "--verify", ref + "^{commit}"], {
cwd: root,
stdio: "ignore",
});
return true;
} catch {
return false;
}
});
if (!resolved || staged || resolved !== "origin/main") {
return resolved ?? null;
}
// A release or long-lived branch owns the suppression debt from its fork.
// Comparing against moving main would turn unrelated debt cleanup into a blocker.
try {
return execFileSync("git", ["merge-base", "HEAD", resolved], {
cwd: root,
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
}).trim();
} catch {
return resolved;
}
}
function writeBaseline(root, entries) {

View File

@@ -233,6 +233,63 @@ describe("check-max-lines-ratchet", () => {
expect(main(root)).toBe(1);
});
it("compares divergent worktrees against their main merge base", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-max-lines-diverged-"));
tempDirs.push(root);
fs.mkdirSync(path.join(root, "config"), { recursive: true });
fs.mkdirSync(path.join(root, "src"), { recursive: true });
fs.writeFileSync(path.join(root, "config/max-lines-baseline.txt"), "src/a.ts\nsrc/b.ts\n");
fs.writeFileSync(path.join(root, "src/a.ts"), "/* oxlint-disable max-lines */\n");
fs.writeFileSync(path.join(root, "src/b.ts"), "/* oxlint-disable max-lines */\n");
for (const args of [
["init"],
["config", "user.email", "test@example.com"],
["config", "user.name", "Test"],
["add", "."],
["commit", "-m", "base"],
["branch", "release"],
]) {
git(root, args);
}
fs.writeFileSync(path.join(root, "config/max-lines-baseline.txt"), "src/a.ts\n");
fs.writeFileSync(path.join(root, "src/b.ts"), "export const b = 1;\n");
git(root, ["add", "."]);
git(root, ["commit", "-m", "shrink main debt"]);
git(root, ["update-ref", "refs/remotes/origin/main", "HEAD"]);
git(root, ["checkout", "release"]);
expect(main(root)).toBe(0);
});
it("falls back to main when no merge base is available", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-max-lines-disconnected-"));
tempDirs.push(root);
fs.mkdirSync(path.join(root, "config"), { recursive: true });
fs.mkdirSync(path.join(root, "src"), { recursive: true });
fs.writeFileSync(path.join(root, "config/max-lines-baseline.txt"), "src/a.ts\n");
fs.writeFileSync(path.join(root, "src/a.ts"), "/* oxlint-disable max-lines */\n");
for (const args of [
["init"],
["config", "user.email", "test@example.com"],
["config", "user.name", "Test"],
["add", "."],
["commit", "-m", "release"],
["branch", "-m", "release"],
]) {
git(root, args);
}
git(root, ["checkout", "--orphan", "main"]);
fs.writeFileSync(path.join(root, "config/max-lines-baseline.txt"), "");
fs.writeFileSync(path.join(root, "src/a.ts"), "export const a = 1;\n");
git(root, ["add", "."]);
git(root, ["commit", "-m", "disconnected main"]);
git(root, ["update-ref", "refs/remotes/origin/main", "HEAD"]);
git(root, ["checkout", "release"]);
expect(main(root)).toBe(1);
});
it("checks staged content instead of unstaged worktree edits", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-max-lines-staged-"));
tempDirs.push(root);