ci: preserve manual npm release approval delays

This commit is contained in:
Onur Solmaz
2026-03-14 13:01:15 +01:00
committed by Onur
parent 2eea93982f
commit 02a86da23a
4 changed files with 24 additions and 3 deletions

View File

@@ -129,6 +129,7 @@ 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

@@ -94,7 +94,8 @@ Historical note:
- [ ] Confirm git status is clean; commit and push as needed.
- [ ] Confirm npm trusted publishing is configured for the `openclaw` package.
- [ ] Push the matching git tag to trigger `.github/workflows/openclaw-npm-release.yml`.
- [ ] Push the matching git tag to trigger the preview run in `.github/workflows/openclaw-npm-release.yml`.
- [ ] 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 workflow 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.

View File

@@ -162,11 +162,13 @@ 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) {
@@ -196,7 +198,7 @@ export function collectReleaseTagErrors(params: {
);
}
if (parsedVersion !== null) {
if (parsedVersion !== null && enforceCalverWindow) {
const dayDistance = utcCalendarDayDistance(parsedVersion.date, now);
if (dayDistance > MAX_CALVER_DISTANCE_DAYS) {
const nowLabel = now.toISOString().slice(0, 10);
@@ -230,12 +232,16 @@ 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({
packageVersion: pkg.version ?? "",
releaseTag: process.env.RELEASE_TAG ?? "",
releaseSha: process.env.RELEASE_SHA,
releaseMainRef: process.env.RELEASE_MAIN_REF,
now,
enforceCalverWindow: !skipCalverWindow,
});
const errors = [...metadataErrors, ...tagErrors];
@@ -251,7 +257,9 @@ function main(): number {
const dayDistance =
parsedVersion === null
? "unknown"
: String(utcCalendarDayDistance(parsedVersion.date, new Date()));
: skipCalverWindow
? "skipped"
: String(utcCalendarDayDistance(parsedVersion.date, now));
console.log(
`openclaw-npm-release-check: validated ${channel} release ${pkg.version} (${dayDistance} day UTC delta).`,
);

View File

@@ -66,6 +66,17 @@ 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({