Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions apps/desktop/src/updates/DesktopUpdates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,32 @@ describe("DesktopUpdates", () => {
).pipe(Effect.provide(Layer.merge(TestClock.layer(), harness.layer)));
});

it.effect("keeps the current track's offers when a track switch fails to save", () => {
const harness = makeHarness({
setUpdateChannelError: new DesktopAppSettings.DesktopSettingsWriteError({
operation: "replace-settings-file",
path: "desktop-settings.json",
cause: new Error("rename failed"),
}),
});

return Effect.scoped(
Effect.gen(function* () {
const updates = yield* DesktopUpdates.DesktopUpdates;
yield* updates.configure;
const error = yield* updates
.setChannel("nightly", { minimumVersion: "1.2.5-nightly.20261028.1" })
.pipe(Effect.flip);
assert.equal(error._tag, "DesktopUpdateChannelPersistenceError");
assert.equal((yield* updates.getState).channel, "latest");

harness.emit("update-available", { version: "1.2.4" });
yield* flushCallbacks;
assert.equal((yield* updates.getState).availableVersion, "1.2.4");
}),
).pipe(Effect.provide(Layer.merge(TestClock.layer(), harness.layer)));
});

it.effect("keeps a saved Stable track across a restart without offering an older release", () => {
// A Nightly build whose switch to Stable did not finish before the app quit.
const harness = makeHarness({ appVersion: "1.2.4-nightly.20261027.1", savedChannel: "latest" });
Expand Down
18 changes: 10 additions & 8 deletions apps/desktop/src/updates/DesktopUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,10 @@ export const make = Effect.gen(function* () {
}

return yield* Effect.gen(function* () {
yield* Ref.set(releaseFloorRef, Option.fromNullishOr(options?.minimumVersion));
const previousFloor = yield* Ref.getAndSet(
releaseFloorRef,
Option.fromNullishOr(options?.minimumVersion),
);
const state = yield* Ref.get(updateStateRef);
const retained = state.downloadedVersion ?? state.availableVersion;
// A build from another track re-checks, so retrying a track switch finds an older release.
Expand All @@ -1242,13 +1245,12 @@ export const make = Effect.gen(function* () {
return state;
}

yield* desktopSettings
.setUpdateChannel(nextChannel)
.pipe(
Effect.mapError(
(cause) => new DesktopUpdateChannelPersistenceError({ channel: nextChannel, cause }),
),
);
yield* desktopSettings.setUpdateChannel(nextChannel).pipe(
Effect.onError(() => Ref.set(releaseFloorRef, previousFloor)),
Effect.mapError(
(cause) => new DesktopUpdateChannelPersistenceError({ channel: nextChannel, cause }),
),
);

const disabledReason = yield* resolveDisabledReason;
yield* setState(yield* baseUpdateState(nextChannel, disabledReason));
Expand Down
Loading