From e49be93f2c6e9b5aeecfa8666817a312cbc53566 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 15 Apr 2026 02:07:57 +0100 Subject: [PATCH] fix(release): keep legacy update QA sidecars --- package.json | 2 ++ scripts/openclaw-npm-postpublish-verify.ts | 13 +++++++++--- scripts/openclaw-npm-release-check.ts | 13 +++++++++++- test/openclaw-npm-postpublish-verify.test.ts | 18 +++++++++-------- test/openclaw-npm-release-check.test.ts | 21 ++++++++++++++++++-- 5 files changed, 53 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index fe4ec6e962a..3d576460cad 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,9 @@ "!dist/**/*.map", "!dist/plugin-sdk/.tsbuildinfo", "!dist/extensions/qa-channel/**", + "dist/extensions/qa-channel/runtime-api.js", "!dist/extensions/qa-lab/**", + "dist/extensions/qa-lab/runtime-api.js", "!dist/extensions/qa-matrix/**", "docs/", "!docs/.generated/**", diff --git a/scripts/openclaw-npm-postpublish-verify.ts b/scripts/openclaw-npm-postpublish-verify.ts index bd8f3385016..0eb9c6b4e1f 100644 --- a/scripts/openclaw-npm-postpublish-verify.ts +++ b/scripts/openclaw-npm-postpublish-verify.ts @@ -44,9 +44,16 @@ type InstalledBundledExtensionManifestRecord = { const MAX_BUNDLED_EXTENSION_MANIFEST_BYTES = 1024 * 1024; const LEGACY_CONTEXT_ENGINE_UNRESOLVED_RUNTIME_MARKER = "Failed to load legacy context engine runtime."; -const PUBLISHED_BUNDLED_RUNTIME_SIDECAR_PATHS = BUNDLED_RUNTIME_SIDECAR_PATHS.filter( - (relativePath) => listBundledPluginPackArtifacts().includes(relativePath), -); +const LEGACY_UPDATE_COMPAT_RUNTIME_SIDECAR_PATHS = [ + "dist/extensions/qa-channel/runtime-api.js", + "dist/extensions/qa-lab/runtime-api.js", +] as const; +const PUBLISHED_BUNDLED_RUNTIME_SIDECAR_PATHS = [ + ...BUNDLED_RUNTIME_SIDECAR_PATHS.filter((relativePath) => + listBundledPluginPackArtifacts().includes(relativePath), + ), + ...LEGACY_UPDATE_COMPAT_RUNTIME_SIDECAR_PATHS, +] as const; export type PublishedInstallScenario = { name: string; diff --git a/scripts/openclaw-npm-release-check.ts b/scripts/openclaw-npm-release-check.ts index eb5c40adde0..0813db74d67 100644 --- a/scripts/openclaw-npm-release-check.ts +++ b/scripts/openclaw-npm-release-check.ts @@ -55,7 +55,15 @@ export type NpmDistTagMirrorAuth = { }; const EXPECTED_REPOSITORY_URL = "https://github.com/openclaw/openclaw"; const MAX_CALVER_DISTANCE_DAYS = 2; -const REQUIRED_PACKED_PATHS = ["dist/control-ui/index.html", ...WORKSPACE_TEMPLATE_PACK_PATHS]; +const LEGACY_UPDATE_COMPAT_PACKED_PATHS = [ + "dist/extensions/qa-channel/runtime-api.js", + "dist/extensions/qa-lab/runtime-api.js", +] as const; +const REQUIRED_PACKED_PATHS = [ + "dist/control-ui/index.html", + ...LEGACY_UPDATE_COMPAT_PACKED_PATHS, + ...WORKSPACE_TEMPLATE_PACK_PATHS, +]; const CONTROL_UI_ASSET_PREFIX = "dist/control-ui/assets/"; const FORBIDDEN_PACKED_PATH_RULES = [ { @@ -464,6 +472,9 @@ function collectPackedTarballErrors(): string[] { export function collectForbiddenPackedPathErrors(paths: Iterable): string[] { const errors: string[] = []; for (const packedPath of paths) { + if ((LEGACY_UPDATE_COMPAT_PACKED_PATHS as readonly string[]).includes(packedPath)) { + continue; + } const matchedRule = FORBIDDEN_PACKED_PATH_RULES.find((rule) => packedPath.startsWith(rule.prefix), ); diff --git a/test/openclaw-npm-postpublish-verify.test.ts b/test/openclaw-npm-postpublish-verify.test.ts index 0069f14e80a..403d3a63f51 100644 --- a/test/openclaw-npm-postpublish-verify.test.ts +++ b/test/openclaw-npm-postpublish-verify.test.ts @@ -17,6 +17,14 @@ import { BUNDLED_RUNTIME_SIDECAR_PATHS } from "../src/plugins/runtime-sidecar-pa const PUBLISHED_BUNDLED_RUNTIME_SIDECAR_PATHS = BUNDLED_RUNTIME_SIDECAR_PATHS.filter( (relativePath) => listBundledPluginPackArtifacts().includes(relativePath), ); +const LEGACY_UPDATE_COMPAT_RUNTIME_SIDECAR_PATHS = [ + "dist/extensions/qa-channel/runtime-api.js", + "dist/extensions/qa-lab/runtime-api.js", +] as const; +const REQUIRED_INSTALLED_RUNTIME_SIDECAR_PATHS = [ + ...PUBLISHED_BUNDLED_RUNTIME_SIDECAR_PATHS, + ...LEGACY_UPDATE_COMPAT_RUNTIME_SIDECAR_PATHS, +] as const; describe("buildPublishedInstallScenarios", () => { it("uses a single fresh scenario for plain stable releases", () => { @@ -75,20 +83,14 @@ describe("collectInstalledPackageErrors", () => { ); expect(errors).toEqual( expect.arrayContaining( - PUBLISHED_BUNDLED_RUNTIME_SIDECAR_PATHS.map( + REQUIRED_INSTALLED_RUNTIME_SIDECAR_PATHS.map( (relativePath) => `installed package is missing required bundled runtime sidecar: ${relativePath}`, ), ), ); - expect(errors).not.toEqual( - expect.arrayContaining([ - "installed package is missing required bundled runtime sidecar: dist/extensions/qa-channel/runtime-api.js", - "installed package is missing required bundled runtime sidecar: dist/extensions/qa-lab/runtime-api.js", - ]), - ); expect(errors.length).toBeGreaterThanOrEqual( - 1 + PUBLISHED_BUNDLED_RUNTIME_SIDECAR_PATHS.length, + 1 + REQUIRED_INSTALLED_RUNTIME_SIDECAR_PATHS.length, ); }); }); diff --git a/test/openclaw-npm-release-check.test.ts b/test/openclaw-npm-release-check.test.ts index b64b683c46e..e354d46a08b 100644 --- a/test/openclaw-npm-release-check.test.ts +++ b/test/openclaw-npm-release-check.test.ts @@ -16,6 +16,11 @@ import { utcCalendarDayDistance, } from "../scripts/openclaw-npm-release-check.ts"; +const LEGACY_UPDATE_COMPAT_PACKED_PATHS = [ + "dist/extensions/qa-channel/runtime-api.js", + "dist/extensions/qa-lab/runtime-api.js", +] as const; + describe("parseReleaseVersion", () => { it("parses stable CalVer releases", () => { expect(parseReleaseVersion("2026.3.10")).toMatchObject({ @@ -281,6 +286,10 @@ describe("parseNpmPackJsonOutput", () => { describe("collectControlUiPackErrors", () => { it("rejects packs that ship the dashboard HTML without the asset payload", () => { expect(collectControlUiPackErrors(["dist/control-ui/index.html"])).toEqual([ + ...LEGACY_UPDATE_COMPAT_PACKED_PATHS.map( + (requiredPath) => + `npm package is missing required path "${requiredPath}". Ensure UI assets are built and included before publish.`, + ), ...WORKSPACE_TEMPLATE_PACK_PATHS.map( (requiredPath) => `npm package is missing required path "${requiredPath}". Ensure UI assets are built and included before publish.`, @@ -293,6 +302,7 @@ describe("collectControlUiPackErrors", () => { expect( collectControlUiPackErrors([ "dist/control-ui/index.html", + ...LEGACY_UPDATE_COMPAT_PACKED_PATHS, ...WORKSPACE_TEMPLATE_PACK_PATHS, "dist/control-ui/assets/index-Bu8rSoJV.js", "dist/control-ui/assets/index-BK0yXA_h.css", @@ -325,11 +335,18 @@ describe("collectForbiddenPackedPathErrors", () => { ]), ).toEqual([ 'npm package must not include private QA channel artifact "dist/extensions/qa-channel/package.json".', - 'npm package must not include private QA channel artifact "dist/extensions/qa-channel/runtime-api.js".', - 'npm package must not include private QA lab artifact "dist/extensions/qa-lab/runtime-api.js".', 'npm package must not include private QA lab artifact "dist/extensions/qa-lab/src/cli.js".', ]); }); + + it("allows the legacy update verifier QA runtime sidecars", () => { + expect( + collectForbiddenPackedPathErrors([ + "dist/extensions/qa-channel/runtime-api.js", + "dist/extensions/qa-lab/runtime-api.js", + ]), + ).toEqual([]); + }); }); describe("collectReleaseTagErrors", () => {