@@ -20,6 +20,7 @@ import path from "node:path";
|
20 | 20 | import { GATEWAY_SERVICE_RUNTIME_PID_ENV } from "../daemon/constants.js"; |
21 | 21 | import { resolveGatewayInstallEntrypoint } from "../daemon/gateway-entrypoint.js"; |
22 | 22 | import { runCommandWithTimeout } from "../process/exec.js"; |
| 23 | +import { trimLogTail } from "./restart-sentinel.js"; |
23 | 24 | import { resolveStableNodePath } from "./stable-node-path.js"; |
24 | 25 | import { |
25 | 26 | DEFAULT_GIT_CHANNEL, |
@@ -85,38 +86,20 @@ const defaultFinalizeSpawner: PostCoreFinalizeSpawner = async ({ argv, cwd, time
|
85 | 86 | return { code: res.code, ...(res.stderr ? { stderr: res.stderr } : {}) }; |
86 | 87 | }; |
87 | 88 | |
88 | | -function normalizeOptionalString(value: string | null | undefined): string | undefined { |
89 | | -const trimmed = value?.trim(); |
90 | | -return trimmed ? trimmed : undefined; |
91 | | -} |
92 | | - |
93 | | -// A no-op git update (same SHA and version) has nothing new to converge against, |
94 | | -// so skip finalize to avoid an unnecessary doctor/convergence run. Mirrors the |
95 | | -// CLI's `shouldResumePostCoreUpdateInFreshProcess` git resume gate. |
96 | | -function gitCoreChanged(result: UpdateRunResult): boolean { |
97 | | -const beforeSha = normalizeOptionalString(result.before?.sha); |
98 | | -const afterSha = normalizeOptionalString(result.after?.sha); |
99 | | -if (beforeSha && afterSha && beforeSha !== afterSha) { |
100 | | -return true; |
101 | | -} |
102 | | -const beforeVersion = normalizeOptionalString(result.before?.version); |
103 | | -const afterVersion = normalizeOptionalString(result.after?.version); |
104 | | -return Boolean(beforeVersion && afterVersion && beforeVersion !== afterVersion); |
105 | | -} |
106 | | - |
107 | 89 | // Only git/source updates routed through `runGatewayUpdate` defer-and-drop |
108 | 90 | // plugin convergence. Package-manager/global installs already converge because |
109 | 91 | // the RPC routes them through `startManagedServiceUpdateHandoff`, which |
110 | | -// re-enters the full `openclaw update` CLI. |
| 92 | +// re-enters the full `openclaw update` CLI. Re-run convergence on no-op retries: |
| 93 | +// an earlier finalizer failure must not be bypassed by a same-SHA update that |
| 94 | +// would otherwise restart the gateway with stale plugins. |
111 | 95 | function isGitUpdateNeedingFinalize( |
112 | 96 | result: UpdateRunResult, |
113 | 97 | ): result is UpdateRunResult & { root: string } { |
114 | 98 | return ( |
115 | 99 | result.status === "ok" && |
116 | 100 | result.mode === "git" && |
117 | 101 | typeof result.root === "string" && |
118 | | -result.root.length > 0 && |
119 | | -gitCoreChanged(result) |
| 102 | +result.root.length > 0 |
120 | 103 | ); |
121 | 104 | } |
122 | 105 | |
@@ -240,7 +223,7 @@ export function foldPostCoreFinalizeIntoResult(
|
240 | 223 | cwd: result.root ?? process.cwd(), |
241 | 224 | durationMs: 0, |
242 | 225 | exitCode: outcome.reason === "nonzero-exit" ? (outcome.exitCode ?? 1) : 1, |
243 | | - ...(outcome.message ? { stderrTail: outcome.message } : {}), |
| 226 | + ...(outcome.message ? { stderrTail: trimLogTail(outcome.message) } : {}), |
244 | 227 | }, |
245 | 228 | ], |
246 | 229 | }; |
|