fix(release): guard package changelog restore

This commit is contained in:
Vincent Koc
2026-05-30 03:01:27 +02:00
parent 730aa406ef
commit 086df266cc
2 changed files with 47 additions and 2 deletions

View File

@@ -105,7 +105,27 @@ export async function restorePackageChangelog(cwd = process.cwd()) {
return false;
}
const changelogPath = path.join(cwd, CHANGELOG_PATH);
const backup = await readFile(backupPath, "utf8");
const [backup, current] = await Promise.all([
readFile(backupPath, "utf8"),
readFile(changelogPath, "utf8"),
]);
if (current !== backup) {
const packageVersion = await readPackageVersion(cwd);
let expectedPackaged;
try {
expectedPackaged = extractCurrentPackageChangelog(backup, packageVersion);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(
`Refusing to restore stale packaged changelog backup from ${BACKUP_PATH}: ${message}`,
);
}
if (current !== expectedPackaged) {
throw new Error(
`Refusing to restore packaged changelog backup from ${BACKUP_PATH} because CHANGELOG.md has changed since the backup was written.`,
);
}
}
await writeFile(changelogPath, backup, "utf8");
await rm(backupPath, { force: true });
return true;

View File

@@ -1,4 +1,4 @@
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
@@ -167,4 +167,29 @@ Docs: https://docs.openclaw.ai
rmSync(root, { recursive: true, force: true });
}
});
it("refuses to restore stale backups over current changelog edits", async () => {
const root = mkdtempSync(path.join(os.tmpdir(), "openclaw-package-changelog-"));
const backupPath = path.join(
root,
".artifacts",
"package-changelog",
"CHANGELOG.md.prepack-backup",
);
const editedChangelog = cumulativeChangelog.replace("- Current fix.", "- Current fix edited.");
try {
writeFileSync(path.join(root, "package.json"), '{"version":"2026.5.28-beta.1"}\n', "utf8");
writeFileSync(path.join(root, "CHANGELOG.md"), editedChangelog, "utf8");
mkdirSync(path.dirname(backupPath), { recursive: true });
writeFileSync(backupPath, cumulativeChangelog, "utf8");
await expect(restorePackageChangelog(root)).rejects.toThrow(
"Refusing to restore packaged changelog backup",
);
expect(readFileSync(path.join(root, "CHANGELOG.md"), "utf8")).toBe(editedChangelog);
expect(existsSync(backupPath)).toBe(true);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
});