fix: exclude qa extensions from npm package

This commit is contained in:
Peter Steinberger
2026-04-22 22:45:50 +01:00
parent ebe32e5cee
commit e56a6f87ec
9 changed files with 21 additions and 36 deletions

View File

@@ -32,9 +32,7 @@
"!dist/extensions/node_modules/**",
"!dist/extensions/*/node_modules/**",
"!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/**",
"!dist/plugin-sdk/extensions/qa-lab/**",
"!dist/plugin-sdk/qa-lab.*",

View File

@@ -52,7 +52,6 @@ const providerConfig = {
};
const PACKAGE_DIST_INVENTORY_RELATIVE_PATH = "dist/postinstall-inventory.json";
const PACKAGED_QA_RUNTIME_PATHS = new Set(["dist/extensions/qa-channel/runtime-api.js"]);
const OMITTED_QA_EXTENSION_PREFIXES = [
"dist/extensions/qa-channel/",
"dist/extensions/qa-lab/",
@@ -478,7 +477,7 @@ function isPackagedDistPath(relativePath) {
return false;
}
if (OMITTED_QA_EXTENSION_PREFIXES.some((prefix) => relativePath.startsWith(prefix))) {
return PACKAGED_QA_RUNTIME_PATHS.has(relativePath);
return false;
}
return true;
}

View File

@@ -59,14 +59,9 @@ export type NpmDistTagMirrorAuth = {
};
const EXPECTED_REPOSITORY_URL = "https://github.com/openclaw/openclaw";
const MAX_CALVER_DISTANCE_DAYS = 2;
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 = [
PACKAGE_DIST_INVENTORY_RELATIVE_PATH,
"dist/control-ui/index.html",
...LEGACY_UPDATE_COMPAT_PACKED_PATHS,
...WORKSPACE_TEMPLATE_PACK_PATHS,
];
const CONTROL_UI_ASSET_PREFIX = "dist/control-ui/assets/";
@@ -104,6 +99,7 @@ const FORBIDDEN_PACKED_PATH_RULES = [
] as const;
const FORBIDDEN_PRIVATE_QA_CONTENT_MARKERS = [
"//#region extensions/qa-lab/",
"qa-channel/runtime-api.js",
"qa-lab/cli.js",
"qa-lab/runtime-api.js",
] as const;
@@ -532,9 +528,6 @@ function collectPackedTarballErrors(): string[] {
export function collectForbiddenPackedPathErrors(paths: Iterable<string>): 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),
);

View File

