fix(plugins): harden bundled install/uninstall sweep

Fix bundled plugin install/uninstall sweep coverage and avoid persisting invalid placeholder config for config-gated bundled plugins.
This commit is contained in:
Vincent Koc
2026-04-27 01:57:40 -07:00
committed by GitHub
parent 7421112898
commit caba05b94a
15 changed files with 550 additions and 15 deletions

View File

@@ -9,6 +9,8 @@ const INSTALL_E2E_RUNNER_PATH = "scripts/docker/install-sh-e2e/run.sh";
const LIVE_CLI_BACKEND_DOCKER_PATH = "scripts/test-live-cli-backend-docker.sh";
const LIVE_BUILD_DOCKER_PATH = "scripts/test-live-build-docker.sh";
const OPENAI_WEB_SEARCH_MINIMAL_E2E_PATH = "scripts/e2e/openai-web-search-minimal-docker.sh";
const BUNDLED_PLUGIN_INSTALL_UNINSTALL_E2E_PATH =
"scripts/e2e/bundled-plugin-install-uninstall-docker.sh";
const PLUGINS_DOCKER_E2E_PATH = "scripts/e2e/plugins-docker.sh";
const PLUGIN_UPDATE_DOCKER_E2E_PATH = "scripts/e2e/plugin-update-unchanged-docker.sh";
const DOCTOR_SWITCH_DOCKER_E2E_PATH = "scripts/e2e/doctor-install-switch-docker.sh";
@@ -90,6 +92,7 @@ describe("docker build helper", () => {
const scenarios = readFileSync(DOCKER_E2E_SCENARIOS_PATH, "utf8");
expect(scenarios).toContain('"plugins-offline"');
expect(scenarios).toContain('"bundled-plugin-install-uninstall"');
expect(scenarios).toContain("OPENCLAW_PLUGINS_E2E_CLAWHUB=0");
expect(scenarios).toContain('"bundled-channel-deps-compat"');
expect(scenarios).toContain("test:docker:bundled-channel-deps:fast");
@@ -125,6 +128,19 @@ describe("docker build helper", () => {
);
});
it("keeps bundled plugin install/uninstall sweep chunkable", () => {
const runner = readFileSync(BUNDLED_PLUGIN_INSTALL_UNINSTALL_E2E_PATH, "utf8");
expect(runner).toContain("OPENCLAW_BUNDLED_PLUGIN_SWEEP_TOTAL");
expect(runner).toContain("OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX");
expect(runner).toContain('"openclaw.plugin.json"');
expect(runner).toContain("read -r plugin_id plugin_dir requires_config");
expect(runner).toContain('node "$OPENCLAW_ENTRY" plugins install "$plugin_id"');
expect(runner).toContain('node "$OPENCLAW_ENTRY" plugins uninstall "$plugin_id" --force');
expect(runner).toContain("assert_installed");
expect(runner).toContain("assert_uninstalled");
});
it("passes installer tag env to bash, not curl", () => {
const runner = readFileSync(INSTALL_E2E_RUNNER_PATH, "utf8");

View File

@@ -111,6 +111,23 @@ describe("scripts/lib/docker-e2e-plan", () => {
]);
});
it("plans bundled plugin install/uninstall as package-backed plugin coverage", () => {
const plan = planFor({ selectedLaneNames: ["bundled-plugin-install-uninstall"] });
expect(plan.lanes).toEqual([
expect.objectContaining({
imageKind: "functional",
live: false,
name: "bundled-plugin-install-uninstall",
resources: expect.arrayContaining(["docker", "npm"]),
}),
]);
expect(plan.needs).toMatchObject({
functionalImage: true,
package: true,
});
});
it("rejects unknown selected lanes with the available lane names", () => {
expect(() => planFor({ selectedLaneNames: ["missing-lane"] })).toThrow(
/OPENCLAW_DOCKER_ALL_LANES unknown lane\(s\): missing-lane/u,