fix(build): address bundled plugin prune review

This commit is contained in:
Ayaan Zaidi
2026-04-08 20:25:49 +05:30
parent b28fe1b92f
commit 66ec8909bd
3 changed files with 61 additions and 12 deletions

View File

@@ -124,7 +124,7 @@ export function pruneBundledPluginSourceNodeModules(params = {}) {
}
for (const entry of readDir(extensionsDir, { withFileTypes: true })) {
if (!entry.isDirectory()) {
if (!entry.isDirectory() || entry.isSymbolicLink()) {
continue;
}
@@ -154,6 +154,19 @@ export function runBundledPluginPostinstall(params = {}) {
const spawn = params.spawnSync ?? spawnSync;
const pathExists = params.existsSync ?? existsSync;
const log = params.log ?? console;
if (isSourceCheckoutRoot({ packageRoot, existsSync: pathExists })) {
try {
pruneBundledPluginSourceNodeModules({
extensionsDir: join(packageRoot, "extensions"),
existsSync: pathExists,
readdirSync: params.readdirSync,
rmSync: params.rmSync,
});
} catch (e) {
log.warn(`[postinstall] could not prune bundled plugin source node_modules: ${String(e)}`);
}
return;
}
if (
!shouldRunBundledPluginPostinstall({
env,
@@ -164,13 +177,6 @@ export function runBundledPluginPostinstall(params = {}) {
) {
return;
}
if (isSourceCheckoutRoot({ packageRoot, existsSync: pathExists })) {
pruneBundledPluginSourceNodeModules({
extensionsDir: join(packageRoot, "extensions"),
existsSync: pathExists,
});
return;
}
const runtimeDeps =
params.runtimeDeps ??
discoverBundledPluginRuntimeDeps({ extensionsDir, existsSync: pathExists });

View File

@@ -60,9 +60,6 @@ function pruneSourceCheckoutBundledPluginNodeModules() {
});
}
pruneSourceCheckoutBundledPluginNodeModules();
pruneStaleRuntimeSymlinks();
function findFatalUnresolvedImport(lines) {
for (const line of lines) {
if (!UNRESOLVED_IMPORT_RE.test(line)) {
@@ -112,6 +109,8 @@ function isMainModule() {
}
if (isMainModule()) {
pruneSourceCheckoutBundledPluginNodeModules();
pruneStaleRuntimeSymlinks();
const invocation = resolveTsdownBuildInvocation();
const result = spawnSync(invocation.command, invocation.args, invocation.options);

View File

@@ -121,9 +121,9 @@ describe("bundled plugin postinstall", () => {
runBundledPluginPostinstall({
env: { HOME: "/tmp/home" },
extensionsDir,
packageRoot,
spawnSync,
log: { log: vi.fn(), warn: vi.fn() },
});
await expect(fs.stat(path.join(extensionsDir, "acpx", "node_modules"))).rejects.toMatchObject({
@@ -132,6 +132,31 @@ describe("bundled plugin postinstall", () => {
expect(spawnSync).not.toHaveBeenCalled();
});
it("keeps source-checkout prune non-fatal", async () => {
const packageRoot = await createTempDirAsync("openclaw-source-checkout-prune-error-");
const extensionsDir = path.join(packageRoot, "extensions");
await fs.mkdir(path.join(packageRoot, ".git"), { recursive: true });
await fs.mkdir(path.join(packageRoot, "src"), { recursive: true });
await fs.mkdir(path.join(extensionsDir, "acpx"), { recursive: true });
await fs.writeFile(path.join(extensionsDir, "acpx", "package.json"), "{}\n");
const warn = vi.fn();
expect(() =>
runBundledPluginPostinstall({
env: { HOME: "/tmp/home" },
packageRoot,
rmSync: vi.fn(() => {
throw new Error("locked");
}),
log: { log: vi.fn(), warn },
}),
).not.toThrow();
expect(warn).toHaveBeenCalledWith(
"[postinstall] could not prune bundled plugin source node_modules: Error: locked",
);
});
it("runs nested local installs with sanitized env when the sentinel package is missing", async () => {
const extensionsDir = await createExtensionsDir();
const packageRoot = path.dirname(path.dirname(extensionsDir));
@@ -354,4 +379,23 @@ describe("bundled plugin postinstall", () => {
fs.stat(path.join(extensionsDir, "fixtures", "node_modules")),
).resolves.toBeTruthy();
});
it("skips symlink entries when pruning source-checkout bundled plugin node_modules", () => {
const removePath = vi.fn();
pruneBundledPluginSourceNodeModules({
extensionsDir: "/repo/extensions",
existsSync: vi.fn((value) => value === "/repo/extensions"),
readdirSync: vi.fn(() => [
{
name: "acpx",
isDirectory: () => true,
isSymbolicLink: () => true,
},
]),
rmSync: removePath,
});
expect(removePath).not.toHaveBeenCalled();
});
});