mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:40:44 +00:00
fix(update): skip legacy parent doctor config writes
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
resolveDoctorHealthContributions,
|
||||
shouldSkipLegacyUpdateDoctorMetadataWrite,
|
||||
shouldSkipLegacyUpdateDoctorConfigWrite,
|
||||
} from "./doctor-health-contributions.js";
|
||||
|
||||
describe("doctor health contributions", () => {
|
||||
@@ -30,54 +30,39 @@ describe("doctor health contributions", () => {
|
||||
expect(ids.indexOf("doctor:command-owner")).toBeLessThan(ids.indexOf("doctor:write-config"));
|
||||
});
|
||||
|
||||
it("skips metadata-only doctor writes under legacy update parents", () => {
|
||||
it("skips doctor config writes under legacy update parents", () => {
|
||||
expect(
|
||||
shouldSkipLegacyUpdateDoctorMetadataWrite({
|
||||
shouldSkipLegacyUpdateDoctorConfigWrite({
|
||||
env: { OPENCLAW_UPDATE_IN_PROGRESS: "1" },
|
||||
before: { gateway: { mode: "local" }, meta: { lastTouchedVersion: "2026.4.26" } },
|
||||
after: {
|
||||
gateway: { mode: "local" },
|
||||
meta: { lastTouchedVersion: "2026.4.27" },
|
||||
wizard: { lastRunCommand: "doctor" },
|
||||
},
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps real doctor repairs writable during update", () => {
|
||||
it("keeps doctor writes outside legacy update writable", () => {
|
||||
expect(
|
||||
shouldSkipLegacyUpdateDoctorMetadataWrite({
|
||||
env: { OPENCLAW_UPDATE_IN_PROGRESS: "1" },
|
||||
before: { gateway: { mode: "local" } },
|
||||
after: { gateway: { mode: "remote" } },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps repair writes from doctor config preflight writable during legacy update", () => {
|
||||
expect(
|
||||
shouldSkipLegacyUpdateDoctorMetadataWrite({
|
||||
env: { OPENCLAW_UPDATE_IN_PROGRESS: "1" },
|
||||
hasPendingConfigWrite: true,
|
||||
before: { gateway: { mode: "remote" } },
|
||||
after: {
|
||||
gateway: { mode: "remote" },
|
||||
meta: { lastTouchedVersion: "2026.4.27" },
|
||||
wizard: { lastRunCommand: "doctor" },
|
||||
},
|
||||
shouldSkipLegacyUpdateDoctorConfigWrite({
|
||||
env: {},
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps current update parents writable", () => {
|
||||
expect(
|
||||
shouldSkipLegacyUpdateDoctorMetadataWrite({
|
||||
shouldSkipLegacyUpdateDoctorConfigWrite({
|
||||
env: {
|
||||
OPENCLAW_UPDATE_IN_PROGRESS: "1",
|
||||
OPENCLAW_UPDATE_PARENT_SUPPORTS_DOCTOR_CONFIG_WRITE: "1",
|
||||
},
|
||||
before: { meta: { lastTouchedVersion: "2026.4.26" } },
|
||||
after: { meta: { lastTouchedVersion: "2026.4.27" } },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("treats falsey update env values as normal writes", () => {
|
||||
expect(
|
||||
shouldSkipLegacyUpdateDoctorConfigWrite({
|
||||
env: {
|
||||
OPENCLAW_UPDATE_IN_PROGRESS: "0",
|
||||
},
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import fs from "node:fs";
|
||||
import { isDeepStrictEqual } from "node:util";
|
||||
import type { probeGatewayMemoryStatus } from "../commands/doctor-gateway-health.js";
|
||||
import type { DoctorOptions, DoctorPrompter } from "../commands/doctor-prompter.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
@@ -52,16 +51,8 @@ function isTruthyEnvValue(value: string | undefined): boolean {
|
||||
return normalized !== "" && normalized !== "0" && normalized !== "false" && normalized !== "no";
|
||||
}
|
||||
|
||||
function omitDoctorWriteMetadata(cfg: OpenClawConfig): OpenClawConfig {
|
||||
const { meta: _meta, wizard: _wizard, ...rest } = cfg;
|
||||
return rest;
|
||||
}
|
||||
|
||||
export function shouldSkipLegacyUpdateDoctorMetadataWrite(params: {
|
||||
export function shouldSkipLegacyUpdateDoctorConfigWrite(params: {
|
||||
env: NodeJS.ProcessEnv;
|
||||
hasPendingConfigWrite?: boolean;
|
||||
before: OpenClawConfig;
|
||||
after: OpenClawConfig;
|
||||
}): boolean {
|
||||
if (!isTruthyEnvValue(params.env.OPENCLAW_UPDATE_IN_PROGRESS)) {
|
||||
return false;
|
||||
@@ -69,13 +60,7 @@ export function shouldSkipLegacyUpdateDoctorMetadataWrite(params: {
|
||||
if (isTruthyEnvValue(params.env[UPDATE_PARENT_SUPPORTS_DOCTOR_CONFIG_WRITE_ENV])) {
|
||||
return false;
|
||||
}
|
||||
if (params.hasPendingConfigWrite === true) {
|
||||
return false;
|
||||
}
|
||||
return isDeepStrictEqual(
|
||||
omitDoctorWriteMetadata(params.before),
|
||||
omitDoctorWriteMetadata(params.after),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
function createDoctorHealthContribution(params: {
|
||||
@@ -534,15 +519,8 @@ async function runWriteConfigHealth(ctx: DoctorHealthFlowContext): Promise<void>
|
||||
command: "doctor",
|
||||
mode: resolveDoctorMode(ctx.cfg),
|
||||
});
|
||||
if (
|
||||
shouldSkipLegacyUpdateDoctorMetadataWrite({
|
||||
env: ctx.env ?? process.env,
|
||||
hasPendingConfigWrite: ctx.configResult.shouldWriteConfig === true,
|
||||
before: ctx.cfgForPersistence,
|
||||
after: ctx.cfg,
|
||||
})
|
||||
) {
|
||||
ctx.runtime.log("Skipping doctor metadata-only config write during legacy update handoff.");
|
||||
if (shouldSkipLegacyUpdateDoctorConfigWrite({ env: ctx.env })) {
|
||||
ctx.runtime.log("Skipping doctor config write during legacy update handoff.");
|
||||
return;
|
||||
}
|
||||
await replaceConfigFile({
|
||||
|
||||
Reference in New Issue
Block a user