fix: keep configured plugin repair scoped

This commit is contained in:
Peter Steinberger
2026-05-02 16:39:39 +01:00
parent 1885f05bae
commit d3519ce42c
3 changed files with 84 additions and 1 deletions

View File

@@ -41,6 +41,7 @@ FAILURE_PHASE=""
FAILURE_MESSAGE=""
gateway_pid=""
clawhub_fixture_pid=""
configured_plugin_installs_clawhub_fixture_owned=""
baseline_spec=""
baseline_version=""
baseline_version_expected="0"
@@ -288,6 +289,7 @@ configured_plugin_installs_enabled() {
start_configured_plugin_installs_clawhub_fixture() {
configured_plugin_installs_enabled || return 0
configured_plugin_installs_clawhub_fixture_owned=""
if [ -n "${OPENCLAW_CLAWHUB_URL:-}" ] || [ -n "${CLAWHUB_URL:-}" ]; then
return 0
fi
@@ -318,6 +320,7 @@ NODE
for _ in $(seq 1 100); do
if [ -s "$port_file" ]; then
export OPENCLAW_CLAWHUB_URL="http://127.0.0.1:$(cat "$port_file")"
configured_plugin_installs_clawhub_fixture_owned="1"
echo "Configured plugin install scenario using ClawHub 404 fixture: $OPENCLAW_CLAWHUB_URL"
return 0
fi
@@ -329,6 +332,9 @@ NODE
assert_configured_plugin_installs_clawhub_attempted() {
configured_plugin_installs_enabled || return 0
if [ "${configured_plugin_installs_clawhub_fixture_owned:-}" != "1" ]; then
return 0
fi
local requests_file="$ARTIFACT_ROOT/clawhub-not-found-requests.jsonl"
if ! grep -q '/api/v1/packages/%40openclaw%2Fmatrix' "$requests_file" 2>/dev/null; then
echo "configured plugin install scenario did not attempt ClawHub for @openclaw/matrix" >&2

View File

@@ -1,10 +1,32 @@
import { describe, expect, it } from "vitest";
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
resolveDoctorHealthContributions,
shouldSkipLegacyUpdateDoctorConfigWrite,
} from "./doctor-health-contributions.js";
const mocks = vi.hoisted(() => ({
maybeRunConfiguredPluginInstallReleaseStep: vi.fn(),
note: vi.fn(),
}));
vi.mock("../commands/doctor/shared/release-configured-plugin-installs.js", () => ({
maybeRunConfiguredPluginInstallReleaseStep: mocks.maybeRunConfiguredPluginInstallReleaseStep,
}));
vi.mock("../terminal/note.js", () => ({
note: mocks.note,
}));
vi.mock("../version.js", () => ({
VERSION: "2026.5.2-test",
}));
describe("doctor health contributions", () => {
beforeEach(() => {
mocks.maybeRunConfiguredPluginInstallReleaseStep.mockReset();
mocks.note.mockReset();
});
it("runs release configured plugin install repair before plugin registry and final config writes", () => {
const ids = resolveDoctorHealthContributions().map((entry) => entry.id);
@@ -15,6 +37,58 @@ describe("doctor health contributions", () => {
);
expect(ids.indexOf("doctor:plugin-registry")).toBeLessThan(ids.indexOf("doctor:write-config"));
});
it("keeps release configured plugin installs repair-only", async () => {
const contribution = resolveDoctorHealthContributions().find(
(entry) => entry.id === "doctor:release-configured-plugin-installs",
);
expect(contribution).toBeDefined();
const ctx = {
cfg: {},
configResult: { cfg: {}, sourceLastTouchedVersion: "2026.4.29" },
sourceConfigValid: true,
prompter: { shouldRepair: false },
env: {},
} as Parameters<NonNullable<typeof contribution>["run"]>[0];
await contribution?.run(ctx);
expect(mocks.maybeRunConfiguredPluginInstallReleaseStep).not.toHaveBeenCalled();
expect(mocks.note).not.toHaveBeenCalled();
});
it("stamps release configured plugin installs after repair changes", async () => {
mocks.maybeRunConfiguredPluginInstallReleaseStep.mockResolvedValue({
changes: ["Installed configured plugin matrix."],
warnings: [],
touchedConfig: true,
});
const contribution = resolveDoctorHealthContributions().find(
(entry) => entry.id === "doctor:release-configured-plugin-installs",
);
expect(contribution).toBeDefined();
const ctx = {
cfg: {},
configResult: { cfg: {}, sourceLastTouchedVersion: "2026.4.29" },
sourceConfigValid: true,
prompter: { shouldRepair: true },
env: {},
} as Parameters<NonNullable<typeof contribution>["run"]>[0];
await contribution?.run(ctx);
expect(mocks.maybeRunConfiguredPluginInstallReleaseStep).toHaveBeenCalledWith({
cfg: {},
env: {},
touchedVersion: "2026.4.29",
});
expect(mocks.note).toHaveBeenCalledWith(
"Installed configured plugin matrix.",
"Doctor changes",
);
expect(ctx.cfg.meta?.lastTouchedVersion).toBe("2026.5.2-test");
});
it("checks command owner configuration before final config writes", () => {
const ids = resolveDoctorHealthContributions().map((entry) => entry.id);

View File

@@ -275,6 +275,9 @@ async function runReleaseConfiguredPluginInstallsHealth(
if (!ctx.sourceConfigValid) {
return;
}
if (!ctx.prompter.shouldRepair) {
return;
}
const { maybeRunConfiguredPluginInstallReleaseStep } =
await import("../commands/doctor/shared/release-configured-plugin-installs.js");
const { note } = await import("../terminal/note.js");