mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Allow downgrading app versions
Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
ceca048b8d
commit
1def5d1354
88
src/behaviours/update-app/downgrading-version-update.test.ts
Normal file
88
src/behaviours/update-app/downgrading-version-update.test.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||||
|
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||||
|
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||||
|
import publishIsConfiguredInjectable from "../../main/update-app/publish-is-configured.injectable";
|
||||||
|
import type { AsyncFnMock } from "@async-fn/jest";
|
||||||
|
import asyncFn from "@async-fn/jest";
|
||||||
|
import type { CheckForPlatformUpdates } from "../../main/update-app/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||||
|
import checkForPlatformUpdatesInjectable from "../../main/update-app/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||||
|
import checkForUpdatesInjectable from "../../main/update-app/check-for-updates/check-for-updates.injectable";
|
||||||
|
import selectedUpdateChannelInjectable from "../../main/update-app/selected-update-channel.injectable";
|
||||||
|
import type { DiContainer } from "@ogre-tools/injectable";
|
||||||
|
import appVersionInjectable from "../../common/get-configuration-file-model/app-version/app-version.injectable";
|
||||||
|
import { updateChannels } from "../../main/update-app/update-channels";
|
||||||
|
|
||||||
|
describe("downgrading version update", () => {
|
||||||
|
let applicationBuilder: ApplicationBuilder;
|
||||||
|
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||||
|
let mainDi: DiContainer;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
applicationBuilder = getApplicationBuilder();
|
||||||
|
|
||||||
|
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||||
|
checkForPlatformUpdatesMock = asyncFn();
|
||||||
|
|
||||||
|
mainDi.override(
|
||||||
|
checkForPlatformUpdatesInjectable,
|
||||||
|
() => checkForPlatformUpdatesMock,
|
||||||
|
);
|
||||||
|
|
||||||
|
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||||
|
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||||
|
});
|
||||||
|
|
||||||
|
mainDi = applicationBuilder.dis.mainDi;
|
||||||
|
});
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
updateChannel: updateChannels.latest,
|
||||||
|
appVersion: "4.0.0-beta",
|
||||||
|
downgradeIsAllowed: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
updateChannel: updateChannels.beta,
|
||||||
|
appVersion: "4.0.0-beta",
|
||||||
|
downgradeIsAllowed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
updateChannel: updateChannels.beta,
|
||||||
|
appVersion: "4.0.0-beta.1",
|
||||||
|
downgradeIsAllowed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
updateChannel: updateChannels.alpha,
|
||||||
|
appVersion: "4.0.0-beta",
|
||||||
|
downgradeIsAllowed: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
updateChannel: updateChannels.alpha,
|
||||||
|
appVersion: "4.0.0-alpha",
|
||||||
|
downgradeIsAllowed: false,
|
||||||
|
},
|
||||||
|
].forEach(({ appVersion, updateChannel, downgradeIsAllowed }) => {
|
||||||
|
it(`given application version "${appVersion}" and update channel "${updateChannel.id}", when checking for updates, can${downgradeIsAllowed ? "": "not"} downgrade`, async () => {
|
||||||
|
mainDi.override(appVersionInjectable, () => appVersion);
|
||||||
|
|
||||||
|
await applicationBuilder.render();
|
||||||
|
|
||||||
|
const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable);
|
||||||
|
|
||||||
|
selectedUpdateChannel.setValue(updateChannel.id);
|
||||||
|
|
||||||
|
const checkForUpdates = mainDi.inject(checkForUpdatesInjectable);
|
||||||
|
|
||||||
|
checkForUpdates();
|
||||||
|
|
||||||
|
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(expect.any(Object), { allowDowngrade: downgradeIsAllowed });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@ -93,6 +93,7 @@ describe("installing update", () => {
|
|||||||
it('checks for updates from "latest" update channel', () => {
|
it('checks for updates from "latest" update channel', () => {
|
||||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
||||||
updateChannels.latest,
|
updateChannels.latest,
|
||||||
|
{ allowDowngrade: true },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -247,6 +248,7 @@ describe("installing update", () => {
|
|||||||
|
|
||||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
||||||
updateChannels.beta,
|
updateChannels.beta,
|
||||||
|
{ allowDowngrade: true },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -272,6 +274,7 @@ describe("installing update", () => {
|
|||||||
it('checks updates from update channel "alpha"', () => {
|
it('checks updates from update channel "alpha"', () => {
|
||||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
||||||
updateChannels.alpha,
|
updateChannels.alpha,
|
||||||
|
{ allowDowngrade: true },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -298,6 +301,7 @@ describe("installing update", () => {
|
|||||||
it('checks updates from update channel "beta"', () => {
|
it('checks updates from update channel "beta"', () => {
|
||||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
||||||
updateChannels.beta,
|
updateChannels.beta,
|
||||||
|
{ allowDowngrade: true },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -324,6 +328,7 @@ describe("installing update", () => {
|
|||||||
it('finally checks updates from update channel "latest"', () => {
|
it('finally checks updates from update channel "latest"', () => {
|
||||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
||||||
updateChannels.latest,
|
updateChannels.latest,
|
||||||
|
{ allowDowngrade: true },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -3,12 +3,11 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import packageInfo from "../../../../package.json";
|
import packageJsonInjectable from "../../vars/package-json.injectable";
|
||||||
|
|
||||||
const appVersionInjectable = getInjectable({
|
const appVersionInjectable = getInjectable({
|
||||||
id: "app-version",
|
id: "app-version",
|
||||||
instantiate: () => packageInfo.version,
|
instantiate: (di) => di.inject(packageJsonInjectable).version,
|
||||||
causesSideEffects: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default appVersionInjectable;
|
export default appVersionInjectable;
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 { afterRootFrameIsReadyInjectionToken } from "../../start-main-application/runnable-tokens/after-root-frame-is-ready-injection-token";
|
|
||||||
import startUpdateCheckingInjectable from "../../start-update-checking.injectable";
|
|
||||||
|
|
||||||
const setupUpdateCheckingInjectable = getInjectable({
|
|
||||||
id: "setup-update-checking",
|
|
||||||
|
|
||||||
instantiate: (di) => {
|
|
||||||
const startUpdateChecking = di.inject(startUpdateCheckingInjectable);
|
|
||||||
|
|
||||||
return {
|
|
||||||
run: () => {
|
|
||||||
startUpdateChecking();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
injectionToken: afterRootFrameIsReadyInjectionToken,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default setupUpdateCheckingInjectable;
|
|
||||||
@ -84,8 +84,8 @@ import setUpdateOnQuitInjectable from "./electron-app/features/set-update-on-qui
|
|||||||
import downloadPlatformUpdateInjectable from "./update-app/download-platform-update/download-platform-update.injectable";
|
import downloadPlatformUpdateInjectable from "./update-app/download-platform-update/download-platform-update.injectable";
|
||||||
import startCatalogSyncInjectable from "./catalog-sync-to-renderer/start-catalog-sync.injectable";
|
import startCatalogSyncInjectable from "./catalog-sync-to-renderer/start-catalog-sync.injectable";
|
||||||
import startKubeConfigSyncInjectable from "./start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable";
|
import startKubeConfigSyncInjectable from "./start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable";
|
||||||
import startCheckingForUpdatesInjectable
|
import startCheckingForUpdatesInjectable from "./update-app/periodical-check-for-updates/start-checking-for-updates.injectable";
|
||||||
from "./update-app/periodical-check-for-updates/start-checking-for-updates.injectable";
|
import appVersionInjectable from "../common/get-configuration-file-model/app-version/app-version.injectable";
|
||||||
|
|
||||||
export function getDiForUnitTesting(opts: GetDiForUnitTestingOptions = {}) {
|
export function getDiForUnitTesting(opts: GetDiForUnitTestingOptions = {}) {
|
||||||
const {
|
const {
|
||||||
@ -124,6 +124,7 @@ export function getDiForUnitTesting(opts: GetDiForUnitTestingOptions = {}) {
|
|||||||
di.override(commandLineArgumentsInjectable, () => []);
|
di.override(commandLineArgumentsInjectable, () => []);
|
||||||
|
|
||||||
di.override(productNameInjectable, () => "some-product-name");
|
di.override(productNameInjectable, () => "some-product-name");
|
||||||
|
di.override(appVersionInjectable, () => "1.0.0");
|
||||||
|
|
||||||
di.override(clusterFramesInjectable, () => observable.map<string, ClusterFrameInfo>());
|
di.override(clusterFramesInjectable, () => observable.map<string, ClusterFrameInfo>());
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import type { UpdateChannel } from "../update-channels";
|
|||||||
import loggerInjectable from "../../../common/logger.injectable";
|
import loggerInjectable from "../../../common/logger.injectable";
|
||||||
import type { UpdateCheckResult } from "electron-updater";
|
import type { UpdateCheckResult } from "electron-updater";
|
||||||
|
|
||||||
export type CheckForPlatformUpdates = (updateChannel: UpdateChannel) => Promise<{ updateWasDiscovered: boolean; version?: string }>;
|
export type CheckForPlatformUpdates = (updateChannel: UpdateChannel, opts: { allowDowngrade: boolean }) => Promise<{ updateWasDiscovered: boolean; version?: string }>;
|
||||||
|
|
||||||
const checkForPlatformUpdatesInjectable = getInjectable({
|
const checkForPlatformUpdatesInjectable = getInjectable({
|
||||||
id: "check-for-platform-updates",
|
id: "check-for-platform-updates",
|
||||||
@ -17,10 +17,10 @@ const checkForPlatformUpdatesInjectable = getInjectable({
|
|||||||
const electronUpdater = di.inject(electronUpdaterInjectable);
|
const electronUpdater = di.inject(electronUpdaterInjectable);
|
||||||
const logger = di.inject(loggerInjectable);
|
const logger = di.inject(loggerInjectable);
|
||||||
|
|
||||||
return async (updateChannel) => {
|
return async (updateChannel, { allowDowngrade }) => {
|
||||||
electronUpdater.channel = updateChannel.id;
|
electronUpdater.channel = updateChannel.id;
|
||||||
electronUpdater.autoDownload = false;
|
electronUpdater.autoDownload = false;
|
||||||
electronUpdater.allowDowngrade = false;
|
electronUpdater.allowDowngrade = allowDowngrade;
|
||||||
|
|
||||||
let result: UpdateCheckResult;
|
let result: UpdateCheckResult;
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ describe("check-for-platform-updates", () => {
|
|||||||
moreStableUpdateChannel: null,
|
moreStableUpdateChannel: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
actualPromise = checkForPlatformUpdates(testUpdateChannel);
|
actualPromise = checkForPlatformUpdates(testUpdateChannel, { allowDowngrade: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sets update channel", () => {
|
it("sets update channel", () => {
|
||||||
@ -60,7 +60,7 @@ describe("check-for-platform-updates", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("sets flag for allowing downgrade", () => {
|
it("sets flag for allowing downgrade", () => {
|
||||||
expect(electronUpdaterFake.allowDowngrade).toBe(false);
|
expect(electronUpdaterFake.allowDowngrade).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("disables auto downloading for being controlled", () => {
|
it("disables auto downloading for being controlled", () => {
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import type { UpdateChannel } from "../update-channels";
|
import type { UpdateChannel } from "../update-channels";
|
||||||
import checkForPlatformUpdatesInjectable from "../check-for-platform-updates/check-for-platform-updates.injectable";
|
import checkForPlatformUpdatesInjectable from "../check-for-platform-updates/check-for-platform-updates.injectable";
|
||||||
|
import updateCanBeDowngradedInjectable from "./update-can-be-downgraded.injectable";
|
||||||
|
|
||||||
interface CheckForUpdatesFromChannelResult {
|
interface CheckForUpdatesFromChannelResult {
|
||||||
updateWasDiscovered: boolean;
|
updateWasDiscovered: boolean;
|
||||||
@ -20,10 +21,14 @@ const checkForUpdatesStartingFromChannelInjectable = getInjectable({
|
|||||||
checkForPlatformUpdatesInjectable,
|
checkForPlatformUpdatesInjectable,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const updateCanBeDowngraded = di.inject(updateCanBeDowngradedInjectable);
|
||||||
|
|
||||||
const _recursiveCheck = async (
|
const _recursiveCheck = async (
|
||||||
updateChannel: UpdateChannel,
|
updateChannel: UpdateChannel,
|
||||||
): Promise<CheckForUpdatesFromChannelResult> => {
|
): Promise<CheckForUpdatesFromChannelResult> => {
|
||||||
const result = await checkForPlatformUpdates(updateChannel);
|
const result = await checkForPlatformUpdates(updateChannel, {
|
||||||
|
allowDowngrade: updateCanBeDowngraded.get(),
|
||||||
|
});
|
||||||
|
|
||||||
if (result.updateWasDiscovered) {
|
if (result.updateWasDiscovered) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* 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 { computed } from "mobx";
|
||||||
|
import selectedUpdateChannelInjectable from "../selected-update-channel.injectable";
|
||||||
|
import appVersionInjectable from "../../../common/get-configuration-file-model/app-version/app-version.injectable";
|
||||||
|
import { SemVer } from "semver";
|
||||||
|
|
||||||
|
const updateCanBeDowngradedInjectable = getInjectable({
|
||||||
|
id: "update-can-be-downgraded",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const selectedUpdateChannel = di.inject(selectedUpdateChannelInjectable);
|
||||||
|
const appVersion = di.inject(appVersionInjectable);
|
||||||
|
|
||||||
|
return computed(() => {
|
||||||
|
const semVer = new SemVer(appVersion);
|
||||||
|
|
||||||
|
return (
|
||||||
|
semVer.prerelease[0] !==
|
||||||
|
selectedUpdateChannel.value.get().id
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default updateCanBeDowngradedInjectable;
|
||||||
@ -3,14 +3,20 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import type { IComputedValue } from "mobx";
|
||||||
import { action, computed, observable } from "mobx";
|
import { action, computed, observable } from "mobx";
|
||||||
import type { UpdateChannelId } from "./update-channels";
|
import type { UpdateChannel, UpdateChannelId } from "./update-channels";
|
||||||
import { updateChannels } from "./update-channels";
|
import { updateChannels } from "./update-channels";
|
||||||
|
|
||||||
|
export interface SelectedUpdateChannel {
|
||||||
|
value: IComputedValue<UpdateChannel>;
|
||||||
|
setValue: (channelId: UpdateChannelId) => void;
|
||||||
|
}
|
||||||
|
|
||||||
const selectedUpdateChannelInjectable = getInjectable({
|
const selectedUpdateChannelInjectable = getInjectable({
|
||||||
id: "selected-update-channel",
|
id: "selected-update-channel",
|
||||||
|
|
||||||
instantiate: () => {
|
instantiate: (): SelectedUpdateChannel => {
|
||||||
const state = observable.box(updateChannels.latest);
|
const state = observable.box(updateChannels.latest);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user