mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(update): fail the git updater when the final HEAD verification probe errors (#129036)
The git updater classified blocking step failures before appending the final
"git rev-parse HEAD (after)" probe, so a nonzero exit from that probe was
invisible to findBlockingGitFailure. The result could report status:"ok"
with a null after.sha even though the installed revision was never verified.
Route the failed probe through rollbackError("head-verification-failed"),
matching every other failure path, so the checkout is rolled back and no
after identity is fabricated.
Fixes #127412
This commit is contained in:
@@ -551,6 +551,9 @@ export async function updateGitCheckout(params: {
|
||||
const afterShaStep = await runStep(
|
||||
step("git rev-parse HEAD (after)", ["git", "-C", gitRoot, "rev-parse", "HEAD"], gitRoot),
|
||||
);
|
||||
if (afterShaStep.exitCode !== 0) {
|
||||
return await rollbackError("head-verification-failed");
|
||||
}
|
||||
if (
|
||||
devTarget?.mode === "tracked" &&
|
||||
devPreflight?.status === "ok" &&
|
||||
|
||||
@@ -1701,6 +1701,43 @@ describe("runGatewayUpdate", () => {
|
||||
expect(calls).toContain(`git -C ${tempDir} reset --hard abc123`);
|
||||
});
|
||||
|
||||
it("rolls back and reports error when the final HEAD verification probe fails", async () => {
|
||||
await setupGitCheckout({ packageManager: "pnpm@8.0.0" });
|
||||
await setupUiIndex();
|
||||
const stableTag = "v1.0.1-1";
|
||||
const doctorNodePath = await resolveStableNodePath(process.execPath);
|
||||
const { runner, calls } = createRunner({
|
||||
...buildStableTagResponses(stableTag),
|
||||
[`git -C ${tempDir} rev-parse --abbrev-ref HEAD`]: { stdout: "main" },
|
||||
"pnpm install": { stdout: "" },
|
||||
"pnpm build": { stdout: "" },
|
||||
"pnpm ui:build": { stdout: "" },
|
||||
[`${doctorNodePath} ${path.join(tempDir, "openclaw.mjs")} doctor --non-interactive --fix`]: {
|
||||
stdout: "",
|
||||
},
|
||||
});
|
||||
let revParseHeadCount = 0;
|
||||
const runCommand = async (argv: string[]) => {
|
||||
const key = argv.join(" ");
|
||||
if (key === `git -C ${tempDir} rev-parse HEAD`) {
|
||||
revParseHeadCount += 1;
|
||||
if (revParseHeadCount === 2) {
|
||||
return toCommandResult({ code: 1, stderr: "fatal: not a valid object name HEAD" });
|
||||
}
|
||||
}
|
||||
return runner(argv);
|
||||
};
|
||||
|
||||
const result = await runWithCommand(runCommand, { channel: "stable" });
|
||||
|
||||
expect(result.status).toBe("error");
|
||||
expect(result.reason).toBe("head-verification-failed");
|
||||
expect(result.after).toBeUndefined();
|
||||
expect(calls).toContain(`git -C ${tempDir} reset --hard`);
|
||||
expect(calls).toContain(`git -C ${tempDir} checkout --force main`);
|
||||
expect(calls).toContain(`git -C ${tempDir} reset --hard abc123`);
|
||||
});
|
||||
|
||||
it("uses stable tag when beta tag is older than release", async () => {
|
||||
await setupGitCheckout({ packageManager: "pnpm@8.0.0" });
|
||||
await setupUiIndex();
|
||||
|
||||
Reference in New Issue
Block a user