mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 02:06:43 +00:00
fix(ci): preserve OCM workspace prepack (#107844)
* fix(ci): preserve OCM workspace prepack * fix(ci): bind OCM prepack to pack context * fix(ci): avoid path import shadowing
This commit is contained in:
@@ -18,7 +18,7 @@ export function buildInstallManifest(
|
||||
openclaw: string;
|
||||
};
|
||||
};
|
||||
export function resolveNpmEnvironment(args: unknown, env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
||||
export function resolveNpmEnvironment(args: string[], env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
||||
export function resolveRuntimePackPlan(
|
||||
args: string[],
|
||||
env?: NodeJS.ProcessEnv,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import { spawnSync, type SpawnSyncOptions } from "node:child_process";
|
||||
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
||||
import { basename, delimiter, join } from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { formatErrorMessage } from "../src/infra/errors.ts";
|
||||
import { writePackageDistInventory } from "./lib/package-dist-inventory.ts";
|
||||
@@ -18,6 +19,10 @@ const requiredControlUiCompressionSuffixes = [".br", ".gz"] as const;
|
||||
const DEFAULT_PREPACK_COMMAND_TIMEOUT_MS = 30 * 60 * 1000;
|
||||
const ALLOW_UNRELEASED_CHANGELOG_ENV = "OPENCLAW_PREPACK_ALLOW_UNRELEASED_CHANGELOG";
|
||||
const PREPARED_RELEASE_ENV = "OPENCLAW_PREPACK_PREPARED";
|
||||
const OCM_INTERNAL_NPM_BIN_ENV = "OCM_INTERNAL_NPM_BIN";
|
||||
const OCM_WORKSPACE_DIRS_ENV = "OPENCLAW_OCM_WORKSPACE_DEPENDENCY_DIRS";
|
||||
const OCM_ADAPTER_BASENAME = "ocm-npm-workspace-deps.mjs";
|
||||
const NPM_COMMAND_ENV = "npm_command";
|
||||
const SELF_CONTAINED_SOURCE_PACK_COMMAND =
|
||||
"node scripts/package-openclaw-for-docker.mjs --allow-unreleased-changelog";
|
||||
|
||||
@@ -28,8 +33,35 @@ type PreparedFileReader = {
|
||||
|
||||
type PackageManifest = {
|
||||
dependencies?: Record<string, unknown>;
|
||||
name?: unknown;
|
||||
};
|
||||
|
||||
function ocmExternalizesWorkspacePackage(packageName: string, env: NodeJS.ProcessEnv): boolean {
|
||||
if (env[NPM_COMMAND_ENV] !== "pack") {
|
||||
return false;
|
||||
}
|
||||
const adapterPath = env[OCM_INTERNAL_NPM_BIN_ENV]?.trim();
|
||||
if (!adapterPath || basename(adapterPath) !== OCM_ADAPTER_BASENAME) {
|
||||
return false;
|
||||
}
|
||||
const workspaceDirs = (env[OCM_WORKSPACE_DIRS_ENV] ?? "")
|
||||
.split(delimiter)
|
||||
.map((entry) => entry.trim())
|
||||
.filter(Boolean);
|
||||
// OCM uses these same manifests to pack and install dependencies beside the root archive.
|
||||
// Require the exact package here so unrelated ambient paths cannot bypass the plain-pack guard.
|
||||
return workspaceDirs.some((workspaceDir) => {
|
||||
try {
|
||||
const manifest = JSON.parse(
|
||||
readFileSync(join(workspaceDir, "package.json"), "utf8"),
|
||||
) as PackageManifest;
|
||||
return manifest.name === packageName;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeFiles(files: Iterable<string>): Set<string> {
|
||||
return new Set(Array.from(files, (file) => file.replace(/\\/g, "/")));
|
||||
}
|
||||
@@ -45,6 +77,9 @@ export function collectSourcePackWorkspaceDependencyErrors(
|
||||
if (typeof aiDependency !== "string" || !aiDependency.trim().startsWith("workspace:")) {
|
||||
return [];
|
||||
}
|
||||
if (ocmExternalizesWorkspacePackage("@openclaw/ai", env)) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
`plain root packing cannot safely resolve @openclaw/ai from ${aiDependency}: pnpm rewrites the workspace dependency to an exact version without bundling the package`,
|
||||
`use \`${SELF_CONTAINED_SOURCE_PACK_COMMAND}\` for a self-contained source package; official npm release automation prepares and publishes @openclaw/ai separately`,
|
||||
|
||||
@@ -92,6 +92,34 @@ describe("collectSourcePackWorkspaceDependencyErrors", () => {
|
||||
OPENCLAW_PREPACK_PREPARED: "1",
|
||||
}),
|
||||
).toEqual([]);
|
||||
expect(
|
||||
collectSourcePackWorkspaceDependencyErrors(rootPackageJson, {
|
||||
npm_command: "pack",
|
||||
OCM_INTERNAL_NPM_BIN: path.join(rootDir, "scripts", "ocm-npm-workspace-deps.mjs"),
|
||||
OPENCLAW_OCM_WORKSPACE_DEPENDENCY_DIRS: aiDir,
|
||||
}),
|
||||
).toEqual([]);
|
||||
expect(
|
||||
collectSourcePackWorkspaceDependencyErrors(rootPackageJson, {
|
||||
npm_command: "pack",
|
||||
OCM_INTERNAL_NPM_BIN: path.join(rootDir, "scripts", "ocm-npm-workspace-deps.mjs"),
|
||||
OPENCLAW_OCM_WORKSPACE_DEPENDENCY_DIRS: rootDir,
|
||||
}),
|
||||
).toHaveLength(2);
|
||||
expect(
|
||||
collectSourcePackWorkspaceDependencyErrors(rootPackageJson, {
|
||||
npm_command: "pack",
|
||||
OCM_INTERNAL_NPM_BIN: path.join(rootDir, "scripts", "other-npm-wrapper.mjs"),
|
||||
OPENCLAW_OCM_WORKSPACE_DEPENDENCY_DIRS: aiDir,
|
||||
}),
|
||||
).toHaveLength(2);
|
||||
expect(
|
||||
collectSourcePackWorkspaceDependencyErrors(rootPackageJson, {
|
||||
npm_command: "publish",
|
||||
OCM_INTERNAL_NPM_BIN: path.join(rootDir, "scripts", "ocm-npm-workspace-deps.mjs"),
|
||||
OPENCLAW_OCM_WORKSPACE_DEPENDENCY_DIRS: aiDir,
|
||||
}),
|
||||
).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user