mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:10:45 +00:00
build: preserve staged plugin runtime deps
This commit is contained in:
@@ -191,6 +191,11 @@ function copyDeclaredPluginSkillPaths(params) {
|
||||
const shouldExcludeNestedNodeModules = /^node_modules(?:\/|$)/u.test(
|
||||
normalizeManifestRelativePath(raw),
|
||||
);
|
||||
if (shouldExcludeNestedNodeModules) {
|
||||
removePathIfExists(
|
||||
ensurePathInsideRoot(params.distPluginDir, normalizeManifestRelativePath(raw)),
|
||||
);
|
||||
}
|
||||
copySkillPathWithRetry({
|
||||
sourcePath,
|
||||
targetPath,
|
||||
@@ -270,10 +275,9 @@ export function copyBundledPluginMetadata(params = {}) {
|
||||
|
||||
if (fs.existsSync(manifestPath)) {
|
||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
||||
// Generated skill assets live under a dedicated dist-owned directory. Also
|
||||
// remove the older bad node_modules tree so release packs cannot pick it up.
|
||||
// Generated skill assets live under a dedicated dist-owned directory. Runtime
|
||||
// dependency staging owns dist plugin node_modules; do not remove it here.
|
||||
removePathIfExists(path.join(distPluginDir, GENERATED_BUNDLED_SKILLS_DIR));
|
||||
removePathIfExists(path.join(distPluginDir, "node_modules"));
|
||||
const copiedSkills = copyDeclaredPluginSkillPaths({
|
||||
manifest,
|
||||
pluginDir,
|
||||
|
||||
@@ -885,6 +885,17 @@ function resolveRuntimeDepsStampPath(repoRoot, pluginId) {
|
||||
}
|
||||
|
||||
function createRuntimeDepsFingerprint(packageJson, pruneConfig, params = {}) {
|
||||
return createHash("sha256")
|
||||
.update(
|
||||
JSON.stringify({
|
||||
cheapFingerprint: createRuntimeDepsCheapFingerprint(packageJson, pruneConfig, params),
|
||||
rootInstalledRuntimeFingerprint: params.rootInstalledRuntimeFingerprint ?? null,
|
||||
}),
|
||||
)
|
||||
.digest("hex");
|
||||
}
|
||||
|
||||
function createRuntimeDepsCheapFingerprint(packageJson, pruneConfig, params = {}) {
|
||||
const repoRoot = params.repoRoot;
|
||||
const lockfilePath =
|
||||
typeof repoRoot === "string" && repoRoot.length > 0
|
||||
@@ -901,7 +912,6 @@ function createRuntimeDepsFingerprint(packageJson, pruneConfig, params = {}) {
|
||||
globalPruneSuffixes: pruneConfig.globalPruneSuffixes,
|
||||
packageJson,
|
||||
pruneRules: [...pruneConfig.pruneRules.entries()],
|
||||
rootInstalledRuntimeFingerprint: params.rootInstalledRuntimeFingerprint ?? null,
|
||||
rootLockfile,
|
||||
version: runtimeDepsStagingVersion,
|
||||
}),
|
||||
@@ -949,6 +959,7 @@ function removeStaleRuntimeDepsTempDirs(pluginDir) {
|
||||
function stageInstalledRootRuntimeDeps(params) {
|
||||
const {
|
||||
directDependencyPackageRoot = null,
|
||||
cheapFingerprint,
|
||||
fingerprint,
|
||||
packageJson,
|
||||
pluginDir,
|
||||
@@ -990,6 +1001,7 @@ function stageInstalledRootRuntimeDeps(params) {
|
||||
assertPathIsNotSymlink(nodeModulesDir, "remove runtime deps");
|
||||
removePathIfExists(nodeModulesDir);
|
||||
writeJsonAtomically(stampPath, {
|
||||
cheapFingerprint,
|
||||
fingerprint,
|
||||
generatedAt: new Date().toISOString(),
|
||||
});
|
||||
@@ -1029,6 +1041,7 @@ function stageInstalledRootRuntimeDeps(params) {
|
||||
|
||||
replaceDirAtomically(nodeModulesDir, stagedNodeModulesDir);
|
||||
writeJsonAtomically(stampPath, {
|
||||
cheapFingerprint,
|
||||
fingerprint,
|
||||
generatedAt: new Date().toISOString(),
|
||||
});
|
||||
@@ -1078,6 +1091,7 @@ function createRootRuntimeStagingError(params) {
|
||||
function installPluginRuntimeDeps(params) {
|
||||
const {
|
||||
directDependencyPackageRoot = null,
|
||||
cheapFingerprint,
|
||||
fingerprint,
|
||||
packageJson,
|
||||
pluginDir,
|
||||
@@ -1120,6 +1134,7 @@ function installPluginRuntimeDeps(params) {
|
||||
removePathIfExists(nodeModulesDir);
|
||||
}
|
||||
writeJsonAtomically(stampPath, {
|
||||
cheapFingerprint,
|
||||
fingerprint,
|
||||
generatedAt: new Date().toISOString(),
|
||||
});
|
||||
@@ -1151,6 +1166,10 @@ export function stageBundledPluginRuntimeDeps(params = {}) {
|
||||
removePathIfExists(stampPath);
|
||||
continue;
|
||||
}
|
||||
const cheapFingerprint = createRuntimeDepsCheapFingerprint(packageJson, pruneConfig, {
|
||||
repoRoot,
|
||||
});
|
||||
const stamp = readRuntimeDepsStamp(stampPath);
|
||||
const rootInstalledRuntimeFingerprint = resolveInstalledRuntimeClosureFingerprint({
|
||||
directDependencyPackageRoot,
|
||||
packageJson,
|
||||
@@ -1160,7 +1179,6 @@ export function stageBundledPluginRuntimeDeps(params = {}) {
|
||||
repoRoot,
|
||||
rootInstalledRuntimeFingerprint,
|
||||
});
|
||||
const stamp = readRuntimeDepsStamp(stampPath);
|
||||
if (fs.existsSync(nodeModulesDir) && stamp?.fingerprint === fingerprint) {
|
||||
continue;
|
||||
}
|
||||
@@ -1168,6 +1186,7 @@ export function stageBundledPluginRuntimeDeps(params = {}) {
|
||||
stageInstalledRootRuntimeDeps({
|
||||
directDependencyPackageRoot,
|
||||
fingerprint,
|
||||
cheapFingerprint,
|
||||
packageJson,
|
||||
pluginDir,
|
||||
pruneConfig,
|
||||
@@ -1184,6 +1203,7 @@ export function stageBundledPluginRuntimeDeps(params = {}) {
|
||||
installParams: {
|
||||
directDependencyPackageRoot,
|
||||
fingerprint,
|
||||
cheapFingerprint,
|
||||
packageJson,
|
||||
pluginDir,
|
||||
pluginId,
|
||||
|
||||
@@ -172,9 +172,7 @@ describe("copyBundledPluginMetadata", () => {
|
||||
expect(fs.existsSync(path.join(copiedSkillDir, "SKILL.md"))).toBe(true);
|
||||
expect(fs.lstatSync(copiedSkillDir).isSymbolicLink()).toBe(false);
|
||||
expect(fs.existsSync(path.join(copiedSkillDir, "node_modules"))).toBe(false);
|
||||
expect(fs.existsSync(path.join(bundledPluginDir(repoRoot, "tlon"), "node_modules"))).toBe(
|
||||
false,
|
||||
);
|
||||
expect(fs.existsSync(staleNodeModulesSkillDir)).toBe(false);
|
||||
expectBundledSkills(repoRoot, "tlon", ["./bundled-skills/@tloncorp/tlon-skill"]);
|
||||
});
|
||||
|
||||
@@ -217,7 +215,7 @@ describe("copyBundledPluginMetadata", () => {
|
||||
expect(fs.existsSync(path.join(repoRoot, "dist", "extensions", "tlon", "bundled-skills"))).toBe(
|
||||
false,
|
||||
);
|
||||
expect(fs.existsSync(staleNodeModulesDir)).toBe(false);
|
||||
expect(fs.existsSync(staleNodeModulesDir)).toBe(true);
|
||||
});
|
||||
|
||||
it("retries transient skill copy races from concurrent runtime postbuilds", () => {
|
||||
|
||||
Reference in New Issue
Block a user