ci: enforce calver freshness on npm publish

This commit is contained in:
Onur Solmaz 2026-03-14 13:37:35 +01:00 committed by Onur
parent 5c9fae5adc
commit c08317203d
4 changed files with 3 additions and 24 deletions

View File

@ -137,7 +137,6 @@ jobs:
env:
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_MAIN_REF: origin/main
RELEASE_SKIP_CALVER_WINDOW: "1"
run: |
set -euo pipefail
RELEASE_SHA=$(git rev-parse HEAD)

View File

@ -99,8 +99,7 @@ Historical note:
- [ ] Run `OpenClaw NPM Release` manually with the same tag to publish after `npm-release` environment approval.
- Stable tags publish to npm `latest`.
- Beta tags publish to npm `beta`.
- The preview run rejects tags that do not match `package.json`, are not on `main`, or whose CalVer date is more than 2 UTC calendar days away from the release date.
- The manual publish run rechecks tag/package/main alignment, but it does not expire a tag just because approval happens later.
- Both the preview run and the manual publish run reject tags that do not match `package.json`, are not on `main`, or whose CalVer date is more than 2 UTC calendar days away from the release date.
- [ ] Verify the registry: `npm view openclaw version`, `npm view openclaw dist-tags`, and `npx -y openclaw@X.Y.Z --version` (or `--help`).
### Troubleshooting (notes from 2.0.0-beta2 release)

View File

@ -162,13 +162,11 @@ export function collectReleaseTagErrors(params: {
releaseSha?: string;
releaseMainRef?: string;
now?: Date;
enforceCalverWindow?: boolean;
}): string[] {
const errors: string[] = [];
const releaseTag = params.releaseTag.trim();
const packageVersion = params.packageVersion.trim();
const now = params.now ?? new Date();
const enforceCalverWindow = params.enforceCalverWindow ?? true;
const parsedVersion = parseReleaseVersion(packageVersion);
if (parsedVersion === null) {
@ -198,7 +196,7 @@ export function collectReleaseTagErrors(params: {
);
}
if (parsedVersion !== null && enforceCalverWindow) {
if (parsedVersion !== null) {
const dayDistance = utcCalendarDayDistance(parsedVersion.date, now);
if (dayDistance > MAX_CALVER_DISTANCE_DAYS) {
const nowLabel = now.toISOString().slice(0, 10);
@ -232,7 +230,6 @@ function loadPackageJson(): PackageJson {
function main(): number {
const pkg = loadPackageJson();
const skipCalverWindow = process.env.RELEASE_SKIP_CALVER_WINDOW === "1";
const now = new Date();
const metadataErrors = collectReleasePackageMetadataErrors(pkg);
const tagErrors = collectReleaseTagErrors({
@ -241,7 +238,6 @@ function main(): number {
releaseSha: process.env.RELEASE_SHA,
releaseMainRef: process.env.RELEASE_MAIN_REF,
now,
enforceCalverWindow: !skipCalverWindow,
});
const errors = [...metadataErrors, ...tagErrors];
@ -255,11 +251,7 @@ function main(): number {
const parsedVersion = parseReleaseVersion(pkg.version ?? "");
const channel = parsedVersion?.channel ?? "unknown";
const dayDistance =
parsedVersion === null
? "unknown"
: skipCalverWindow
? "skipped"
: String(utcCalendarDayDistance(parsedVersion.date, now));
parsedVersion === null ? "unknown" : String(utcCalendarDayDistance(parsedVersion.date, now));
console.log(
`openclaw-npm-release-check: validated ${channel} release ${pkg.version} (${dayDistance} day UTC delta).`,
);

View File

@ -66,17 +66,6 @@ describe("collectReleaseTagErrors", () => {
).toContainEqual(expect.stringContaining("must be within 2 days"));
});
it("allows manual publish validation to skip the CalVer freshness window", () => {
expect(
collectReleaseTagErrors({
packageVersion: "2026.3.10",
releaseTag: "v2026.3.10",
now: new Date("2026-03-20T00:00:00Z"),
enforceCalverWindow: false,
}),
).toEqual([]);
});
it("rejects tags that do not match the current release format", () => {
expect(
collectReleaseTagErrors({