


















@@ -161,7 +161,7 @@ export type UpdateInstallSurface =
161161162162function mapManagerResolutionFailure(
163163reason: UpdatePackageManagerFailureReason,
164-): UpdateRunResult["reason"] {
164+): NonNullable<UpdateRunResult["reason"]> {
165165return reason;
166166}
167167@@ -766,7 +766,7 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
766766const beforeVersion = await readPackageVersion(gitRoot);
767767const channel: UpdateChannel = opts.channel ?? "dev";
768768const devTargetRef = channel === "dev" ? normalizeDevTargetRef(opts.devTargetRef) : null;
769-const branch = channel === "dev" ? await readBranchName(runCommand, gitRoot, timeoutMs) : null;
769+const branch = await readBranchName(runCommand, gitRoot, timeoutMs);
770770const needsCheckoutMain = channel === "dev" && !devTargetRef && branch !== DEV_BRANCH;
771771gitTotalSteps = channel === "dev" ? (needsCheckoutMain ? 11 : 10) : 9;
772772const buildGitErrorResult = (reason: string): UpdateRunResult => ({
@@ -786,6 +786,60 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
786786}
787787return null;
788788};
789+const appendRecoveryStep = async (name: string, argv: string[]) => {
790+const started = Date.now();
791+const result = await runCommand(argv, { cwd: gitRoot, timeoutMs });
792+const recoveryStep: UpdateStepResult = {
793+ name,
794+command: argv.join(" "),
795+cwd: gitRoot,
796+durationMs: Date.now() - started,
797+exitCode: result.code,
798+stdoutTail: trimLogTail(result.stdout, MAX_LOG_CHARS),
799+stderrTail: trimLogTail(result.stderr, MAX_LOG_CHARS),
800+};
801+steps.push(recoveryStep);
802+return recoveryStep.exitCode === 0;
803+};
804+const rollbackGitCheckout = async () => {
805+if (!beforeSha) {
806+return;
807+}
808+await appendRecoveryStep("git rollback clean", ["git", "-C", gitRoot, "reset", "--hard"]);
809+if (branch && branch !== "HEAD") {
810+const checkedOutBranch = await appendRecoveryStep("git rollback checkout", [
811+"git",
812+"-C",
813+gitRoot,
814+"checkout",
815+"--force",
816+branch,
817+]);
818+if (checkedOutBranch) {
819+await appendRecoveryStep("git rollback reset", [
820+"git",
821+"-C",
822+gitRoot,
823+"reset",
824+"--hard",
825+beforeSha,
826+]);
827+}
828+return;
829+}
830+await appendRecoveryStep("git rollback checkout", [
831+"git",
832+"-C",
833+gitRoot,
834+"checkout",
835+"--detach",
836+beforeSha,
837+]);
838+};
839+const buildGitErrorResultWithRollback = async (reason: string): Promise<UpdateRunResult> => {
840+await rollbackGitCheckout();
841+return buildGitErrorResult(reason);
842+};
789843790844const statusCheck = await runStep(
791845step(
@@ -1212,15 +1266,7 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
12121266"require-preferred",
12131267);
12141268if (manager.kind === "missing-required") {
1215-return {
1216-status: "error",
1217-mode: "git",
1218-root: gitRoot,
1219-reason: mapManagerResolutionFailure(manager.reason),
1220-before: { sha: beforeSha, version: beforeVersion },
1221- steps,
1222-durationMs: Date.now() - startedAt,
1223-};
1269+return await buildGitErrorResultWithRollback(mapManagerResolutionFailure(manager.reason));
12241270}
12251271try {
12261272const installEnv = resolveInstallEnv(manager.manager, manager.env);
@@ -1247,15 +1293,7 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
12471293}
12481294}
12491295if (finalDepsStep.exitCode !== 0) {
1250-return {
1251-status: "error",
1252-mode: "git",
1253-root: gitRoot,
1254-reason: "deps-install-failed",
1255-before: { sha: beforeSha, version: beforeVersion },
1256- steps,
1257-durationMs: Date.now() - startedAt,
1258-};
1296+return await buildGitErrorResultWithRollback("deps-install-failed");
12591297}
1260129812611299const buildStep = await runStep(
@@ -1268,31 +1306,15 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
12681306);
12691307steps.push(buildStep);
12701308if (buildStep.exitCode !== 0) {
1271-return {
1272-status: "error",
1273-mode: "git",
1274-root: gitRoot,
1275-reason: "build-failed",
1276-before: { sha: beforeSha, version: beforeVersion },
1277- steps,
1278-durationMs: Date.now() - startedAt,
1279-};
1309+return await buildGitErrorResultWithRollback("build-failed");
12801310}
1281131112821312const uiBuildStep = await runStep(
12831313step("ui:build", managerScriptArgs(manager.manager, "ui:build"), gitRoot, manager.env),
12841314);
12851315steps.push(uiBuildStep);
12861316if (uiBuildStep.exitCode !== 0) {
1287-return {
1288-status: "error",
1289-mode: "git",
1290-root: gitRoot,
1291-reason: "ui-build-failed",
1292-before: { sha: beforeSha, version: beforeVersion },
1293- steps,
1294-durationMs: Date.now() - startedAt,
1295-};
1317+return await buildGitErrorResultWithRollback("ui-build-failed");
12961318}
1297131912981320const doctorEntry = path.join(gitRoot, "openclaw.mjs");
@@ -1309,15 +1331,7 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
13091331exitCode: 1,
13101332stderrTail: `missing ${doctorEntry}`,
13111333});
1312-return {
1313-status: "error",
1314-mode: "git",
1315-root: gitRoot,
1316-reason: "doctor-entry-missing",
1317-before: { sha: beforeSha, version: beforeVersion },
1318- steps,
1319-durationMs: Date.now() - startedAt,
1320-};
1334+return await buildGitErrorResultWithRollback("doctor-entry-missing");
13211335}
1322133613231337// Use --fix so that doctor auto-strips unknown config keys introduced by
@@ -1335,15 +1349,7 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
13351349);
13361350steps.push(doctorStep);
13371351if (doctorStep.exitCode !== 0) {
1338-return {
1339-status: "error",
1340-mode: "git",
1341-root: gitRoot,
1342-reason: "doctor-failed",
1343-before: { sha: beforeSha, version: beforeVersion },
1344- steps,
1345-durationMs: Date.now() - startedAt,
1346-};
1352+return await buildGitErrorResultWithRollback("doctor-failed");
13471353}
1348135413491355const uiIndexHealth = await resolveControlUiDistIndexHealth({ root: gitRoot });
@@ -1367,15 +1373,7 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
13671373steps.push(repairStep);
1368137413691375if (repairResult.code !== 0) {
1370-return {
1371-status: "error",
1372-mode: "git",
1373-root: gitRoot,
1374-reason: "ui-build-failed",
1375-before: { sha: beforeSha, version: beforeVersion },
1376- steps,
1377-durationMs: Date.now() - startedAt,
1378-};
1376+return await buildGitErrorResultWithRollback("ui-build-failed");
13791377}
1380137813811379const repairedUiIndexHealth = await resolveControlUiDistIndexHealth({ root: gitRoot });
@@ -1390,15 +1388,7 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise<
13901388exitCode: 1,
13911389stderrTail: `missing ${uiIndexPath}`,
13921390});
1393-return {
1394-status: "error",
1395-mode: "git",
1396-root: gitRoot,
1397-reason: "ui-assets-missing",
1398-before: { sha: beforeSha, version: beforeVersion },
1399- steps,
1400-durationMs: Date.now() - startedAt,
1401-};
1391+return await buildGitErrorResultWithRollback("ui-assets-missing");
14021392}
14031393}
14041394此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。