1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Reorganize responsibilities for checking updates

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-05-19 13:25:50 +03:00
parent e2de1449d5
commit 129f9c1953
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
7 changed files with 133 additions and 102 deletions

View File

@ -12,7 +12,8 @@ export type ApplicationUpdateStatusEventId =
| "download-for-update-started"
| "download-for-update-failed";
export type ApplicationUpdateStatusChannel = Channel<{ eventId: ApplicationUpdateStatusEventId; version?: string }>;
export interface ApplicationUpdateStatusChannelMessage { eventId: ApplicationUpdateStatusEventId; version?: string }
export type ApplicationUpdateStatusChannel = Channel<ApplicationUpdateStatusChannelMessage>;
const applicationUpdateStatusChannelInjectable = getInjectable({
id: "application-update-status-channel",

View File

@ -20,6 +20,7 @@ const checkForPlatformUpdatesInjectable = getInjectable({
return async (updateChannel) => {
electronUpdater.channel = updateChannel.id;
electronUpdater.autoDownload = false;
electronUpdater.allowDowngrade = false;
let result: UpdateCheckResult;

View File

@ -28,6 +28,7 @@ describe("check-for-platform-updates", () => {
electronUpdaterFake = {
channel: undefined,
autoDownload: undefined,
allowDowngrade: undefined,
checkForUpdates: checkForUpdatesMock,
} as unknown as AppUpdater;
@ -58,6 +59,10 @@ describe("check-for-platform-updates", () => {
expect(electronUpdaterFake.channel).toBe("some-update-channel");
});
it("sets flag for allowing downgrade", () => {
expect(electronUpdaterFake.allowDowngrade).toBe(false);
});
it("disables auto downloading for being controlled", () => {
expect(electronUpdaterFake.autoDownload).toBe(false);
});

View File

@ -7,17 +7,12 @@ import { computed } from "mobx";
import updatingIsEnabledInjectable from "./updating-is-enabled.injectable";
import { trayMenuItemInjectionToken } from "../tray/tray-menu-item/tray-menu-item-injection-token";
import showApplicationWindowInjectable from "../start-main-application/lens-window/show-application-window.injectable";
import askBooleanInjectable from "../ask-boolean/ask-boolean.injectable";
import quitAndInstallUpdateInjectable from "../electron-app/features/quit-and-install-update.injectable";
import discoveredUpdateVersionInjectable from "../../common/application-update/discovered-update-version/discovered-update-version.injectable";
import updateIsBeingDownloadedInjectable from "../../common/application-update/update-is-being-downloaded/update-is-being-downloaded.injectable";
import updatesAreBeingDiscoveredInjectable from "../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
import checkForUpdatesInjectable from "./check-for-updates/check-for-updates.injectable";
import downloadUpdateInjectable from "./download-update/download-update.injectable";
import progressOfUpdateDownloadInjectable from "../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
import assert from "assert";
import { sendToAgnosticChannelInjectionToken } from "../../common/channel/send-to-agnostic-channel-injection-token";
import applicationUpdateStatusChannelInjectable from "../../common/application-update/application-update-status-channel.injectable";
import checkForUpdatesInjectable from "./check-for-updates/check-for-updates.injectable";
const checkForUpdatesTrayItemInjectable = getInjectable({
id: "check-for-updates-tray-item",
@ -26,15 +21,10 @@ const checkForUpdatesTrayItemInjectable = getInjectable({
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
const updatingIsEnabled = di.inject(updatingIsEnabledInjectable);
const progressOfUpdateDownload = di.inject(progressOfUpdateDownloadInjectable);
const askBoolean = di.inject(askBooleanInjectable);
const quitAndInstallUpdate = di.inject(quitAndInstallUpdateInjectable);
const discoveredVersionState = di.inject(discoveredUpdateVersionInjectable);
const downloadingUpdateState = di.inject(updateIsBeingDownloadedInjectable);
const checkingForUpdatesState = di.inject(updatesAreBeingDiscoveredInjectable);
const checkForUpdates = di.inject(checkForUpdatesInjectable);
const downloadUpdate = di.inject(downloadUpdateInjectable);
const sendToAgnosticChannel = di.inject(sendToAgnosticChannelInjectionToken);
const applicationUpdateStatusChannel = di.inject(applicationUpdateStatusChannelInjectable);
return {
id: "check-for-updates",
@ -62,31 +52,7 @@ const checkForUpdatesTrayItemInjectable = getInjectable({
visible: computed(() => updatingIsEnabled),
click: async () => {
const { updateWasDiscovered, version } = await checkForUpdates();
if (updateWasDiscovered) {
sendToAgnosticChannel(applicationUpdateStatusChannel, { eventId: "download-for-update-started", version });
// Note: intentional orphan promise to make download happen in the background
downloadUpdate().then(async ({ downloadWasSuccessful }) => {
if (!downloadWasSuccessful) {
sendToAgnosticChannel(applicationUpdateStatusChannel, { eventId: "download-for-update-failed" });
return;
}
const userWantsToInstallUpdate = await askBoolean({
id: "install-update",
title: "Update available",
question: `Version ${version} of Lens IDE is available and ready to be installed. Would you like to update now?`,
});
if (userWantsToInstallUpdate) {
quitAndInstallUpdate();
}
});
}
await checkForUpdates();
await showApplicationWindow();
},

View File

@ -0,0 +1,23 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ApplicationUpdateStatusChannelMessage } from "../../../common/application-update/application-update-status-channel.injectable";
import { sendToAgnosticChannelInjectionToken } from "../../../common/channel/send-to-agnostic-channel-injection-token";
import applicationUpdateStatusChannelInjectable from "../../../common/application-update/application-update-status-channel.injectable";
const broadcastChangeInUpdatingStatusInjectable = getInjectable({
id: "broadcast-change-in-updating-status",
instantiate: (di) => {
const sendToAgnosticChannel = di.inject(sendToAgnosticChannelInjectionToken);
const applicationUpdateStatusChannel = di.inject(applicationUpdateStatusChannelInjectable);
return (data: ApplicationUpdateStatusChannelMessage) => {
sendToAgnosticChannel(applicationUpdateStatusChannel, data);
};
},
});
export default broadcastChangeInUpdatingStatusInjectable;

View File

@ -0,0 +1,47 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { UpdateChannel } from "../update-channels";
import checkForPlatformUpdatesInjectable from "../check-for-platform-updates/check-for-platform-updates.injectable";
interface CheckForUpdatesFromChannelResult {
updateWasDiscovered: boolean;
version?: string;
actualUpdateChannel?: UpdateChannel;
}
const checkForUpdatesStartingFromChannelInjectable = getInjectable({
id: "check-for-updates-starting-from-channel",
instantiate: (di) => {
const checkForPlatformUpdates = di.inject(
checkForPlatformUpdatesInjectable,
);
const _recursiveCheck = async (
updateChannel: UpdateChannel,
): Promise<CheckForUpdatesFromChannelResult> => {
const result = await checkForPlatformUpdates(updateChannel);
if (result.updateWasDiscovered) {
return {
updateWasDiscovered: true,
version: result.version,
actualUpdateChannel: updateChannel,
};
}
if (updateChannel.moreStableUpdateChannel) {
return await _recursiveCheck(updateChannel.moreStableUpdateChannel);
}
return { updateWasDiscovered: false };
};
return _recursiveCheck;
},
});
export default checkForUpdatesStartingFromChannelInjectable;

View File

@ -3,103 +3,91 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { CheckForPlatformUpdates } from "../check-for-platform-updates/check-for-platform-updates.injectable";
import checkForPlatformUpdatesInjectable from "../check-for-platform-updates/check-for-platform-updates.injectable";
import type { UpdateChannel } from "../update-channels";
import selectedUpdateChannelInjectable from "../selected-update-channel.injectable";
import updatesAreBeingDiscoveredInjectable from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
import discoveredUpdateVersionInjectable from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable";
import { runInAction } from "mobx";
import assert from "assert";
import applicationUpdateStatusChannelInjectable from "../../../common/application-update/application-update-status-channel.injectable";
import { sendToAgnosticChannelInjectionToken } from "../../../common/channel/send-to-agnostic-channel-injection-token";
import askBooleanInjectable from "../../ask-boolean/ask-boolean.injectable";
import quitAndInstallUpdateInjectable from "../../electron-app/features/quit-and-install-update.injectable";
import downloadUpdateInjectable from "../download-update/download-update.injectable";
import broadcastChangeInUpdatingStatusInjectable from "./broadcast-change-in-updating-status.injectable";
import checkForUpdatesStartingFromChannelInjectable from "./check-for-updates-starting-from-channel.injectable";
const checkForUpdatesInjectable = getInjectable({
id: "check-for-updates",
instantiate: (di) => {
const askBoolean = di.inject(askBooleanInjectable);
const quitAndInstallUpdate = di.inject(quitAndInstallUpdateInjectable);
const downloadUpdate = di.inject(downloadUpdateInjectable);
const selectedUpdateChannel = di.inject(selectedUpdateChannelInjectable);
const sendToAgnosticChannel = di.inject(sendToAgnosticChannelInjectionToken);
const applicationUpdateStatusChannel = di.inject(applicationUpdateStatusChannelInjectable);
const checkForPlatformUpdates = di.inject(
checkForPlatformUpdatesInjectable,
);
const checkingForUpdatesState = di.inject(
updatesAreBeingDiscoveredInjectable,
);
const broadcastChangeInUpdatingStatus = di.inject(broadcastChangeInUpdatingStatusInjectable);
const checkingForUpdatesState = di.inject(updatesAreBeingDiscoveredInjectable);
const discoveredVersionState = di.inject(discoveredUpdateVersionInjectable);
const checkForUpdatesStartingFromChannel = di.inject(checkForUpdatesStartingFromChannelInjectable);
return async () => {
broadcastChangeInUpdatingStatus({ eventId: "checking-for-updates" });
runInAction(() => {
checkingForUpdatesState.set(true);
});
const checkForUpdatesStartingFromChannel =
checkForUpdatesStartingFromChannelFor(checkForPlatformUpdates);
sendToAgnosticChannel(applicationUpdateStatusChannel, { eventId: "checking-for-updates" });
const { updateWasDiscovered, version, actualUpdateChannel } =
await checkForUpdatesStartingFromChannel(selectedUpdateChannel.value.get());
if (!updateWasDiscovered) {
sendToAgnosticChannel(applicationUpdateStatusChannel, { eventId: "no-updates-available" });
broadcastChangeInUpdatingStatus({ eventId: "no-updates-available" });
runInAction(() => {
discoveredVersionState.set(null);
checkingForUpdatesState.set(false);
});
return;
}
broadcastChangeInUpdatingStatus({
eventId: "download-for-update-started",
version,
});
runInAction(() => {
if (!updateWasDiscovered) {
discoveredVersionState.set(null);
} else {
// TODO: Unacceptable damage caused by strict mode
assert(version);
assert(actualUpdateChannel);
// TODO: Unacceptable damage caused by strict mode
assert(version);
assert(actualUpdateChannel);
discoveredVersionState.set({
version,
updateChannel: actualUpdateChannel,
});
}
discoveredVersionState.set({
version,
updateChannel: actualUpdateChannel,
});
checkingForUpdatesState.set(false);
});
return { updateWasDiscovered, version };
// Note: intentional orphan promise to make download happen in the background
downloadUpdate().then(async ({ downloadWasSuccessful }) => {
if (!downloadWasSuccessful) {
broadcastChangeInUpdatingStatus({
eventId: "download-for-update-failed",
});
return;
}
const userWantsToInstallUpdate = await askBoolean({
id: "install-update",
title: "Update Available",
question: `Version ${version} of Lens IDE is available and ready to be installed. Would you like to update now?`,
});
if (userWantsToInstallUpdate) {
quitAndInstallUpdate();
}
});
};
},
});
export default checkForUpdatesInjectable;
const checkForUpdatesStartingFromChannelFor = (
checkForPlatformUpdates: CheckForPlatformUpdates,
) => {
const _recursiveCheck = async (
updateChannel: UpdateChannel,
): Promise<{
updateWasDiscovered: boolean;
version?: string;
actualUpdateChannel?: UpdateChannel;
}> => {
const result = await checkForPlatformUpdates(updateChannel);
if (result.updateWasDiscovered) {
return {
updateWasDiscovered: true,
version: result.version,
actualUpdateChannel: updateChannel,
};
}
if (updateChannel.moreStableUpdateChannel) {
return await _recursiveCheck(updateChannel.moreStableUpdateChannel);
}
return { updateWasDiscovered: false };
};
return _recursiveCheck;
};