feat(update): add core auto-updater and dry-run preview

This commit is contained in:
Peter Steinberger
2026-02-22 17:11:24 +01:00
parent 13690d406a
commit f442a3539f
15 changed files with 673 additions and 45 deletions

View File

@@ -374,6 +374,23 @@ describe("update-cli", () => {
expect(defaultRuntime.log).toHaveBeenCalled();
});
it("updateCommand --dry-run previews without mutating", async () => {
vi.mocked(defaultRuntime.log).mockClear();
serviceLoaded.mockResolvedValue(true);
await updateCommand({ dryRun: true, channel: "beta" });
expect(writeConfigFile).not.toHaveBeenCalled();
expect(runGatewayUpdate).not.toHaveBeenCalled();
expect(runDaemonInstall).not.toHaveBeenCalled();
expect(runRestartScript).not.toHaveBeenCalled();
expect(runDaemonRestart).not.toHaveBeenCalled();
const logs = vi.mocked(defaultRuntime.log).mock.calls.map((call) => String(call[0]));
expect(logs.join("\n")).toContain("Update dry-run");
expect(logs.join("\n")).toContain("No changes were applied.");
});
it("updateStatusCommand prints table output", async () => {
await updateStatusCommand({ json: false });
@@ -704,6 +721,16 @@ describe("update-cli", () => {
expect(vi.mocked(runGatewayUpdate).mock.calls.length > 0).toBe(shouldRunUpdate);
});
it("dry-run bypasses downgrade confirmation checks in non-interactive mode", async () => {
await setupNonInteractiveDowngrade();
vi.mocked(defaultRuntime.exit).mockClear();
await updateCommand({ dryRun: true });
expect(vi.mocked(defaultRuntime.exit).mock.calls.some((call) => call[0] === 1)).toBe(false);
expect(runGatewayUpdate).not.toHaveBeenCalled();
});
it("updateWizardCommand requires a TTY", async () => {
setTty(false);
vi.mocked(defaultRuntime.error).mockClear();