mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-14 10:26:05 +00:00
* build(docker): package selected external plugins * test(docker): auto-clean plugin fixture * fix(docker): preserve selected image provenance * fix(docker): accept manifest-only plugin selections * fix(docker): resolve selected plugin manifest ids * fix(docker): isolate resolved plugin selection
63 lines
2.4 KiB
TypeScript
63 lines
2.4 KiB
TypeScript
import { spawnSync } from "node:child_process";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
import { useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js";
|
|
|
|
const repoRoot = path.resolve(fileURLToPath(new URL("../..", import.meta.url)));
|
|
const selectorScript = path.join(repoRoot, "scripts/lib/docker-plugin-selection.mjs");
|
|
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
|
|
|
|
function writePlugin(extensionsRoot: string, dirName: string, manifestId?: string) {
|
|
const pluginDir = path.join(extensionsRoot, dirName);
|
|
fs.mkdirSync(pluginDir, { recursive: true });
|
|
fs.writeFileSync(path.join(pluginDir, "package.json"), `${JSON.stringify({ name: dirName })}\n`);
|
|
if (manifestId) {
|
|
fs.writeFileSync(
|
|
path.join(pluginDir, "openclaw.plugin.json"),
|
|
`${JSON.stringify({ id: manifestId })}\n`,
|
|
);
|
|
}
|
|
}
|
|
|
|
function runSelector(extensionsRoot: string, selection: string) {
|
|
return spawnSync(process.execPath, [selectorScript, extensionsRoot, selection], {
|
|
encoding: "utf8",
|
|
});
|
|
}
|
|
|
|
describe("Docker plugin selection", () => {
|
|
it("resolves manifest ids and source directory names deterministically", () => {
|
|
const extensionsRoot = tempDirs.make("openclaw-docker-plugin-selection-");
|
|
writePlugin(extensionsRoot, "source-only");
|
|
writePlugin(extensionsRoot, "provider-source", "provider-id");
|
|
|
|
const result = runSelector(
|
|
extensionsRoot,
|
|
"source-only,provider-id provider-source,provider-id",
|
|
);
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stderr).toBe("");
|
|
expect(result.stdout).toBe("provider-source\nsource-only\n");
|
|
});
|
|
|
|
it("fails closed for unknown, invalid, and ambiguous ids", () => {
|
|
const extensionsRoot = tempDirs.make("openclaw-docker-plugin-selection-errors-");
|
|
writePlugin(extensionsRoot, "shared");
|
|
writePlugin(extensionsRoot, "other-source", "shared");
|
|
|
|
for (const [selection, message] of [
|
|
["missing-plugin", "unknown OPENCLAW_EXTENSIONS plugin id: missing-plugin"],
|
|
["../invalid", "invalid OPENCLAW_EXTENSIONS plugin id: ../invalid"],
|
|
["shared", "ambiguous OPENCLAW_EXTENSIONS plugin id: shared"],
|
|
] as const) {
|
|
const result = runSelector(extensionsRoot, selection);
|
|
expect(result.status).toBe(1);
|
|
expect(result.stdout).toBe("");
|
|
expect(result.stderr).toContain(message);
|
|
}
|
|
});
|
|
});
|