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

Include bundled extensions in package.json (#6715)

* bundle extensions to asar

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* make build fix

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen 2022-12-13 13:24:46 +02:00 committed by GitHub
parent 146cae0b1c
commit 012944d562
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 55 additions and 108 deletions

View File

@ -69,6 +69,7 @@ $(extension_node_modules): node_modules
$(extension_dists): src/extensions/npm/extensions/dist $(extension_node_modules)
cd $(@:/dist=) && ../../node_modules/.bin/npm run build
rm -rf ./node_modules/$(shell basename $(@:/dist=))
.PHONY: clean-old-extensions
clean-old-extensions:
@ -76,6 +77,7 @@ clean-old-extensions:
.PHONY: build-extensions
build-extensions: node_modules clean-old-extensions $(extension_dists)
yarn install --check-files --frozen-lockfile --network-timeout=100000
.PHONY: test-extensions
test-extensions: $(extension_node_modules)

View File

@ -8,7 +8,7 @@
"styles": []
},
"scripts": {
"build": "npx webpack && npm pack",
"build": "npx webpack",
"dev": "npx webpack -- --watch",
"test": "echo NO TESTS"
},

View File

@ -8,7 +8,7 @@
"styles": []
},
"scripts": {
"build": "npx webpack && npm pack",
"build": "npx webpack",
"dev": "npx webpack -- --watch",
"test": "npx jest --passWithNoTests --env=jsdom src $@",
"clean": "rm -rf dist/ && rm *.tgz"

View File

@ -8,7 +8,7 @@
"styles": []
},
"scripts": {
"build": "npx webpack && npm pack",
"build": "npx webpack",
"dev": "npx webpack -- --watch",
"test": "npx jest --passWithNoTests --env=jsdom src $@"
},

View File

@ -8,7 +8,7 @@
"styles": []
},
"scripts": {
"build": "npx webpack && npm pack",
"build": "npx webpack",
"dev": "npx webpack -- --watch",
"test": "npx jest --passWithNoTests --env=jsdom src $@"
},

View File