@@ -66,16 +66,11 @@ const requiredPathGroups = [
"dist/build-info.json",
"dist/channel-catalog.json",
"dist/control-ui/index.html",
"dist/extensions/qa-channel/runtime-api.js",
"dist/extensions/qa-lab/runtime-api.js",
];
const legacyUpdateCompatPackPaths = new Set([
"dist/extensions/qa-channel/runtime-api.js",
"dist/extensions/qa-lab/runtime-api.js",
]);
const forbiddenPrefixes = [
"dist-runtime/",
"dist/OpenClaw.app/",
"dist/extensions/qa-channel/",
"dist/extensions/qa-lab/",
"dist/plugin-sdk/extensions/qa-lab/",
"dist/plugin-sdk/qa-lab.",
@@ -89,6 +84,7 @@ const forbiddenPrefixes = [
];
const forbiddenPrivateQaContentMarkers = [
"//#region extensions/qa-lab/",
"qa-channel/runtime-api.js",
"qa-lab/cli.js",
"qa-lab/runtime-api.js",
] as const;
@@ -460,9 +456,7 @@ export function collectForbiddenPackPaths(paths: Iterable<string>): string[] {
return [...paths]
.filter(
(path) =>
!legacyUpdateCompatPackPaths.has(path) &&
(forbiddenPrefixes.some((prefix) => path.startsWith(prefix)) ||
/node_modules\//.test(path)),
forbiddenPrefixes.some((prefix) => path.startsWith(prefix)) || /node_modules\//.test(path),
)
.toSorted((left, right) => left.localeCompare(right));
}

View File

@@ -114,9 +114,7 @@ describe("package dist inventory", () => {
);
await fs.writeFile(omittedMap, "{}", "utf8");
await expect(writePackageDistInventory(packageRoot)).resolves.toEqual([
"dist/extensions/qa-channel/runtime-api.js",
]);
await expect(writePackageDistInventory(packageRoot)).resolves.toEqual([]);
});
});
it("fails closed when the inventory is missing", async () => {

View File

@@ -3,7 +3,6 @@ import path from "node:path";
export const PACKAGE_DIST_INVENTORY_RELATIVE_PATH = "dist/postinstall-inventory.json";
const LEGACY_QA_LAB_DIR = ["qa", "lab"].join("-");
const PACKAGED_QA_RUNTIME_PATHS = new Set(["dist/extensions/qa-channel/runtime-api.js"]);
const OMITTED_QA_EXTENSION_PREFIXES = [
"dist/extensions/qa-channel/",
`dist/extensions/${LEGACY_QA_LAB_DIR}/`,
@@ -51,7 +50,7 @@ function isPackagedDistPath(relativePath: string): boolean {
return false;
}
if (OMITTED_QA_EXTENSION_PREFIXES.some((prefix) => relativePath.startsWith(prefix))) {
return PACKAGED_QA_RUNTIME_PATHS.has(relativePath);
return false;
}
return true;
}

View File

@@ -94,6 +94,9 @@ function listTsFiles(rootRelativePath: string, filter: FileFilter = {}): string[
for (const entry of readdirSync(directory, { withFileTypes: true })) {
const fullPath = resolve(directory, entry.name);
if (entry.isDirectory()) {
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") {
continue;
}
walk(fullPath);
continue;
}

View File

@@ -22,13 +22,8 @@ import {
} from "../scripts/openclaw-npm-release-check.ts";
import { PACKAGE_DIST_INVENTORY_RELATIVE_PATH } from "../src/infra/package-dist-inventory.ts";
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 = [
PACKAGE_DIST_INVENTORY_RELATIVE_PATH,
...LEGACY_UPDATE_COMPAT_PACKED_PATHS,
...WORKSPACE_TEMPLATE_PACK_PATHS,
] as const;
@@ -344,6 +339,8 @@ 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".',
'npm package must not include private QA lab type artifact "dist/plugin-sdk/extensions/qa-lab/cli.d.ts".',
'npm package must not include private QA runtime chunk "dist/qa-runtime-B9LDtssJ.js".',
@@ -351,13 +348,16 @@ describe("collectForbiddenPackedPathErrors", () => {
]);
});
it("allows legacy update verifier QA runtime sidecars", () => {
it("rejects legacy update verifier QA runtime sidecars", () => {
expect(
collectForbiddenPackedPathErrors([
"dist/extensions/qa-channel/runtime-api.js",
"dist/extensions/qa-lab/runtime-api.js",
]),
).toEqual([]);
).toEqual([
'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".',
]);
});
it("rejects root dist chunks that still reference the private qa lab", () => {

View File

@@ -308,10 +308,11 @@ describe("collectForbiddenPackPaths", () => {
]);
});
it("blocks private qa lab and suite paths from npm pack output", () => {
it("blocks private qa channel, qa lab, and suite paths from npm pack output", () => {
expect(
collectForbiddenPackPaths([
"dist/index.js",
"dist/extensions/qa-channel/runtime-api.js",
"dist/extensions/qa-lab/runtime-api.js",
"dist/plugin-sdk/extensions/qa-lab/cli.d.ts",
"dist/plugin-sdk/qa-lab.js",
@@ -320,6 +321,8 @@ describe("collectForbiddenPackPaths", () => {
"qa/scenarios/index.md",
]),
).toEqual([
"dist/extensions/qa-channel/runtime-api.js",
"dist/extensions/qa-lab/runtime-api.js",
"dist/plugin-sdk/extensions/qa-lab/cli.d.ts",
"dist/plugin-sdk/qa-lab.js",
"dist/plugin-sdk/qa-runtime.js",
@@ -408,8 +411,6 @@ describe("collectMissingPackPaths", () => {
"dist/index.js",
"dist/entry.js",
"dist/control-ui/index.html",
"dist/extensions/qa-channel/runtime-api.js",
"dist/extensions/qa-lab/runtime-api.js",
"dist/extensions/acpx/mcp-proxy.mjs",
bundledDistPluginFile("diffs", "assets/viewer-runtime.js"),
...requiredBundledPluginPackPaths,