mirror of
https://github.com/openclaw/clawhub.git
synced 2026-08-14 00:47:57 +00:00
fix(release): reject partial ancestry metadata
This commit is contained in:
@@ -154,16 +154,20 @@ function collectReleaseTagErrors({ packageVersion, releaseTag, releaseSha, relea
|
||||
`Release tag ${normalizedTag} does not match packages/clawhub/package.json version ${normalizedVersion}; expected v${normalizedVersion}.`,
|
||||
);
|
||||
}
|
||||
if (releaseSha?.trim() && releaseMainRef?.trim()) {
|
||||
const normalizedReleaseSha = releaseSha?.trim() ?? "";
|
||||
const normalizedReleaseMainRef = releaseMainRef?.trim() ?? "";
|
||||
if (Boolean(normalizedReleaseSha) !== Boolean(normalizedReleaseMainRef)) {
|
||||
errors.push("Release ancestry validation requires both --release-sha and --release-main-ref.");
|
||||
} else if (normalizedReleaseSha && normalizedReleaseMainRef) {
|
||||
try {
|
||||
execFileSync(
|
||||
"git",
|
||||
["merge-base", "--is-ancestor", releaseSha.trim(), releaseMainRef.trim()],
|
||||
["merge-base", "--is-ancestor", normalizedReleaseSha, normalizedReleaseMainRef],
|
||||
{ stdio: "ignore" },
|
||||
);
|
||||
} catch {
|
||||
errors.push(
|
||||
`Tagged commit ${releaseSha.trim()} is not contained in ${releaseMainRef.trim()}.`,
|
||||
`Tagged commit ${normalizedReleaseSha} is not contained in ${normalizedReleaseMainRef}.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,22 +4,64 @@ import { spawnSync } from "node:child_process";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
describe("clawhub CLI npm release metadata check", () => {
|
||||
const releaseTag = "v0.23.0";
|
||||
|
||||
function runCheck(args) {
|
||||
const env = { ...process.env };
|
||||
delete env.RELEASE_TAG;
|
||||
delete env.RELEASE_SHA;
|
||||
delete env.RELEASE_MAIN_REF;
|
||||
return spawnSync("node", ["scripts/clawhub-cli-npm-release-check.mjs", ...args], {
|
||||
encoding: "utf8",
|
||||
env,
|
||||
});
|
||||
}
|
||||
|
||||
it("rejects option names used as missing flag values", () => {
|
||||
const result = spawnSync(
|
||||
"node",
|
||||
[
|
||||
"scripts/clawhub-cli-npm-release-check.mjs",
|
||||
"--tag",
|
||||
"--release-sha",
|
||||
"abc",
|
||||
"--release-main-ref",
|
||||
"main",
|
||||
],
|
||||
{ encoding: "utf8" },
|
||||
);
|
||||
const result = runCheck(["--tag", "--release-sha", "abc", "--release-main-ref", "main"]);
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stderr).toContain("--tag requires a value.");
|
||||
expect(result.stderr).not.toContain('Release tag must match vX.Y.Z; found "--release-sha".');
|
||||
});
|
||||
|
||||
it.each([
|
||||
["--release-sha", "HEAD"],
|
||||
["--release-main-ref", "HEAD"],
|
||||
])("rejects %s without its matching ancestry ref", (flag, value) => {
|
||||
const result = runCheck(["--tag", releaseTag, flag, value]);
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stderr).toContain(
|
||||
"Release ancestry validation requires both --release-sha and --release-main-ref.",
|
||||
);
|
||||
});
|
||||
|
||||
it("validates that the release commit is an ancestor of the main ref", () => {
|
||||
const result = runCheck([
|
||||
"--tag",
|
||||
releaseTag,
|
||||
"--release-sha",
|
||||
"HEAD^",
|
||||
"--release-main-ref",
|
||||
"HEAD",
|
||||
]);
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
expect(result.stdout).toContain("Release metadata OK");
|
||||
});
|
||||
|
||||
it("rejects a release commit that is not contained in the main ref", () => {
|
||||
const result = runCheck([
|
||||
"--tag",
|
||||
releaseTag,
|
||||
"--release-sha",
|
||||
"HEAD",
|
||||
"--release-main-ref",
|
||||
"HEAD^",
|
||||
]);
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stderr).toContain("Tagged commit HEAD is not contained in HEAD^.");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user