plugins: trim staged runtime cargo

This commit is contained in:
Gustavo Madeira Santana
2026-04-13 18:02:56 -04:00
parent e04a63d08a
commit b5dcc11273
3 changed files with 194 additions and 19 deletions

View File

@@ -62,12 +62,48 @@ function dependencyVersionSatisfied(spec, installedVersion) {
return semverSatisfies(installedVersion, spec, { includePrerelease: false });
}
const stagedRuntimeDepPruneRules = new Map([
const defaultStagedRuntimeDepGlobalPruneSuffixes = [".map"];
const defaultStagedRuntimeDepPruneRules = new Map([
// Type declarations only; runtime resolves through lib/es entrypoints.
["@larksuiteoapi/node-sdk", ["types"]],
["@larksuiteoapi/node-sdk", { paths: ["types"] }],
[
"@matrix-org/matrix-sdk-crypto-nodejs",
{
paths: ["index.d.ts", "README.md", "CHANGELOG.md", "RELEASING.md", ".node-version"],
},
],
[
"@matrix-org/matrix-sdk-crypto-wasm",
{
paths: [
"index.d.ts",
"pkg/matrix_sdk_crypto_wasm.d.ts",
"pkg/matrix_sdk_crypto_wasm_bg.wasm.d.ts",
"README.md",
],
},
],
[
"matrix-js-sdk",
{
paths: ["src", "CHANGELOG.md", "CONTRIBUTING.rst", "README.md", "release.sh"],
suffixes: [".d.ts"],
},
],
["matrix-widget-api", { paths: ["src"], suffixes: [".d.ts"] }],
["oidc-client-ts", { paths: ["README.md"], suffixes: [".d.ts"] }],
["music-metadata", { paths: ["README.md"], suffixes: [".d.ts"] }],
]);
const runtimeDepsStagingVersion = 2;
function resolveRuntimeDepPruneConfig(params = {}) {
return {
globalPruneSuffixes:
params.stagedRuntimeDepGlobalPruneSuffixes ?? defaultStagedRuntimeDepGlobalPruneSuffixes,
pruneRules: params.stagedRuntimeDepPruneRules ?? defaultStagedRuntimeDepPruneRules,
};
}
function collectInstalledRuntimeClosure(rootNodeModulesDir, dependencySpecs) {
const packageCache = new Map();
const closure = new Set();
@@ -102,20 +138,73 @@ function collectInstalledRuntimeClosure(rootNodeModulesDir, dependencySpecs) {
return [...closure];
}
function pruneStagedInstalledDependencyCargo(nodeModulesDir, depName) {
const prunePaths = stagedRuntimeDepPruneRules.get(depName);
if (!prunePaths) {
function walkFiles(rootDir, visitFile) {
if (!fs.existsSync(rootDir)) {
return;
}
const depRoot = dependencyNodeModulesPath(nodeModulesDir, depName);
for (const relativePath of prunePaths) {
removePathIfExists(path.join(depRoot, relativePath));
const queue = [rootDir];
while (queue.length > 0) {
const currentDir = queue.shift();
for (const entry of fs.readdirSync(currentDir, { withFileTypes: true })) {
const fullPath = path.join(currentDir, entry.name);
if (entry.isDirectory()) {
queue.push(fullPath);
continue;
}
if (entry.isFile()) {
visitFile(fullPath);
}
}
}
}
function pruneStagedRuntimeDependencyCargo(nodeModulesDir) {
for (const depName of stagedRuntimeDepPruneRules.keys()) {
pruneStagedInstalledDependencyCargo(nodeModulesDir, depName);
function pruneDependencyFilesBySuffixes(depRoot, suffixes) {
if (!suffixes || suffixes.length === 0 || !fs.existsSync(depRoot)) {
return;
}
walkFiles(depRoot, (fullPath) => {
if (suffixes.some((suffix) => fullPath.endsWith(suffix))) {
removePathIfExists(fullPath);
}
});
}
function pruneStagedInstalledDependencyCargo(nodeModulesDir, depName, pruneConfig) {
const depRoot = dependencyNodeModulesPath(nodeModulesDir, depName);
const pruneRule = pruneConfig.pruneRules.get(depName);
for (const relativePath of pruneRule?.paths ?? []) {
removePathIfExists(path.join(depRoot, relativePath));
}
pruneDependencyFilesBySuffixes(depRoot, pruneConfig.globalPruneSuffixes);
pruneDependencyFilesBySuffixes(depRoot, pruneRule?.suffixes ?? []);
}
function listInstalledDependencyNames(nodeModulesDir) {
if (!fs.existsSync(nodeModulesDir)) {
return [];
}
const names = [];
for (const entry of fs.readdirSync(nodeModulesDir, { withFileTypes: true })) {
if (!entry.isDirectory()) {
continue;
}
if (entry.name.startsWith("@")) {
const scopeDir = path.join(nodeModulesDir, entry.name);
for (const scopedEntry of fs.readdirSync(scopeDir, { withFileTypes: true })) {
if (scopedEntry.isDirectory()) {
names.push(`${entry.name}/${scopedEntry.name}`);
}
}
continue;
}
names.push(entry.name);
}
return names;
}
function pruneStagedRuntimeDependencyCargo(nodeModulesDir, pruneConfig) {
for (const depName of listInstalledDependencyNames(nodeModulesDir)) {
pruneStagedInstalledDependencyCargo(nodeModulesDir, depName, pruneConfig);
}
}
@@ -174,12 +263,13 @@ function resolveRuntimeDepsStampPath(pluginDir) {
return path.join(pluginDir, ".openclaw-runtime-deps-stamp.json");
}
function createRuntimeDepsFingerprint(packageJson) {
function createRuntimeDepsFingerprint(packageJson, pruneConfig) {
return createHash("sha256")
.update(
JSON.stringify({
globalPruneSuffixes: pruneConfig.globalPruneSuffixes,
packageJson,
pruneRules: [...stagedRuntimeDepPruneRules.entries()],
pruneRules: [...pruneConfig.pruneRules.entries()],
version: runtimeDepsStagingVersion,
}),
)
@@ -198,7 +288,7 @@ function readRuntimeDepsStamp(stampPath) {
}
function stageInstalledRootRuntimeDeps(params) {
const { fingerprint, packageJson, pluginDir, repoRoot } = params;
const { fingerprint, packageJson, pluginDir, pruneConfig, repoRoot } = params;
const dependencySpecs = {
...packageJson.dependencies,
...packageJson.optionalDependencies,
@@ -230,7 +320,7 @@ function stageInstalledRootRuntimeDeps(params) {
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
fs.cpSync(sourcePath, targetPath, { recursive: true, force: true, dereference: true });
}
pruneStagedRuntimeDependencyCargo(stagedNodeModulesDir);
pruneStagedRuntimeDependencyCargo(stagedNodeModulesDir, pruneConfig);
replaceDir(nodeModulesDir, stagedNodeModulesDir);
writeJson(stampPath, {
@@ -244,10 +334,10 @@ function stageInstalledRootRuntimeDeps(params) {
}
function installPluginRuntimeDeps(params) {
const { fingerprint, packageJson, pluginDir, pluginId, repoRoot } = params;
const { fingerprint, packageJson, pluginDir, pluginId, pruneConfig, repoRoot } = params;
if (
repoRoot &&
stageInstalledRootRuntimeDeps({ fingerprint, packageJson, pluginDir, repoRoot })
stageInstalledRootRuntimeDeps({ fingerprint, packageJson, pluginDir, pruneConfig, repoRoot })
) {
return;
}
@@ -291,7 +381,7 @@ function installPluginRuntimeDeps(params) {
);
}
pruneStagedRuntimeDependencyCargo(stagedNodeModulesDir);
pruneStagedRuntimeDependencyCargo(stagedNodeModulesDir, pruneConfig);
replaceDir(nodeModulesDir, stagedNodeModulesDir);
writeJson(stampPath, {
@@ -325,6 +415,7 @@ export function stageBundledPluginRuntimeDeps(params = {}) {
const installPluginRuntimeDepsImpl =
params.installPluginRuntimeDepsImpl ?? installPluginRuntimeDeps;
const installAttempts = params.installAttempts ?? 3;
const pruneConfig = resolveRuntimeDepPruneConfig(params);
for (const pluginDir of listBundledPluginRuntimeDirs(repoRoot)) {
const pluginId = path.basename(pluginDir);
const packageJson = sanitizeBundledManifestForRuntimeInstall(pluginDir);
@@ -335,7 +426,7 @@ export function stageBundledPluginRuntimeDeps(params = {}) {
removePathIfExists(stampPath);
continue;
}
const fingerprint = createRuntimeDepsFingerprint(packageJson);
const fingerprint = createRuntimeDepsFingerprint(packageJson, pruneConfig);
const stamp = readRuntimeDepsStamp(stampPath);
if (fs.existsSync(nodeModulesDir) && stamp?.fingerprint === fingerprint) {
continue;
@@ -348,6 +439,7 @@ export function stageBundledPluginRuntimeDeps(params = {}) {
packageJson,
pluginDir,
pluginId,
pruneConfig,
repoRoot,
},
});