Skip to content

Commit 26c9885

Browse files
committed
fix: skip stale post-switch update follow-ups
1 parent 1cce188 commit 26c9885

2 files changed

Lines changed: 48 additions & 19 deletions

File tree

src/cli/update-cli.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,9 @@ describe("update-cli", () => {
10131013

10141014
it("skips plugin sync in the old process after switching from package to git", async () => {
10151015
const tempDir = createCaseDir("openclaw-update");
1016+
const completionCacheSpy = vi
1017+
.spyOn(updateCliShared, "tryWriteCompletionCache")
1018+
.mockResolvedValue(undefined);
10161019
mockPackageInstallStatus(tempDir);
10171020
vi.mocked(runGatewayUpdate).mockResolvedValue(
10181021
makeOkUpdateResult({
@@ -1021,6 +1024,7 @@ describe("update-cli", () => {
10211024
after: { version: "2026.4.5" },
10221025
}),
10231026
);
1027+
serviceLoaded.mockResolvedValue(true);
10241028
syncPluginsForUpdateChannel.mockRejectedValue(
10251029
new Error("Config validation failed: old host version"),
10261030
);
@@ -1029,6 +1033,9 @@ describe("update-cli", () => {
10291033

10301034
expect(syncPluginsForUpdateChannel).not.toHaveBeenCalled();
10311035
expect(replaceConfigFile).not.toHaveBeenCalled();
1036+
expect(completionCacheSpy).not.toHaveBeenCalled();
1037+
expect(runRestartScript).not.toHaveBeenCalled();
1038+
expect(runDaemonRestart).not.toHaveBeenCalled();
10321039
expect(defaultRuntime.exit).not.toHaveBeenCalledWith(1);
10331040
expect(
10341041
vi
@@ -1038,6 +1045,14 @@ describe("update-cli", () => {
10381045
).toContain(
10391046
"Skipped plugin update sync in the pre-update CLI process after switching to a git install.",
10401047
);
1048+
expect(
1049+
vi
1050+
.mocked(defaultRuntime.log)
1051+
.mock.calls.map((call) => String(call[0]))
1052+
.join("\n"),
1053+
).toContain(
1054+
"Skipped completion/restart follow-ups in the pre-update CLI process after switching to a git install.",
1055+
);
10411056
});
10421057
it("explains why git updates cannot run with edited files", async () => {
10431058
vi.mocked(defaultRuntime.log).mockClear();

src/cli/update-cli/update-command.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,11 +1075,15 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
10751075
}
10761076
}
10771077

1078+
const postUpdateRoot = result.root;
1079+
10781080
// A package -> git switch still runs inside the pre-update CLI process.
1079-
// Plugin sync/validation can then compare new bundled plugin minima against
1080-
// the old host version and fail even though the install itself succeeded.
1081-
const deferPluginSync = switchToGit && result.mode === "git";
1082-
if (deferPluginSync) {
1081+
// Any follow-up work that re-enters the CLI can then compare new bundled
1082+
// plugin minima against the old host version and fail even though the
1083+
// install itself succeeded. Leave the switched checkout alone and let the
1084+
// new git install handle follow-up commands in a fresh process.
1085+
const deferOldProcessPostUpdateWork = switchToGit && result.mode === "git";
1086+
if (deferOldProcessPostUpdateWork) {
10831087
if (!opts.json) {
10841088
defaultRuntime.log(
10851089
theme.muted(
@@ -1089,28 +1093,38 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
10891093
}
10901094
} else {
10911095
await updatePluginsAfterCoreUpdate({
1092-
root,
1096+
root: postUpdateRoot,
10931097
channel,
10941098
configSnapshot: postUpdateConfigSnapshot,
10951099
opts,
10961100
});
10971101
}
10981102

1099-
await tryWriteCompletionCache(root, Boolean(opts.json));
1100-
await tryInstallShellCompletion({
1101-
jsonMode: Boolean(opts.json),
1102-
skipPrompt: Boolean(opts.yes),
1103-
});
1103+
if (deferOldProcessPostUpdateWork) {
1104+
if (!opts.json) {
1105+
defaultRuntime.log(
1106+
theme.muted(
1107+
"Skipped completion/restart follow-ups in the pre-update CLI process after switching to a git install.",
1108+
),
1109+
);
1110+
}
1111+
} else {
1112+
await tryWriteCompletionCache(postUpdateRoot, Boolean(opts.json));
1113+
await tryInstallShellCompletion({
1114+
jsonMode: Boolean(opts.json),
1115+
skipPrompt: Boolean(opts.yes),
1116+
});
11041117

1105-
await maybeRestartService({
1106-
shouldRestart,
1107-
result,
1108-
opts,
1109-
refreshServiceEnv: refreshGatewayServiceEnv,
1110-
gatewayPort,
1111-
restartScriptPath,
1112-
invocationCwd,
1113-
});
1118+
await maybeRestartService({
1119+
shouldRestart,
1120+
result,
1121+
opts,
1122+
refreshServiceEnv: refreshGatewayServiceEnv,
1123+
gatewayPort,
1124+
restartScriptPath,
1125+
invocationCwd,
1126+
});
1127+
}
11141128

11151129
if (!opts.json) {
11161130
defaultRuntime.log(theme.muted(pickUpdateQuip()));

0 commit comments

Comments
 (0)