@ -58,7 +58,13 @@
"bundledHelmVersion": "3.7.2",
"sentryDsn": "",
"contentSecurityPolicy": "script-src 'unsafe-eval' 'self'; frame-src http://*.localhost:*/; img-src * data:",
"welcomeRoute": "/welcome"
"welcomeRoute": "/welcome",
"extensions": [
"kube-object-event-status",
"metrics-cluster-feature",
"node-menu",
"pod-menu"
]
},
"engines": {
"node": ">=16 <17"
@ -98,15 +104,6 @@
],
"afterSign": "build/notarize.js",
"extraResources": [
{
"from": "extensions/",
"to": "./extensions/",
"filter": [
"**/*.tgz",
"**/package.json",
"!**/node_modules"
]
},
{
"from": "templates/",
"to": "./templates/",
@ -236,9 +233,14 @@
"joi": "^17.7.0",
"js-yaml": "^4.1.0",
"jsdom": "^16.7.0",
"kube-object-event-status": "file:./extensions/kube-object-event-status",
"lens-metrics-cluster-feature": "file:./extensions/metrics-cluster-feature",
"lens-node-menu": "file:./extensions/node-menu",
"lens-pod-menu": "file:./extensions/pod-menu",
"lodash": "^4.17.15",
"marked": "^4.2.3",
"md5-file": "^5.0.0",
"metrics-cluster-feature": "file:./extensions/metrics-cluster-feature",
"mobx": "^6.7.0",
"mobx-observable-history": "^2.0.3",
"mobx-react": "^7.6.0",
@ -249,10 +251,12 @@
"monaco-editor": "^0.29.1",
"monaco-editor-webpack-plugin": "^5.0.0",
"node-fetch": "^3.3.0",
"node-menu": "file:./extensions/node-menu",
"node-pty": "0.10.1",
"npm": "^8.19.3",
"p-limit": "^3.1.0",
"path-to-regexp": "^6.2.0",
"pod-menu": "file:./extensions/pod-menu",
"proper-lockfile": "^4.1.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",

View File

@ -18,6 +18,7 @@ export default getGlobalOverride(applicationInformationInjectable, () => ({
sentryDsn: "",
contentSecurityPolicy: "script-src 'unsafe-eval' 'self'; frame-src http://*.localhost:*/; img-src * data:",
welcomeRoute: "/welcome",
extensions: [],
},
copyright: "some-copyright-information",
description: "some-descriptive-text",

View File

@ -10,7 +10,6 @@ import extensionsStoreInjectable from "../extensions-store/extensions-store.inje
import extensionInstallationStateStoreInjectable from "../extension-installation-state-store/extension-installation-state-store.injectable";
import installExtensionInjectable from "../extension-installer/install-extension/install-extension.injectable";
import extensionPackageRootDirectoryInjectable from "../extension-installer/extension-package-root-directory/extension-package-root-directory.injectable";
import installExtensionsInjectable from "../extension-installer/install-extensions/install-extensions.injectable";
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
import loggerInjectable from "../../common/logger.injectable";
import pathExistsInjectable from "../../common/fs/path-exists.injectable";
@ -28,6 +27,7 @@ import getRelativePathInjectable from "../../common/path/get-relative-path.injec
import joinPathsInjectable from "../../common/path/join-paths.injectable";
import removePathInjectable from "../../common/fs/remove-path.injectable";
import homeDirectoryPathInjectable from "../../common/os/home-directory-path.injectable";
import applicationInformationInjectable from "../../common/vars/application-information.injectable";
import lensResourcesDirInjectable from "../../common/vars/lens-resources-dir.injectable";
const extensionDiscoveryInjectable = getInjectable({
@ -39,7 +39,6 @@ const extensionDiscoveryInjectable = getInjectable({
extensionInstallationStateStore: di.inject(extensionInstallationStateStoreInjectable),
isCompatibleExtension: di.inject(isCompatibleExtensionInjectable),
installExtension: di.inject(installExtensionInjectable),
installExtensions: di.inject(installExtensionsInjectable),
extensionPackageRootDirectory: di.inject(extensionPackageRootDirectoryInjectable),
resourcesDirectory: di.inject(lensResourcesDirInjectable),
readJsonFile: di.inject(readJsonFileInjectable),
@ -59,6 +58,7 @@ const extensionDiscoveryInjectable = getInjectable({
getRelativePath: di.inject(getRelativePathInjectable),
joinPaths: di.inject(joinPathsInjectable),
homeDirectoryPath: di.inject(homeDirectoryPathInjectable),
applicationInformation: di.inject(applicationInformationInjectable),
}),
});

View File

@ -12,7 +12,6 @@ import type { ExtensionsStore } from "../extensions-store/extensions-store";
import type { ExtensionLoader } from "../extension-loader";
import type { LensExtensionId, LensExtensionManifest } from "../lens-extension";
import type { ExtensionInstallationStateStore } from "../extension-installation-state-store/extension-installation-state-store";
import type { PackageJson } from "type-fest";
import { extensionDiscoveryStateChannel } from "../../common/ipc/extension-handling";
import { requestInitialExtensionDiscovery } from "../../renderer/ipc";
import type { ReadJson } from "../../common/fs/read-json-file.injectable";
@ -20,7 +19,6 @@ import type { Logger } from "../../common/logger";
import type { PathExists } from "../../common/fs/path-exists.injectable";
import type { Watch } from "../../common/fs/watch/watch.injectable";
import type { Stats } from "fs";
import { constants } from "fs";
import type { LStat } from "../../common/fs/lstat.injectable";
import type { ReadDirectory } from "../../common/fs/read-directory.injectable";
import type { EnsureDirectory } from "../../common/fs/ensure-dir.injectable";
@ -32,6 +30,7 @@ import type { GetDirnameOfPath } from "../../common/path/get-dirname.injectable"
import type { GetRelativePath } from "../../common/path/get-relative-path.injectable";
import type { RemovePath } from "../../common/fs/remove-path.injectable";
import type TypedEventEmitter from "typed-emitter";
import type { ApplicationInformation } from "../../common/vars/application-information.injectable";
interface Dependencies {
readonly extensionLoader: ExtensionLoader;
@ -43,9 +42,9 @@ interface Dependencies {
readonly isProduction: boolean;
readonly fileSystemSeparator: string;
readonly homeDirectoryPath: string;
readonly applicationInformation: ApplicationInformation;
isCompatibleExtension: (manifest: LensExtensionManifest) => boolean;
installExtension: (name: string) => Promise<void>;
installExtensions: (packageJsonPath: string, packagesJson: PackageJson) => Promise<void>;
readJsonFile: ReadJson;
pathExists: PathExists;
removePath: RemovePath;
@ -137,14 +136,6 @@ export class ExtensionDiscovery {
return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory, manifestFilename);
}
get inTreeTargetPath(): string {
return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory, "extensions");
}
get inTreeFolderPath(): string {
return this.dependencies.joinPaths(this.dependencies.resourcesDirectory, "extensions");
}
get nodeModulesPath(): string {
return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory, "node_modules");
}
@ -329,26 +320,6 @@ export class ExtensionDiscovery {
);
await this.dependencies.removePath(this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory, "package-lock.json"));
const canWriteToInTreeFolder = await this.dependencies.accessPath(this.inTreeFolderPath, constants.W_OK);
if (canWriteToInTreeFolder) {
// Set bundled folder path to static/extensions
this.bundledFolderPath = this.inTreeFolderPath;
} else {
// Remove e.g. /Users/<username>/Library/Application Support/LensDev/extensions
await this.dependencies.removePath(this.inTreeTargetPath);
// Create folder e.g. /Users/<username>/Library/Application Support/LensDev/extensions
await this.dependencies.ensureDirectory(this.inTreeTargetPath);
// Copy static/extensions to e.g. /Users/<username>/Library/Application Support/LensDev/extensions
await this.dependencies.copy(this.inTreeFolderPath, this.inTreeTargetPath);
// Set bundled folder path to e.g. /Users/<username>/Library/Application Support/LensDev/extensions
this.bundledFolderPath = this.inTreeTargetPath;
}
await this.dependencies.ensureDirectory(this.nodeModulesPath);
await this.dependencies.ensureDirectory(this.localFolderPath);
@ -382,7 +353,7 @@ export class ExtensionDiscovery {
protected async getByManifest(manifestPath: string, { isBundled = false } = {}): Promise<InstalledExtension | null> {
try {
const manifest = await this.dependencies.readJsonFile(manifestPath) as unknown as LensExtensionManifest;
const id = this.getInstalledManifestPath(manifest.name);
const id = isBundled ? manifestPath : this.getInstalledManifestPath(manifest.name);
const isEnabled = this.dependencies.extensionsStore.isEnabled({ id, isBundled });
const extensionDir = this.dependencies.getDirnameOfPath(manifestPath);
const npmPackage = this.dependencies.joinPaths(extensionDir, `${manifest.name}-${manifest.version}.tgz`);
@ -417,39 +388,24 @@ export class ExtensionDiscovery {
const userExtensions = await this.loadFromFolder(this.localFolderPath, bundledExtensions.map((extension) => extension.manifest.name));
const extensions = bundledExtensions.concat(userExtensions);
await this.installBundledPackages(this.packageJsonPath, extensions);
return this.extensions = new Map(extensions.map(extension => [extension.id, extension]));
}
/**
* Write package.json to file system and install dependencies.
*/
installBundledPackages(packageJsonPath: string, extensions: InstalledExtension[]): Promise<void> {
const dependencies = Object.fromEntries(
extensions.filter(extension => extension.isBundled).map(extension => [extension.manifest.name, extension.absolutePath]),
);
const optionalDependencies = Object.fromEntries(
extensions.filter(extension => !extension.isBundled).map(extension => [extension.manifest.name, extension.absolutePath]),
);
return this.dependencies.installExtensions(packageJsonPath, { dependencies, optionalDependencies });
}
async loadBundledExtensions(): Promise<InstalledExtension[]> {
const extensions: InstalledExtension[] = [];
const folderPath = this.bundledFolderPath;
const paths = await this.dependencies.readDirectory(folderPath);
const extensionNames = this.dependencies.applicationInformation.config.extensions || [];
for (const fileName of paths) {
const absPath = this.dependencies.joinPaths(folderPath, fileName);
for (const dirName of extensionNames) {
const absPath = this.dependencies.joinPaths(__dirname, "..", "..", "node_modules", dirName);
const extension = await this.loadExtensionFromFolder(absPath, { isBundled: true });
if (extension) {
extensions.push(extension);
if (!extension) {
throw new Error(`Couldn't load bundled extension: ${dirName}`);
}
extensions.push(extension);
}
this.dependencies.logger.debug(`${logModule}: ${extensions.length} extensions loaded`, { folderPath, extensions });
this.dependencies.logger.debug(`${logModule}: ${extensions.length} extensions loaded`, { extensions });
return extensions;
}

View File

@ -5,10 +5,7 @@
import AwaitLock from "await-lock";
import child_process from "child_process";
import fs from "fs-extra";
import path from "path";
import logger from "../../main/logger";
import type { PackageJson } from "type-fest";
const logModule = "[EXTENSION-INSTALLER]";
@ -38,27 +35,6 @@ export class ExtensionInstaller {
return __non_webpack_require__.resolve("npm");
}
/**
* Write package.json to the file system and execute npm install for it.
*/
installPackages = async (packageJsonPath: string, packagesJson: PackageJson): Promise<void> => {
// Mutual exclusion to install packages in sequence
await this.installLock.acquireAsync();
try {
// Write the package.json which will be installed in .installDependencies()
await fs.writeFile(path.join(packageJsonPath), JSON.stringify(packagesJson, null, 2), {
mode: 0o600,
});
logger.info(`${logModule} installing dependencies at ${this.dependencies.extensionPackageRootDirectory}`);
await this.npm(...baseNpmInstallArgs);
logger.info(`${logModule} dependencies installed at ${this.dependencies.extensionPackageRootDirectory}`);
} finally {
this.installLock.release();
}
};
/**
* Install single package using npm
*/

View File

@ -1,13 +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 extensionInstallerInjectable from "../extension-installer.injectable";
const installExtensionsInjectable = getInjectable({
id: "install-extensions",
instantiate: (di) => di.inject(extensionInstallerInjectable).installPackages,
});
export default installExtensionsInjectable;

View File

@ -8394,6 +8394,9 @@ klona@^2.0.4, klona@^2.0.5:
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc"
integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==
"kube-object-event-status@file:./extensions/kube-object-event-status":
version "6.1.1"
kuler@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
@ -8411,6 +8414,15 @@ lazy-val@^1.0.4, lazy-val@^1.0.5:
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d"
integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==
"lens-metrics-cluster-feature@file:./extensions/metrics-cluster-feature":
version "6.1.0"
"lens-node-menu@file:./extensions/node-menu":
version "6.1.0"
"lens-pod-menu@file:./extensions/pod-menu":
version "6.1.0"
less@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/less/-/less-4.1.2.tgz#6099ee584999750c2624b65f80145f8674e4b4b0"
@ -8976,6 +8988,9 @@ methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
"metrics-cluster-feature@file:./extensions/metrics-cluster-feature":
version "6.1.0"
micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
@ -9422,6 +9437,9 @@ node-loader@^2.0.0:
dependencies:
loader-utils "^2.0.0"
"node-menu@file:./extensions/node-menu":
version "6.1.0"
node-pty@0.10.1:
version "0.10.1"
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.1.tgz#cd05d03a2710315ec40221232ec04186f6ac2c6d"
@ -10227,6 +10245,9 @@ plist@^3.0.1, plist@^3.0.4:
base64-js "^1.5.1"
xmlbuilder "^9.0.7"
"pod-menu@file:./extensions/pod-menu":
version "6.1.0"
popper.js@1.16.1-lts:
version "1.16.1-lts"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05"