Clean up versioning and packageJson uses (#6196)

This commit is contained in:
Sebastian Malton authored and GitHub committed 2022-09-15 17:20:58 -04:00
1 parent cfe35ded90
commit 67ac1692b2
116 files changed
+1154 -644

No files matched your search

@@ -3,65 +3,53 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import assert from "assert";
import semver from "semver";
import { isCompatibleExtension } from "../extension-discovery/is-compatible-extension/is-compatible-extension";
import type { LensExtensionManifest } from "../lens-extension";
describe("Extension/App versions compatibility checks", () => {
it("is compatible with exact version matching", () => {
expect(isCompatible({ extLensEngineVersion: "5.5.0", appVersion: "5.5.0" })).toBeTruthy();
expect(isCompatible({ extLensEngineVersion: "5.5.0", extensionApiVersion: "5.5.0" })).toBeTruthy();
});
it("is compatible with upper %PATCH versions of base app", () => {
expect(isCompatible({ extLensEngineVersion: "5.5.0", appVersion: "5.5.5" })).toBeTruthy();
expect(isCompatible({ extLensEngineVersion: "5.5.0", extensionApiVersion: "5.5.5" })).toBeTruthy();
});
it("is compatible with higher %MINOR version of base app", () => {
expect(isCompatible({ extLensEngineVersion: "5.5.0", appVersion: "5.6.0" })).toBeTruthy();
expect(isCompatible({ extLensEngineVersion: "5.5.0", extensionApiVersion: "5.6.0" })).toBeTruthy();
});
it("is not compatible with higher %MAJOR version of base app", () => {
expect(isCompatible({ extLensEngineVersion: "5.6.0", appVersion: "6.0.0" })).toBeFalsy(); // extension for lens@5 not compatible with lens@6
expect(isCompatible({ extLensEngineVersion: "6.0.0", appVersion: "5.6.0" })).toBeFalsy();
});
it("is compatible with lensEngine with prerelease", () => {
expect(isCompatible({
extLensEngineVersion: "^5.4.0-alpha.0",
appVersion: "5.5.0-alpha.0",
})).toBeTruthy();
expect(isCompatible({ extLensEngineVersion: "5.6.0", extensionApiVersion: "6.0.0" })).toBeFalsy(); // extension for lens@5 not compatible with lens@6
expect(isCompatible({ extLensEngineVersion: "6.0.0", extensionApiVersion: "5.6.0" })).toBeFalsy();
});
it("supports short version format for manifest.engines.lens", () => {
expect(isCompatible({ extLensEngineVersion: "5.5", appVersion: "5.5.1" })).toBeTruthy();
expect(isCompatible({ extLensEngineVersion: "5.5", extensionApiVersion: "5.5.1" })).toBeTruthy();
});
it("throws for incorrect or not supported version format", () => {
expect(() => isCompatible({
extLensEngineVersion: ">=2.0",
appVersion: "2.0",
extensionApiVersion: "2.0",
})).toThrow(/Invalid format/i);
expect(() => isCompatible({
extLensEngineVersion: "~2.0",
appVersion: "2.0",
extensionApiVersion: "2.0",
})).toThrow(/Invalid format/i);
expect(() => isCompatible({
extLensEngineVersion: "*",
appVersion: "1.0",
extensionApiVersion: "1.0",
})).toThrow(/Invalid format/i);
});
});
function isCompatible({ extLensEngineVersion = "^1.0", appVersion = "1.0" } = {}): boolean {
const appSemVer = semver.coerce(appVersion);
function isCompatible({ extLensEngineVersion = "^1.0", extensionApiVersion = "1.0" } = {}): boolean {
const extensionManifestMock = getExtensionManifestMock(extLensEngineVersion);
assert(appSemVer);
return isCompatibleExtension({ appSemVer })(extensionManifestMock);
return isCompatibleExtension({ extensionApiVersion })(extensionManifestMock);
}
function getExtensionManifestMock(lensEngine = "1.0"): LensExtensionManifest {
+57 -6
View File
@@ -3,14 +3,65 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getAppVersion } from "../../common/utils";
import appNameInjectable from "../../common/vars/app-name.injectable";
import isLinuxInjectable from "../../common/vars/is-linux.injectable";
import isMacInjectable from "../../common/vars/is-mac.injectable";
import isSnapPackageInjectable from "../../common/vars/is-snap-package.injectable";
import isWindowsInjectable from "../../common/vars/is-windows.injectable";
import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
import { getLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import getEnabledExtensionsInjectable from "./get-enabled-extensions/get-enabled-extensions.injectable";
import * as Preferences from "./user-preferences";
import type { UserPreferenceExtensionItems } from "./user-preferences";
import { Preferences } from "./user-preferences";
import { slackUrl, issuesTrackerUrl } from "../../common/vars";
import { buildVersionInjectionToken } from "../../common/vars/build-semantic-version.injectable";
export const version = getAppVersion();
export { isSnap, isWindows, isMac, isLinux, appName, slackUrl, issuesTrackerUrl } from "../../common/vars";
export interface AppExtensionItems {
readonly Preferences: UserPreferenceExtensionItems;
readonly version: string;
readonly appName: string;
readonly slackUrl: string;
readonly issuesTrackerUrl: string;
readonly isSnap: boolean;
readonly isWindows: boolean;
readonly isMac: boolean;
readonly isLinux: boolean;
getEnabledExtensions: () => string[];
}
export const getEnabledExtensions = asLegacyGlobalFunctionForExtensionApi(getEnabledExtensionsInjectable);
export const App: AppExtensionItems = {
Preferences,
getEnabledExtensions: asLegacyGlobalFunctionForExtensionApi(getEnabledExtensionsInjectable),
get version() {
const di = getLegacyGlobalDiForExtensionApi();
export { Preferences };
return di.inject(buildVersionInjectionToken).get();
},
get appName() {
const di = getLegacyGlobalDiForExtensionApi();
return di.inject(appNameInjectable);
},
get isSnap() {
const di = getLegacyGlobalDiForExtensionApi();
return di.inject(isSnapPackageInjectable);
},
get isWindows() {
const di = getLegacyGlobalDiForExtensionApi();
return di.inject(isWindowsInjectable);
},
get isMac() {
const di = getLegacyGlobalDiForExtensionApi();
return di.inject(isMacInjectable);
},
get isLinux() {
const di = getLegacyGlobalDiForExtensionApi();
return di.inject(isLinuxInjectable);
},
slackUrl,
issuesTrackerUrl,
};
+2 -2
View File
@@ -4,10 +4,10 @@
*/
// APIs
import * as App from "./app";
import { App } from "./app";
import * as EventBus from "./event-bus";
import * as Store from "./stores";
import * as Util from "./utils";
import { Util } from "./utils";
import * as Catalog from "./catalog";
import * as Types from "./types";
import * as Proxy from "./proxy";
@@ -4,10 +4,13 @@
*/
import { UserStore } from "../../common/user-store";
/**
* Get the configured kubectl binaries path.
*/
export function getKubectlPath(): string | undefined {
return UserStore.getInstance().kubectlBinariesPath;
export interface UserPreferenceExtensionItems {
/**
* Get the configured kubectl binaries path.
*/
getKubectlPath: () => string | undefined;
}
export const Preferences: UserPreferenceExtensionItems = {
getKubectlPath: () => UserStore.getInstance().kubectlBinariesPath,
};
+28 -8
View File
@@ -4,14 +4,34 @@
*/
import openLinkInBrowserInjectable from "../../common/utils/open-link-in-browser.injectable";
import buildVersionInjectable from "../../main/vars/build-version/build-version.injectable";
import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
import { getLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import { Singleton } from "../../common/utils";
import { prevDefault, stopPropagation } from "../../renderer/utils/prevDefault";
import type { IClassName } from "../../renderer/utils/cssNames";
import { cssNames } from "../../renderer/utils/cssNames";
export { Singleton, getAppVersion } from "../../common/utils";
export { prevDefault, stopPropagation } from "../../renderer/utils/prevDefault";
export { cssNames } from "../../renderer/utils/cssNames";
export interface UtilsExtensionItems {
Singleton: Singleton;
prevDefault: <E extends React.SyntheticEvent | Event, R>(callback: (evt: E) => R) => (evt: E) => R;
stopPropagation: (evt: Event | React.SyntheticEvent) => void;
cssNames: (...classNames: IClassName[]) => string;
openExternal: (url: string) => Promise<void>;
openBrowser: (url: string) => Promise<void>;
getAppVersion: () => string;
}
/**
* @deprecated Use {@link openBrowser} instead
*/
export const openExternal = asLegacyGlobalFunctionForExtensionApi(openLinkInBrowserInjectable);
export const openBrowser = asLegacyGlobalFunctionForExtensionApi(openLinkInBrowserInjectable);
export const Util: UtilsExtensionItems = {
Singleton,
prevDefault,
stopPropagation,
cssNames,
openExternal: asLegacyGlobalFunctionForExtensionApi(openLinkInBrowserInjectable),
openBrowser: asLegacyGlobalFunctionForExtensionApi(openLinkInBrowserInjectable),
getAppVersion: () => {
const di = getLegacyGlobalDiForExtensionApi();
return di.inject(buildVersionInjectable).get();
},
};
@@ -20,21 +20,20 @@ import watchInjectable from "../../common/fs/watch/watch.injectable";
const extensionDiscoveryInjectable = getInjectable({
id: "extension-discovery",
instantiate: (di) =>
new ExtensionDiscovery({
extensionLoader: di.inject(extensionLoaderInjectable),
extensionsStore: di.inject(extensionsStoreInjectable),
extensionInstallationStateStore: di.inject(extensionInstallationStateStoreInjectable),
isCompatibleExtension: di.inject(isCompatibleExtensionInjectable),
installExtension: di.inject(installExtensionInjectable),
installExtensions: di.inject(installExtensionsInjectable),
extensionPackageRootDirectory: di.inject(extensionPackageRootDirectoryInjectable),
staticFilesDirectory: di.inject(staticFilesDirectoryInjectable),
readJsonFile: di.inject(readJsonFileInjectable),
pathExists: di.inject(pathExistsInjectable),
watch: di.inject(watchInjectable),
logger: di.inject(loggerInjectable),
}),
instantiate: (di) => new ExtensionDiscovery({
extensionLoader: di.inject(extensionLoaderInjectable),
extensionsStore: di.inject(extensionsStoreInjectable),
extensionInstallationStateStore: di.inject(extensionInstallationStateStoreInjectable),
isCompatibleExtension: di.inject(isCompatibleExtensionInjectable),
installExtension: di.inject(installExtensionInjectable),
installExtensions: di.inject(installExtensionsInjectable),
extensionPackageRootDirectory: di.inject(extensionPackageRootDirectoryInjectable),
staticFilesDirectory: di.inject(staticFilesDirectoryInjectable),
readJsonFile: di.inject(readJsonFileInjectable),
pathExists: di.inject(pathExistsInjectable),
watch: di.inject(watchInjectable),
logger: di.inject(loggerInjectable),
}),
});
export default extensionDiscoveryInjectable;
@@ -15,10 +15,10 @@ import directoryForUserDataInjectable from "../../common/app-paths/directory-for
import mockFs from "mock-fs";
import { delay } from "../../renderer/utils";
import { observable, when } from "mobx";
import appVersionInjectable from "../../common/vars/app-version.injectable";
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
import pathExistsInjectable from "../../common/fs/path-exists.injectable";
import watchInjectable from "../../common/fs/watch/watch.injectable";
import extensionApiVersionInjectable from "../../common/vars/extension-api-version.injectable";
console = new Console(process.stdout, process.stderr); // fix mockFS
@@ -33,7 +33,7 @@ describe("ExtensionDiscovery", () => {
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
di.override(installExtensionInjectable, () => () => Promise.resolve());
di.override(appVersionInjectable, () => "5.0.0");
di.override(extensionApiVersionInjectable, () => "5.0.0");
readJsonFileMock = jest.fn();
di.override(readJsonFileInjectable, () => readJsonFileMock);
@@ -3,13 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import appSemanticVersionInjectable from "../../../common/vars/app-semantic-version.injectable";
import extensionApiVersionInjectable from "../../../common/vars/extension-api-version.injectable";
import { isCompatibleExtension } from "./is-compatible-extension";
const isCompatibleExtensionInjectable = getInjectable({
id: "is-compatible-extension",
instantiate: (di) => isCompatibleExtension({
appSemVer: di.inject(appSemanticVersionInjectable),
extensionApiVersion: di.inject(extensionApiVersionInjectable),
}),
});
@@ -2,16 +2,15 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import semver, { type SemVer } from "semver";
import semver from "semver";
import type { LensExtensionManifest } from "../../lens-extension";
interface Dependencies {
appSemVer: SemVer;
extensionApiVersion: string;
}
export const isCompatibleExtension = ({ appSemVer }: Dependencies): ((manifest: LensExtensionManifest) => boolean) => {
export const isCompatibleExtension = ({ extensionApiVersion }: Dependencies): ((manifest: LensExtensionManifest) => boolean) => {
return (manifest: LensExtensionManifest): boolean => {
const appVersion = appSemVer.raw.split("-")[0]; // drop prerelease version if any, e.g. "-alpha.0"
const manifestLensEngine = manifest.engines.lens;
const validVersion = manifestLensEngine.match(/^[\^0-9]\d*\.\d+\b/); // must start from ^ or number
@@ -30,7 +29,7 @@ export const isCompatibleExtension = ({ appSemVer }: Dependencies): ((manifest:
}) as semver.SemVer;
const supportedVersionsByExtension = semver.validRange(`^${extMajor}.${extMinor}`) as string;
return semver.satisfies(appVersion, supportedVersionsByExtension, {
return semver.satisfies(extensionApiVersion, supportedVersionsByExtension, {
loose: true,
includePrerelease: false,
});