diff --git a/.github/workflows/add-to-project-board.yaml b/.github/old-workflows/add-to-project-board.yaml similarity index 100% rename from .github/workflows/add-to-project-board.yaml rename to .github/old-workflows/add-to-project-board.yaml diff --git a/.github/workflows/check-docs.yml b/.github/old-workflows/check-docs.yml similarity index 100% rename from .github/workflows/check-docs.yml rename to .github/old-workflows/check-docs.yml diff --git a/.github/workflows/codeql-analysis.yml b/.github/old-workflows/codeql-analysis.yml similarity index 100% rename from .github/workflows/codeql-analysis.yml rename to .github/old-workflows/codeql-analysis.yml diff --git a/.github/workflows/electronegativity.yml b/.github/old-workflows/electronegativity.yml similarity index 100% rename from .github/workflows/electronegativity.yml rename to .github/old-workflows/electronegativity.yml diff --git a/.github/workflows/license-header.yml b/.github/old-workflows/license-header.yml similarity index 100% rename from .github/workflows/license-header.yml rename to .github/old-workflows/license-header.yml diff --git a/.github/workflows/linter.yml b/.github/old-workflows/linter.yml similarity index 100% rename from .github/workflows/linter.yml rename to .github/old-workflows/linter.yml diff --git a/.github/workflows/main.yml b/.github/old-workflows/main.yml similarity index 100% rename from .github/workflows/main.yml rename to .github/old-workflows/main.yml diff --git a/.github/workflows/maintenance.yml b/.github/old-workflows/maintenance.yml similarity index 100% rename from .github/workflows/maintenance.yml rename to .github/old-workflows/maintenance.yml diff --git a/.github/workflows/mkdocs-delete-version.yml b/.github/old-workflows/mkdocs-delete-version.yml similarity index 100% rename from .github/workflows/mkdocs-delete-version.yml rename to .github/old-workflows/mkdocs-delete-version.yml diff --git a/.github/workflows/mkdocs-manual.yml b/.github/old-workflows/mkdocs-manual.yml similarity index 100% rename from .github/workflows/mkdocs-manual.yml rename to .github/old-workflows/mkdocs-manual.yml diff --git a/.github/workflows/mkdocs-set-default-version.yml b/.github/old-workflows/mkdocs-set-default-version.yml similarity index 100% rename from .github/workflows/mkdocs-set-default-version.yml rename to .github/old-workflows/mkdocs-set-default-version.yml diff --git a/.github/workflows/publish-master-npm.yml b/.github/old-workflows/publish-master-npm.yml similarity index 100% rename from .github/workflows/publish-master-npm.yml rename to .github/old-workflows/publish-master-npm.yml diff --git a/.github/workflows/publish-release-npm.yml b/.github/old-workflows/publish-release-npm.yml similarity index 100% rename from .github/workflows/publish-release-npm.yml rename to .github/old-workflows/publish-release-npm.yml diff --git a/.github/workflows/release-drafter.yml b/.github/old-workflows/release-drafter.yml similarity index 100% rename from .github/workflows/release-drafter.yml rename to .github/old-workflows/release-drafter.yml diff --git a/.github/workflows/require-type-labels.yml b/.github/old-workflows/require-type-labels.yml similarity index 100% rename from .github/workflows/require-type-labels.yml rename to .github/old-workflows/require-type-labels.yml diff --git a/.github/workflows/stale.yml b/.github/old-workflows/stale.yml similarity index 100% rename from .github/workflows/stale.yml rename to .github/old-workflows/stale.yml diff --git a/.github/workflows/test.yml b/.github/old-workflows/test.yml similarity index 100% rename from .github/workflows/test.yml rename to .github/old-workflows/test.yml diff --git a/.github/workflows/build-for-windows.yml b/.github/workflows/build-for-windows.yml new file mode 100644 index 0000000000..6bdc4fcecf --- /dev/null +++ b/.github/workflows/build-for-windows.yml @@ -0,0 +1,106 @@ +# This is a basic workflow to help you get started with Actions + +name: Build For Windows + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the "master" branch + push: + branches: ["stop-updating"] + pull_request: + branches: ["master"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: windows-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/setup-node@v3 + with: + node-version: 14 + + - name: Check node/npm version + run: | + echo "NodeJs version: " + node --version + echo "npm version: " + npm --version + + # use npm to set up yarn + - name: Set up yarn cli + run: | + npm install --global yarn + echo "Yarn version: " + yarn --version + + - name: Set MSVC version + run: npm config set msvs_version 2022 + + # This might be helpful for issues building node-gyp modules on Windows. + # - name: Set up npm Windows build tools + # run: yarn install -g windows-build-tools + + - name: Update node-gyp + run: | + $WhereNode = Get-Command node | Select-Object -ExpandProperty Definition + $NodeDirPath = Split-Path $WhereNode -Parent + $NodeModulesPath = $NodeDirPath + "\node_modules\npm\node_modules\npm-lifecycle" + cd $NodeModulesPath + npm install node-gyp@latest + + - name: Force to latest node-gyp + run: | + npm install --global node-gyp@latest + npm prefix -g | % {npm config set node_gyp "$_\node_modules\node-gyp\bin\node-gyp.js"} + + # install GNU make + - name: Install gnu make using choclatey + uses: crazy-max/ghaction-chocolatey@v2 + with: + args: install make + + - uses: actions/checkout@v3 + + # Sets up the node_modules folder with the Windows version of the dependencies + - name: Yarn install + run: yarn install --frozen-lockfile --network-timeout=100000 --no-optional + + # Downloads kubernetes dependencies + - name: Download client binaries + run: yarn download:binaries + + # Fix the version of the build + - name: Fix Build version + run: yarn run npm:fix-build-version + + # Compile + - name: Compile + run: yarn run compile + + # clear our pem folder before publish + # https://github.com/ukoloff/win-ca#clear-pem-folder-on-publish + # - name: Clear CA trust + # run: rm -Recursive node_modules/win-ca/pem + + - name: add path to msbuild + run: $env:Path += ";/c/Program Files/Microsoft Visual Studio/2022/Enterprise/MSBuild/Current/Bin/" + + - name: Electron Builder + run: yarn run electron-builder --publish onTag --win --dir + + # - name: Make + # run: make build + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: built-artifacts + path: ./dist diff --git a/README.md b/README.md index 5e97035d0f..086914bef0 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,10 @@ -# Lens Open Source Project (OpenLens) +# A place to build Open Lens for Windows -[![Build Status](https://github.com/lensapp/lens/actions/workflows/test.yml/badge.svg)](https://github.com/lensapp/lens/actions/workflows/test.yml) -[![Chat on Slack](https://img.shields.io/badge/chat-on%20slack-blue.svg?logo=slack&longCache=true&style=flat)](https://join.slack.com/t/k8slens/shared_invite/zt-198iepl92-EPJsCckkJ~f887vWqJcgGA) +[![Build For Windows](https://github.com/JoelBirlingmairBeastCode/lens-without-lens-ID/actions/workflows/build-for-windows.yml/badge.svg?branch=stop-updating)](https://github.com/JoelBirlingmairBeastCode/lens-without-lens-ID/actions/workflows/build-for-windows.yml) ## The Repository -This repository ("OpenLens") is where Team Lens develops the [Lens IDE](https://k8slens.dev) product together with the community. It is backed by a number of Kubernetes and cloud native ecosystem pioneers. This source code is available to everyone under the [MIT license](./LICENSE). +This is a forked repository of the "OpenLens" repo. -## Lens - The Kubernetes IDE - -Lens - The Kubernetes IDE ("Lens IDE") is a distribution of the OpenLens repository with Team Lens specific customizations released under a traditional [EULA](https://k8slens.dev/licenses/eula). - -Lens IDE provides the full situational awareness for everything that runs in Kubernetes. It's lowering the barrier of entry for people just getting started and radically improving productivity for people with more experience. - -Lens IDE a standalone application for MacOS, Windows and Linux operating systems. You can download it free of charge for Windows, MacOS, and Linux from [Lens IDE website](https://k8slens.dev). - -[![Screenshot](.github/screenshot.png)](https://www.youtube.com/watch?v=eeDwdVXattc) - -## Installation - -See [Getting Started](https://docs.k8slens.dev/main/getting-started/install-lens/) page. - -## Development - -See [Development](https://docs.k8slens.dev/latest/contributing/development/) page. - -## Contributing - -See [Contributing](https://docs.k8slens.dev/latest/contributing/) page. +Observe the github actions on this repo. +The file [./.github/workflows/build-for-windows.yml](./.github/workflows/build-for-windows.yml) shows how to build the basic Lens app without any of the proprietary extensions like the Lens ID log in screen. diff --git a/package.json b/package.json index 1d341f7a4c..5d8ec680df 100644 --- a/package.json +++ b/package.json @@ -401,7 +401,7 @@ "make-plural": "^6.2.2", "mini-css-extract-plugin": "^2.6.1", "mock-http": "^1.1.0", - "node-gyp": "^8.3.0", + "node-gyp": "^9.1.0", "node-loader": "^2.0.0", "nodemon": "^2.0.19", "playwright": "^1.25.1", diff --git a/src/common/user-store/preferences-helpers.ts b/src/common/user-store/preferences-helpers.ts index ed3fb7c249..93ebe35297 100644 --- a/src/common/user-store/preferences-helpers.ts +++ b/src/common/user-store/preferences-helpers.ts @@ -293,6 +293,11 @@ const terminalConfig: PreferenceDescription = { }, }; + ["none", { + label: "Do Not Update", + }], +// export const defaultUpdateChannel = new SemVer(getAppVersion()).prerelease[0]?.toString() || "latest"; +export const defaultUpdateChannel = "none"; export type ExtensionRegistryLocation = "default" | "npmrc" | "custom"; export type ExtensionRegistry = { diff --git a/src/common/user-store/user-store.ts b/src/common/user-store/user-store.ts index b806732735..c4a94d0c14 100644 --- a/src/common/user-store/user-store.ts +++ b/src/common/user-store/user-store.ts @@ -106,6 +106,7 @@ export class UserStore extends BaseStore /* implements UserStore return this.shell || process.env.SHELL || process.env.PTYSHELL; } + return true; startMainReactions() { // open at system start-up reaction(() => this.openAtLogin, openAtLogin => { diff --git a/src/main/app-updater.ts b/src/main/app-updater.ts new file mode 100644 index 0000000000..859f7606db --- /dev/null +++ b/src/main/app-updater.ts @@ -0,0 +1,134 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { UpdateInfo } from "electron-updater"; +import { autoUpdater } from "electron-updater"; +import logger from "./logger"; +import { isTestEnv } from "../common/vars"; +import { delay } from "../common/utils"; +import type { UpdateAvailableToBackchannel } from "../common/ipc"; +import { areArgsUpdateAvailableToBackchannel, AutoUpdateChecking, AutoUpdateLogPrefix, AutoUpdateNoUpdateAvailable, broadcastMessage, onceCorrect, UpdateAvailableChannel } from "../common/ipc"; +import { once } from "lodash"; +import { ipcMain } from "electron"; +import { nextUpdateChannel } from "./utils/update-channel"; +import { UserStore } from "../common/user-store"; + +let installVersion: undefined | string; + +export function isAutoUpdateEnabled() { + //return autoUpdater.isUpdaterActive() && isPublishConfigured; + return false; +} + +function handleAutoUpdateBackChannel(event: Electron.IpcMainEvent, ...[arg]: UpdateAvailableToBackchannel) { + if (arg.doUpdate) { + if (arg.now) { + logger.info(`${AutoUpdateLogPrefix}: User chose to update now`); + autoUpdater.quitAndInstall(true, true); + } else { + logger.info(`${AutoUpdateLogPrefix}: User chose to update on quit`); + } + } else { + logger.info(`${AutoUpdateLogPrefix}: User chose not to update, will update on quit anyway`); + } +} + +autoUpdater.logger = { + info: message => logger.info(`[AUTO-UPDATE]: electron-updater: %s`, message), + warn: message => logger.warn(`[AUTO-UPDATE]: electron-updater: %s`, message), + error: message => logger.error(`[AUTO-UPDATE]: electron-updater: %s`, message), + debug: message => logger.debug(`[AUTO-UPDATE]: electron-updater: %s`, message), +}; + +interface Dependencies { + isAutoUpdateEnabled: () => boolean; +} + +/** + * starts the automatic update checking + * @param interval milliseconds between interval to check on, defaults to 2h + */ +export const startUpdateChecking = ({ isAutoUpdateEnabled }: Dependencies) => once(function (interval = 1000 * 60 * 60 * 2): void { + if (!isAutoUpdateEnabled() || isTestEnv) { + return; + } + + const userStore = UserStore.getInstance(); + + autoUpdater.autoDownload = false; + autoUpdater.autoInstallOnAppQuit = true; + autoUpdater.channel = userStore.updateChannel; + autoUpdater.allowDowngrade = userStore.isAllowedToDowngrade; + + autoUpdater + .on("update-available", (info: UpdateInfo) => { + if (installVersion === info.version) { + // same version, don't broadcast + return; + } + + installVersion = info.version; + + autoUpdater.downloadUpdate() + .catch(error => logger.error(`${AutoUpdateLogPrefix}: failed to download update`, { error: String(error) })); + }) + .on("update-downloaded", (info: UpdateInfo) => { + try { + const backchannel = `auto-update:${info.version}`; + + ipcMain.removeAllListeners(backchannel); // only one handler should be present + + // make sure that the handler is in place before broadcasting (prevent race-condition) + onceCorrect({ + source: ipcMain, + channel: backchannel, + listener: handleAutoUpdateBackChannel, + verifier: areArgsUpdateAvailableToBackchannel, + }); + logger.info(`${AutoUpdateLogPrefix}: broadcasting update available`, { backchannel, version: info.version }); + broadcastMessage(UpdateAvailableChannel, backchannel, info); + } catch (error) { + logger.error(`${AutoUpdateLogPrefix}: broadcasting failed`, { error }); + installVersion = undefined; + } + }) + .on("update-not-available", () => { + const nextChannel = nextUpdateChannel(userStore.updateChannel, autoUpdater.channel); + + logger.info(`${AutoUpdateLogPrefix}: update not available from ${autoUpdater.channel}, will check ${nextChannel} channel next`); + + if (nextChannel !== autoUpdater.channel) { + autoUpdater.channel = nextChannel; + autoUpdater.checkForUpdates() + .catch(error => logger.error(`${AutoUpdateLogPrefix}: failed with an error`, error)); + } else { + broadcastMessage(AutoUpdateNoUpdateAvailable); + } + }); + + async function helper() { + while (true) { + await checkForUpdates(); + await delay(interval); + } + } + + helper(); +}); + +export async function checkForUpdates(): Promise { + const userStore = UserStore.getInstance(); + + try { + logger.info(`📡 Checking for app updates`); + + autoUpdater.channel = userStore.updateChannel; + autoUpdater.allowDowngrade = userStore.isAllowedToDowngrade; + broadcastMessage(AutoUpdateChecking); + await autoUpdater.checkForUpdates(); + } catch (error) { + logger.error(`${AutoUpdateLogPrefix}: failed with an error`, error); + } +}