From f2acc598aea6eeea3708d530c60be29926843a2d Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sun, 22 Oct 2023 12:58:40 -0400 Subject: [PATCH 01/24] Add option to disable auto-update --- .mirrord/mirrord.json | 10 ++ src/binaryManager.ts | 36 ++++++- src/status.ts | 10 +- src/tests/e2e.ts | 222 ++++++++++++++++++++++-------------------- 4 files changed, 169 insertions(+), 109 deletions(-) create mode 100644 .mirrord/mirrord.json diff --git a/.mirrord/mirrord.json b/.mirrord/mirrord.json new file mode 100644 index 00000000..46b0a57c --- /dev/null +++ b/.mirrord/mirrord.json @@ -0,0 +1,10 @@ +{ + "feature": { + "network": { + "incoming": "mirror", + "outgoing": true + }, + "fs": "read", + "env": true + } +} diff --git a/src/binaryManager.ts b/src/binaryManager.ts index d7de5fcb..b2cd0588 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -1,17 +1,21 @@ import axios, { AxiosResponse } from 'axios'; +import * as vscode from 'vscode'; import which from 'which'; import { globalContext } from './extension'; import { MirrordAPI } from './api'; import { Utils } from 'vscode-uri'; import * as fs from 'node:fs'; import { platform } from 'os'; -import { Uri, workspace, window, ProgressLocation, ExtensionMode } from 'vscode'; +import { Uri, workspace, window, ProgressLocation, ExtensionMode, InputBoxOptions } from 'vscode'; import { NotificationBuilder } from './notification'; const mirrordBinaryEndpoint = 'https://version.mirrord.dev/v1/version'; // const binaryCheckInterval = 1000 * 60 * 3; const baseDownloadUri = 'https://github.com/metalbear-co/mirrord/releases/download'; +export let autoUpdate = true; +let mirrordBinaryVersion: string | null = null; + function getExtensionMirrordPath(): Uri { return Utils.joinPath(globalContext.globalStorageUri, 'mirrord'); } @@ -194,4 +198,32 @@ async function downloadMirrordBinary(destPath: Uri, version: string): Promise { + if (value !== "") { + if (/^[0-9]+\\.[0-9]+\\.[0-9]+$/.test(value)) { + vscode.window.showErrorMessage("Invalid version format ${value}: must follow semver format"); + } + } + return null; + } + }; + + await vscode.window.showInputBox(options); + } else { + autoUpdate = true; + vscode.window.showInformationMessage("Auto-update enabled"); + } +} diff --git a/src/status.ts b/src/status.ts index 28d2293d..318e6ebb 100644 --- a/src/status.ts +++ b/src/status.ts @@ -3,11 +3,13 @@ import { MirrordConfigManager } from './config'; import { globalContext } from './extension'; import { waitlistRegisterCommand } from './waitlist'; import { NotificationBuilder } from './notification'; +import { toggleAutoUpdate, autoUpdate } from './binaryManager'; export class MirrordStatus { readonly statusBar: vscode.StatusBarItem; static readonly toggleCommandId = 'mirrord.toggleMirroring'; static readonly settingsCommandId = 'mirrord.changeSettings'; + static readonly autoUpdateCommandId = 'mirrord.autoUpdate'; static readonly submitFeedbackCommandId = 'mirrord.submitFeedback'; static readonly waitlistCommandId = 'mirrord.waitlistSignup'; static readonly selectActiveConfigId = 'mirrord.selectActiveConfig'; @@ -19,7 +21,7 @@ export class MirrordStatus { draw() { const { - enabled, + enabled, statusBar, } = this; @@ -38,6 +40,9 @@ export class MirrordStatus { if (activeConfig) { statusBar.tooltip.appendMarkdown(`\n\n[Active config: ${vscode.workspace.asRelativePath(activeConfig)}](${activeConfig})`); } + + const autoUpdateState = autoUpdate; + statusBar.tooltip.appendMarkdown(`\n\n[Auto-update: ${autoUpdateState ? 'Enabled' : 'Disabled'}](command:${MirrordStatus.autoUpdateCommandId})`); statusBar.tooltip.appendMarkdown(`\n\n[Select active config](command:${MirrordStatus.selectActiveConfigId})`); statusBar.tooltip.appendMarkdown(`\n\n[Settings](command:${MirrordStatus.settingsCommandId})`); statusBar.tooltip.appendMarkdown(`\n\n[mirrord for Teams Waitlist](command:${MirrordStatus.waitlistCommandId})`); @@ -56,6 +61,9 @@ export class MirrordStatus { globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.selectActiveConfigId, async () => { await configManager.selectActiveConfig(); })); + globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.autoUpdateCommandId, async () => { + await toggleAutoUpdate(); + })); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.settingsCommandId, configManager.changeSettings.bind(configManager))); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.toggleCommandId, this.toggle.bind(this))); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.submitFeedbackCommandId, this.submitFeedback.bind(this))); diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index ffd7d5a2..4e4edc39 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -1,7 +1,8 @@ import { expect } from "chai"; import { join } from "path"; -import { VSBrowser, StatusBar, ActivityBar, DebugView, InputBox, DebugToolbar, BottomBarPanel, EditorView } from "vscode-extension-tester"; +import { VSBrowser, StatusBar, ActivityBar, DebugView, InputBox, DebugToolbar, BottomBarPanel, EditorView, TextEditor } from "vscode-extension-tester"; import get from "axios"; +import exp from "constants"; const kubeService = process.env.KUBE_SERVICE; const podToSelect = process.env.POD_TO_SELECT; @@ -15,122 +16,131 @@ const podToSelect = process.env.POD_TO_SELECT; * - Send traffic to the pod * - Tests successfully exit if "GET: Request completed" is found in the terminal */ -describe("mirrord sample flow test", function() { +describe("mirrord sample flow test", function () { - this.timeout("6 minutes"); // --> mocha tests timeout - this.bail(true); // --> stop tests on first failure + this.timeout("6 minutes"); // --> mocha tests timeout + this.bail(true); // --> stop tests on first failure - let browser: VSBrowser; + let browser: VSBrowser; - const testWorkspace = join(__dirname, '../../test-workspace'); - const fileName = "app_flask.py"; - const defaultTimeout = 10000; // = 10 seconds + const testWorkspace = join(__dirname, '../../test-workspace'); + const fileName = "app_flask.py"; + const defaultTimeout = 10000; // = 10 seconds - before(async function() { - console.log("podToSelect: " + podToSelect); - console.log("kubeService: " + kubeService); + before(async function () { + console.log("podToSelect: " + podToSelect); + console.log("kubeService: " + kubeService); - expect(podToSelect).to.not.be.undefined; - expect(kubeService).to.not.be.undefined; + expect(podToSelect).to.not.be.undefined; + expect(kubeService).to.not.be.undefined; - browser = VSBrowser.instance; + browser = VSBrowser.instance; - await browser.openResources(testWorkspace, join(testWorkspace, fileName)); - await browser.waitForWorkbench(); + await browser.openResources(testWorkspace, join(testWorkspace, fileName)); + await browser.waitForWorkbench(); - const ew = new EditorView(); - try { - await ew.closeEditor('Welcome'); - } catch (error) { - console.log("Welcome page is not displayed" + error); - // continue - Welcome page is not displayed - } - await ew.openEditor('app_flask.py'); - }); - - it("enable mirrord button", async function() { - const statusBar = new StatusBar(); + const ew = new EditorView(); + try { + await ew.closeEditor('Welcome'); + } catch (error) { + console.log("Welcome page is not displayed" + error) + // continue - Welcome page is not displayed + } + await ew.openEditor('app_flask.py'); + }); - await browser.driver.wait(async () => { - return await statusBar.isDisplayed(); + it("enable mirrord button", async function () { + const statusBar = new StatusBar(); + + await browser.driver.wait(async () => { + return await statusBar.isDisplayed(); + }); + + // vscode refreshes the status bar on load and there is no deterministic way but to retry to click on + // the mirrord button after an interval + await browser.driver.wait(async () => { + let retries = 0; + while (retries < 3) { + try { + for (let button of await statusBar.getItems()) { + if ((await button.getText()).startsWith('mirrord')) { + await button.click(); + return true; + } + } + } catch (e) { + if (e instanceof Error && e.name === 'StaleElementReferenceError') { + await new Promise(resolve => setTimeout(resolve, 1000)); + retries++; + } else { + throw e; + } + } + } + throw new Error('Failed to click the button after multiple attempts'); + }, defaultTimeout, "mirrord `enable` button not found -- timed out"); }); - // vscode refreshes the status bar on load and there is no deterministic way but to retry to click on - // the mirrord button after an interval - await browser.driver.wait(async () => { - let retries = 0; - while (retries < 3) { - try { - for (let button of await statusBar.getItems()) { - if ((await button.getText()).startsWith('mirrord')) { - await button.click(); - return true; + it("select pod from quickpick", async function () { + await startDebugging(); + const inputBox = await InputBox.create(defaultTimeout * 2); + // assertion that podToSelect is not undefined is done in "before" block + await browser.driver.wait(async () => { + if (!await inputBox.isDisplayed()) { + return false; } - } - } catch (e) { - if (e instanceof Error && e.name === 'StaleElementReferenceError') { - await new Promise(resolve => setTimeout(resolve, 1000)); - retries++; - } else { - throw e; - } - } - } - throw new Error('Failed to click the button after multiple attempts'); - }, defaultTimeout, "mirrord `enable` button not found -- timed out"); - }); - - it("select pod from quickpick", async function() { - await startDebugging(); - const inputBox = await InputBox.create(defaultTimeout * 2); - // assertion that podToSelect is not undefined is done in "before" block - await browser.driver.wait(async () => { - if (!await inputBox.isDisplayed()) { - return false; - } - - for (const pick of await inputBox.getQuickPicks()) { - let label = await pick.getLabel(); - - if (label === podToSelect) { - return true; - } - // to pick up the podToSelect, we need to select the "Show Pods" - // from quickpick as pods are not displayed first - if (label === "Show Pods") { - await pick.select(); - } - } - return false; - }, defaultTimeout * 2, "quickPick not found -- timed out"); + for (const pick of await inputBox.getQuickPicks()) { + let label = await pick.getLabel(); + + if (label === podToSelect) { + return true; + } + // to pick up the podToSelect, we need to select the "Show Pods" + // from quickpick as pods are not displayed first + if (label === "Show Pods") { + await pick.select(); + } + } + + return false; + }, defaultTimeout * 2, "quickPick not found -- timed out"); + + await inputBox.selectQuickPick(podToSelect!); + }); + + it("wait for breakpoint to be hit", async function () { + const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); + const panel = new BottomBarPanel(); + const textEditor = new TextEditor(); + await browser.driver.wait(async () => { + return await debugToolbar.isDisplayed(); + }, 2 * defaultTimeout, "debug toolbar not found -- timed out"); - await inputBox.selectQuickPick(podToSelect!); - }); - it("wait for process to write to terminal", async function() { - const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); - const panel = new BottomBarPanel(); - await browser.driver.wait(async () => { - return await debugToolbar.isDisplayed(); - }, 2 * defaultTimeout, "debug toolbar not found -- timed out"); + let terminal = await panel.openTerminalView(); + await browser.driver.wait(async () => { + const text = await terminal.getText(); + return await terminal.isDisplayed() && text.includes("Press CTRL+C to quit"); + }, 2 * defaultTimeout, "terminal text not found -- timed out"); - let terminal = await panel.openTerminalView(); - await browser.driver.wait(async () => { - const text = await terminal.getText(); - return await terminal.isDisplayed() && text.includes("Press CTRL+C to quit"); - }, 2 * defaultTimeout, "terminal text not found -- timed out"); + const result = await textEditor.toggleBreakpoint(9); + expect(result).to.be.true; - await sendTrafficToPod(); + await sendTrafficToPod(); - await browser.driver.wait(async () => { - const text = await terminal.getText(); - return text.includes("GET: Request completed"); - }, defaultTimeout, "terminal text not found -- timed out"); + await browser.driver.wait(async () => { + const text = await terminal.getText(); + return text.includes("GET: Request completed"); + }, defaultTimeout, "terminal text not found -- timed out"); - }); + const breakpoint = await textEditor.getPausedBreakpoint(); + expect(breakpoint).to.not.be.undefined; + const lineNumber = await breakpoint?.getLineNumber(); + expect(lineNumber).to.equal(9); + }); }); @@ -138,19 +148,19 @@ describe("mirrord sample flow test", function() { * sends a GET request to the pod's nodePort */ async function sendTrafficToPod() { - const response = await get(kubeService!!); - expect(response.status).to.equal(200); - expect(response.data).to.equal("OK - GET: Request completed\n"); + const response = await get(kubeService!!); + expect(response.status).to.equal(200); + expect(response.data).to.equal("OK - GET: Request completed\n"); } /** * starts debugging the current file with the provided configuration - * debugging starts from the "Run and Debug" button in the activity bar + * debugging starts from the "Run and Debug" button in the activity bar */ async function startDebugging(configurationFile: string = "Python: Current File") { - const activityBar = await new ActivityBar().getViewControl("Run and Debug"); - expect(activityBar).to.not.be.undefined; - const debugView = await activityBar?.openView() as DebugView; - await debugView.selectLaunchConfiguration(configurationFile); - await debugView.start(); -} + const activityBar = await new ActivityBar().getViewControl("Run and Debug"); + expect(activityBar).to.not.be.undefined; + const debugView = await activityBar?.openView() as DebugView; + await debugView.selectLaunchConfiguration(configurationFile); + await debugView.start(); +} \ No newline at end of file From b585bdc96b5f8f57f3da7619ee5d43fee378070a Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sun, 22 Oct 2023 12:59:47 -0400 Subject: [PATCH 02/24] unneeded file --- .mirrord/mirrord.json | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .mirrord/mirrord.json diff --git a/.mirrord/mirrord.json b/.mirrord/mirrord.json deleted file mode 100644 index 46b0a57c..00000000 --- a/.mirrord/mirrord.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "feature": { - "network": { - "incoming": "mirror", - "outgoing": true - }, - "fs": "read", - "env": true - } -} From ace812e65c4702012cef078dfcffa233a45ffcbe Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sun, 22 Oct 2023 13:00:37 -0400 Subject: [PATCH 03/24] revert --- src/tests/e2e.ts | 220 ++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 115 deletions(-) diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index 4e4edc39..7af89f19 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -1,8 +1,7 @@ import { expect } from "chai"; import { join } from "path"; -import { VSBrowser, StatusBar, ActivityBar, DebugView, InputBox, DebugToolbar, BottomBarPanel, EditorView, TextEditor } from "vscode-extension-tester"; +import { VSBrowser, StatusBar, ActivityBar, DebugView, InputBox, DebugToolbar, BottomBarPanel, EditorView } from "vscode-extension-tester"; import get from "axios"; -import exp from "constants"; const kubeService = process.env.KUBE_SERVICE; const podToSelect = process.env.POD_TO_SELECT; @@ -16,131 +15,122 @@ const podToSelect = process.env.POD_TO_SELECT; * - Send traffic to the pod * - Tests successfully exit if "GET: Request completed" is found in the terminal */ -describe("mirrord sample flow test", function () { +describe("mirrord sample flow test", function() { - this.timeout("6 minutes"); // --> mocha tests timeout - this.bail(true); // --> stop tests on first failure + this.timeout("6 minutes"); // --> mocha tests timeout + this.bail(true); // --> stop tests on first failure - let browser: VSBrowser; + let browser: VSBrowser; - const testWorkspace = join(__dirname, '../../test-workspace'); - const fileName = "app_flask.py"; - const defaultTimeout = 10000; // = 10 seconds + const testWorkspace = join(__dirname, '../../test-workspace'); + const fileName = "app_flask.py"; + const defaultTimeout = 10000; // = 10 seconds - before(async function () { - console.log("podToSelect: " + podToSelect); - console.log("kubeService: " + kubeService); + before(async function() { + console.log("podToSelect: " + podToSelect); + console.log("kubeService: " + kubeService); - expect(podToSelect).to.not.be.undefined; - expect(kubeService).to.not.be.undefined; + expect(podToSelect).to.not.be.undefined; + expect(kubeService).to.not.be.undefined; - browser = VSBrowser.instance; + browser = VSBrowser.instance; - await browser.openResources(testWorkspace, join(testWorkspace, fileName)); - await browser.waitForWorkbench(); + await browser.openResources(testWorkspace, join(testWorkspace, fileName)); + await browser.waitForWorkbench(); - const ew = new EditorView(); - try { - await ew.closeEditor('Welcome'); - } catch (error) { - console.log("Welcome page is not displayed" + error) - // continue - Welcome page is not displayed - } - await ew.openEditor('app_flask.py'); - }); + const ew = new EditorView(); + try { + await ew.closeEditor('Welcome'); + } catch (error) { + console.log("Welcome page is not displayed" + error); + // continue - Welcome page is not displayed + } + await ew.openEditor('app_flask.py'); + }); - it("enable mirrord button", async function () { - const statusBar = new StatusBar(); - - await browser.driver.wait(async () => { - return await statusBar.isDisplayed(); - }); - - // vscode refreshes the status bar on load and there is no deterministic way but to retry to click on - // the mirrord button after an interval - await browser.driver.wait(async () => { - let retries = 0; - while (retries < 3) { - try { - for (let button of await statusBar.getItems()) { - if ((await button.getText()).startsWith('mirrord')) { - await button.click(); - return true; - } - } - } catch (e) { - if (e instanceof Error && e.name === 'StaleElementReferenceError') { - await new Promise(resolve => setTimeout(resolve, 1000)); - retries++; - } else { - throw e; - } - } - } - throw new Error('Failed to click the button after multiple attempts'); - }, defaultTimeout, "mirrord `enable` button not found -- timed out"); - }); + it("enable mirrord button", async function() { + const statusBar = new StatusBar(); - it("select pod from quickpick", async function () { - await startDebugging(); - const inputBox = await InputBox.create(defaultTimeout * 2); - // assertion that podToSelect is not undefined is done in "before" block - await browser.driver.wait(async () => { - if (!await inputBox.isDisplayed()) { - return false; - } + await browser.driver.wait(async () => { + return await statusBar.isDisplayed(); + }); - for (const pick of await inputBox.getQuickPicks()) { - let label = await pick.getLabel(); - - if (label === podToSelect) { - return true; - } - // to pick up the podToSelect, we need to select the "Show Pods" - // from quickpick as pods are not displayed first - if (label === "Show Pods") { - await pick.select(); - } + // vscode refreshes the status bar on load and there is no deterministic way but to retry to click on + // the mirrord button after an interval + await browser.driver.wait(async () => { + let retries = 0; + while (retries < 3) { + try { + for (let button of await statusBar.getItems()) { + if ((await button.getText()).startsWith('mirrord')) { + await button.click(); + return true; } + } + } catch (e) { + if (e instanceof Error && e.name === 'StaleElementReferenceError') { + await new Promise(resolve => setTimeout(resolve, 1000)); + retries++; + } else { + throw e; + } + } + } + throw new Error('Failed to click the button after multiple attempts'); + }, defaultTimeout, "mirrord `enable` button not found -- timed out"); + }); + + it("select pod from quickpick", async function() { + await startDebugging(); + const inputBox = await InputBox.create(defaultTimeout * 2); + // assertion that podToSelect is not undefined is done in "before" block + await browser.driver.wait(async () => { + if (!await inputBox.isDisplayed()) { + return false; + } + + for (const pick of await inputBox.getQuickPicks()) { + let label = await pick.getLabel(); + + if (label === podToSelect) { + return true; + } + // to pick up the podToSelect, we need to select the "Show Pods" + // from quickpick as pods are not displayed first + if (label === "Show Pods") { + await pick.select(); + } + } - return false; - }, defaultTimeout * 2, "quickPick not found -- timed out"); - - await inputBox.selectQuickPick(podToSelect!); - }); - - it("wait for breakpoint to be hit", async function () { - const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); - const panel = new BottomBarPanel(); - const textEditor = new TextEditor(); - await browser.driver.wait(async () => { - return await debugToolbar.isDisplayed(); - }, 2 * defaultTimeout, "debug toolbar not found -- timed out"); + return false; + }, defaultTimeout * 2, "quickPick not found -- timed out"); + await inputBox.selectQuickPick(podToSelect!); + }); - let terminal = await panel.openTerminalView(); + it("wait for process to write to terminal", async function() { + const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); + const panel = new BottomBarPanel(); + await browser.driver.wait(async () => { + return await debugToolbar.isDisplayed(); + }, 2 * defaultTimeout, "debug toolbar not found -- timed out"); - await browser.driver.wait(async () => { - const text = await terminal.getText(); - return await terminal.isDisplayed() && text.includes("Press CTRL+C to quit"); - }, 2 * defaultTimeout, "terminal text not found -- timed out"); + let terminal = await panel.openTerminalView(); - const result = await textEditor.toggleBreakpoint(9); - expect(result).to.be.true; + await browser.driver.wait(async () => { + const text = await terminal.getText(); + return await terminal.isDisplayed() && text.includes("Press CTRL+C to quit"); + }, 2 * defaultTimeout, "terminal text not found -- timed out"); - await sendTrafficToPod(); + await sendTrafficToPod(); - await browser.driver.wait(async () => { - const text = await terminal.getText(); - return text.includes("GET: Request completed"); - }, defaultTimeout, "terminal text not found -- timed out"); + await browser.driver.wait(async () => { + const text = await terminal.getText(); + return text.includes("GET: Request completed"); + }, defaultTimeout, "terminal text not found -- timed out"); - const breakpoint = await textEditor.getPausedBreakpoint(); - expect(breakpoint).to.not.be.undefined; - const lineNumber = await breakpoint?.getLineNumber(); - expect(lineNumber).to.equal(9); - }); + }); }); @@ -148,19 +138,19 @@ describe("mirrord sample flow test", function () { * sends a GET request to the pod's nodePort */ async function sendTrafficToPod() { - const response = await get(kubeService!!); - expect(response.status).to.equal(200); - expect(response.data).to.equal("OK - GET: Request completed\n"); + const response = await get(kubeService!!); + expect(response.status).to.equal(200); + expect(response.data).to.equal("OK - GET: Request completed\n"); } /** * starts debugging the current file with the provided configuration - * debugging starts from the "Run and Debug" button in the activity bar + * debugging starts from the "Run and Debug" button in the activity bar */ async function startDebugging(configurationFile: string = "Python: Current File") { - const activityBar = await new ActivityBar().getViewControl("Run and Debug"); - expect(activityBar).to.not.be.undefined; - const debugView = await activityBar?.openView() as DebugView; - await debugView.selectLaunchConfiguration(configurationFile); - await debugView.start(); + const activityBar = await new ActivityBar().getViewControl("Run and Debug"); + expect(activityBar).to.not.be.undefined; + const debugView = await activityBar?.openView() as DebugView; + await debugView.selectLaunchConfiguration(configurationFile); + await debugView.start(); } \ No newline at end of file From 66f6534e45291e8f272546bd03b9363ce95a5933 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sun, 22 Oct 2023 16:47:19 -0400 Subject: [PATCH 04/24] .. --- package-lock.json | 2 +- package.json | 2 +- src/binaryManager.ts | 111 ++++++++++++++++++++++--------------------- src/status.ts | 9 ++-- 4 files changed, 64 insertions(+), 60 deletions(-) diff --git a/package-lock.json b/package-lock.json index 44b4c201..e33c1c17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.54.1", "dependencies": { "axios": "^1.4.0", - "semver": "^7.3.7", + "semver": "^7.5.4", "toml": "^3.0.0", "vscode-uri": "^3.0.7", "which": "^3.0.1", diff --git a/package.json b/package.json index dcba02e9..7a02394b 100644 --- a/package.json +++ b/package.json @@ -226,7 +226,7 @@ }, "dependencies": { "axios": "^1.4.0", - "semver": "^7.3.7", + "semver": "^7.5.4", "toml": "^3.0.0", "vscode-uri": "^3.0.7", "which": "^3.0.1", diff --git a/src/binaryManager.ts b/src/binaryManager.ts index b2cd0588..3a636126 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -8,13 +8,14 @@ import * as fs from 'node:fs'; import { platform } from 'os'; import { Uri, workspace, window, ProgressLocation, ExtensionMode, InputBoxOptions } from 'vscode'; import { NotificationBuilder } from './notification'; +import { eq, gte, lt } from 'semver'; const mirrordBinaryEndpoint = 'https://version.mirrord.dev/v1/version'; // const binaryCheckInterval = 1000 * 60 * 3; const baseDownloadUri = 'https://github.com/metalbear-co/mirrord/releases/download'; export let autoUpdate = true; -let mirrordBinaryVersion: string | null = null; +let userSpecifiedMirrordBinaryVersion: string | null | undefined = null; function getExtensionMirrordPath(): Uri { return Utils.joinPath(globalContext.globalStorageUri, 'mirrord'); @@ -24,34 +25,17 @@ function getExtensionMirrordPath(): Uri { /** * Tries to find local mirrord in path or in extension storage. */ -export async function getLocalMirrordBinary(version?: string): Promise { +export async function getLocalMirrordBinary(): Promise { try { const mirrordPath = await which("mirrord"); - if (version) { - const api = new MirrordAPI(mirrordPath); - const installedVersion = await api.getBinaryVersion(); - if (installedVersion === version) { - return mirrordPath; - } - } else { - return mirrordPath; - } + return mirrordPath; } catch (e) { console.debug("couldn't find mirrord in path"); } try { const mirrordPath = getExtensionMirrordPath(); await workspace.fs.stat(mirrordPath); - if (version) { - const api = new MirrordAPI(mirrordPath.fsPath); - const installedVersion = await api.getBinaryVersion(); - if (installedVersion === version) { - return mirrordPath.fsPath; - } - } else { - return mirrordPath.fsPath; - } - + return mirrordPath.fsPath; } catch (e) { console.log("couldn't find mirrord in extension storage"); } @@ -102,27 +86,42 @@ async function getConfiguredMirrordBinary(): Promise { export async function getMirrordBinary(): Promise { const configured = await getConfiguredMirrordBinary(); if (configured) { + await vscode.window.showInformationMessage(`Using mirrord binary specified in settings: ${configured}`); return configured; } - let foundLocal = await getLocalMirrordBinary(); - // timeout is 1s if we have alternative or 10s if we don't - let timeout = foundLocal ? 1000 : 10000; - const latestVersion = await getLatestSupportedVersion(timeout); - - // See if maybe we have it installed already, in correct version. - const localMirrord = await getLocalMirrordBinary(latestVersion); - if (localMirrord) { - const api = new MirrordAPI(localMirrord); - const installedVersion = await api.getBinaryVersion(); - if (installedVersion === latestVersion) { - return localMirrord; + const extensionMirrordPath = getExtensionMirrordPath(); + const latestVersion = await getLatestSupportedVersion(10000); + + if (autoUpdate) { + await downloadMirrordBinary(extensionMirrordPath, latestVersion); + return extensionMirrordPath.fsPath; + } else { + if (userSpecifiedMirrordBinaryVersion) { + await downloadMirrordBinary(extensionMirrordPath, userSpecifiedMirrordBinaryVersion); + return extensionMirrordPath.fsPath; + } else { + let localMirrord = await getLocalMirrordBinary(); + if (localMirrord) { + const api = new MirrordAPI(localMirrord); + const installedVersion = await api.getBinaryVersion(); + + // in the release CI - the semver version is greater than the current remote semver version + // and hence, we need to use the local version + + if (installedVersion !== null && installedVersion !== undefined && lt(installedVersion, latestVersion)) { + await vscode.window.showInformationMessage(`Using local mirrord binary: ${localMirrord} which is outdated. Latest supported version is ${latestVersion}`); + } else if (installedVersion !== null && installedVersion !== undefined && eq(installedVersion, latestVersion)) { + await vscode.window.showInformationMessage(`Using local mirrord binary: ${localMirrord} which is up-to-date`); + } else if (installedVersion !== null && installedVersion !== undefined && gte(installedVersion, latestVersion)) { + await vscode.window.showInformationMessage(`Using local mirrord binary: ${localMirrord} which is newer than the latest supported version ${latestVersion}. Possily a CI build`); + } + + return localMirrord; + } } } - const extensionMirrordPath = getExtensionMirrordPath(); - await downloadMirrordBinary(extensionMirrordPath, latestVersion); - return extensionMirrordPath.fsPath; } @@ -201,29 +200,35 @@ async function downloadMirrordBinary(destPath: Uri, version: string): Promise { - if (value !== "") { - if (/^[0-9]+\\.[0-9]+\\.[0-9]+$/.test(value)) { - vscode.window.showErrorMessage("Invalid version format ${value}: must follow semver format"); - } - } - return null; - } + prompt: "auto-update will be disabled, mirrord will be updated to the specified version.", + placeHolder: "Current version: " + userSpecifiedMirrordBinaryVersion ?? "unspecified", }; - - await vscode.window.showInputBox(options); + const value = await vscode.window.showInputBox(options); + if (value && value !== "" && !(/^[0-9]+\.[0-9]+\.[0-9]+$/.test(value))) { + vscode.window.showErrorMessage(`Invalid version format ${value}: must follow semver format`); + } + autoUpdate = false; + + if (value !== undefined) { + if (value !== null && userSpecifiedMirrordBinaryVersion === null) { + userSpecifiedMirrordBinaryVersion = value; + } + } + vscode.window.showInformationMessage("Auto-update disabled"); } else { autoUpdate = true; vscode.window.showInformationMessage("Auto-update enabled"); } -} +} \ No newline at end of file diff --git a/src/status.ts b/src/status.ts index 318e6ebb..8f254680 100644 --- a/src/status.ts +++ b/src/status.ts @@ -19,7 +19,7 @@ export class MirrordStatus { this.statusBar = statusBar; } - draw() { + public draw() { const { enabled, statusBar, @@ -39,10 +39,8 @@ export class MirrordStatus { const activeConfig = MirrordConfigManager.getInstance().activeConfig(); if (activeConfig) { statusBar.tooltip.appendMarkdown(`\n\n[Active config: ${vscode.workspace.asRelativePath(activeConfig)}](${activeConfig})`); - } - - const autoUpdateState = autoUpdate; - statusBar.tooltip.appendMarkdown(`\n\n[Auto-update: ${autoUpdateState ? 'Enabled' : 'Disabled'}](command:${MirrordStatus.autoUpdateCommandId})`); + } + statusBar.tooltip.appendMarkdown(`\n\n[Auto-update: ${autoUpdate ? 'Enabled' : 'Disabled'}](command:${MirrordStatus.autoUpdateCommandId})`); statusBar.tooltip.appendMarkdown(`\n\n[Select active config](command:${MirrordStatus.selectActiveConfigId})`); statusBar.tooltip.appendMarkdown(`\n\n[Settings](command:${MirrordStatus.settingsCommandId})`); statusBar.tooltip.appendMarkdown(`\n\n[mirrord for Teams Waitlist](command:${MirrordStatus.waitlistCommandId})`); @@ -63,6 +61,7 @@ export class MirrordStatus { })); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.autoUpdateCommandId, async () => { await toggleAutoUpdate(); + this.draw(); })); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.settingsCommandId, configManager.changeSettings.bind(configManager))); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.toggleCommandId, this.toggle.bind(this))); From f2c488ffb1ed4b185f3171ebbcd7e5c33f7e5792 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sun, 22 Oct 2023 18:27:28 -0400 Subject: [PATCH 05/24] .. --- src/binaryManager.ts | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index 3a636126..961bdb5b 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -118,6 +118,8 @@ export async function getMirrordBinary(): Promise { } return localMirrord; + } else { + await downloadMirrordBinary(extensionMirrordPath, latestVersion); } } } @@ -206,26 +208,32 @@ async function downloadMirrordBinary(destPath: Uri, version: string): Promise Date: Sun, 22 Oct 2023 18:30:33 -0400 Subject: [PATCH 06/24] changelog --- changelog.d/62.added.md | 1 + src/status.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/62.added.md diff --git a/changelog.d/62.added.md b/changelog.d/62.added.md new file mode 100644 index 00000000..a02957b8 --- /dev/null +++ b/changelog.d/62.added.md @@ -0,0 +1 @@ +Add option to disable auto-update diff --git a/src/status.ts b/src/status.ts index 8f254680..34c5c163 100644 --- a/src/status.ts +++ b/src/status.ts @@ -19,7 +19,7 @@ export class MirrordStatus { this.statusBar = statusBar; } - public draw() { + draw() { const { enabled, statusBar, From a28ff84e4d5325039af303f70a9e744bc7e031cb Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Wed, 25 Oct 2023 22:55:57 -0400 Subject: [PATCH 07/24] CR --- src/binaryManager.ts | 142 ++++++++++++++++++++----------------------- src/status.ts | 11 +--- 2 files changed, 67 insertions(+), 86 deletions(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index 961bdb5b..17f84052 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -8,15 +8,12 @@ import * as fs from 'node:fs'; import { platform } from 'os'; import { Uri, workspace, window, ProgressLocation, ExtensionMode, InputBoxOptions } from 'vscode'; import { NotificationBuilder } from './notification'; -import { eq, gte, lt } from 'semver'; +import * as semver from 'semver'; const mirrordBinaryEndpoint = 'https://version.mirrord.dev/v1/version'; // const binaryCheckInterval = 1000 * 60 * 3; const baseDownloadUri = 'https://github.com/metalbear-co/mirrord/releases/download'; -export let autoUpdate = true; -let userSpecifiedMirrordBinaryVersion: string | null | undefined = null; - function getExtensionMirrordPath(): Uri { return Utils.joinPath(globalContext.globalStorageUri, 'mirrord'); } @@ -25,17 +22,37 @@ function getExtensionMirrordPath(): Uri { /** * Tries to find local mirrord in path or in extension storage. */ -export async function getLocalMirrordBinary(): Promise { +export async function getLocalMirrordBinary(version?: string): Promise { try { const mirrordPath = await which("mirrord"); - return mirrordPath; + if (version) { + const api = new MirrordAPI(mirrordPath); + const installedVersion = await api.getBinaryVersion(); + + // we use semver.get here because installedVersion can be greater than the latest version + // if we are running on the release CI. + if (installedVersion && semver.gte(installedVersion, version)) { + return mirrordPath; + } + } else { + return mirrordPath; + } } catch (e) { console.debug("couldn't find mirrord in path"); } try { const mirrordPath = getExtensionMirrordPath(); await workspace.fs.stat(mirrordPath); - return mirrordPath.fsPath; + if (version) { + const api = new MirrordAPI(mirrordPath.fsPath); + const installedVersion = await api.getBinaryVersion(); + if (installedVersion === version) { + return mirrordPath.fsPath; + } + } else { + return mirrordPath.fsPath; + } + } catch (e) { console.log("couldn't find mirrord in extension storage"); } @@ -81,49 +98,60 @@ async function getConfiguredMirrordBinary(): Promise { } /** - * Downloads mirrord binary (if needed) and returns its path - */ + * Auto-update configuration i.e. workspace settings for mirrord auto-update +*/ + +interface AutoUpdateConfiguration { + enabled: boolean; + version: string | null; +} + +/** + * Toggles auto-update of mirrord binary. + * Criteria for auto-update: + * - Auto-update is enabled by default + * - if mirrord binary path is mentioned in workspace settings, then that is used + * - if auto-update is enabled, then latest supported version is downloaded + * - if auto-update is disabled, and a version is specified, then that version is downloaded + * - if auto-update is disabled, and no version is specified, then local mirrord binary is used + * * - if auto-update is disabled, and no version is specified, and no local mirrord binary is found, then latest supported version is downloaded + * @returns Path to mirrord binary +*/ export async function getMirrordBinary(): Promise { const configured = await getConfiguredMirrordBinary(); + if (configured) { - await vscode.window.showInformationMessage(`Using mirrord binary specified in settings: ${configured}`); + vscode.window.showInformationMessage(`Using mirrord binary specified in settings: ${configured}`); return configured; } + const autoUpdateConfigured: AutoUpdateConfiguration | null = vscode.workspace.getConfiguration().get("mirrord.autoUpdate", { enabled: true, version: null }); + const extensionMirrordPath = getExtensionMirrordPath(); const latestVersion = await getLatestSupportedVersion(10000); - if (autoUpdate) { - await downloadMirrordBinary(extensionMirrordPath, latestVersion); - return extensionMirrordPath.fsPath; - } else { - if (userSpecifiedMirrordBinaryVersion) { - await downloadMirrordBinary(extensionMirrordPath, userSpecifiedMirrordBinaryVersion); - return extensionMirrordPath.fsPath; - } else { - let localMirrord = await getLocalMirrordBinary(); - if (localMirrord) { - const api = new MirrordAPI(localMirrord); - const installedVersion = await api.getBinaryVersion(); - - // in the release CI - the semver version is greater than the current remote semver version - // and hence, we need to use the local version - - if (installedVersion !== null && installedVersion !== undefined && lt(installedVersion, latestVersion)) { - await vscode.window.showInformationMessage(`Using local mirrord binary: ${localMirrord} which is outdated. Latest supported version is ${latestVersion}`); - } else if (installedVersion !== null && installedVersion !== undefined && eq(installedVersion, latestVersion)) { - await vscode.window.showInformationMessage(`Using local mirrord binary: ${localMirrord} which is up-to-date`); - } else if (installedVersion !== null && installedVersion !== undefined && gte(installedVersion, latestVersion)) { - await vscode.window.showInformationMessage(`Using local mirrord binary: ${localMirrord} which is newer than the latest supported version ${latestVersion}. Possily a CI build`); - } - - return localMirrord; - } else { - await downloadMirrordBinary(extensionMirrordPath, latestVersion); + if (autoUpdateConfigured && !autoUpdateConfigured.enabled) { + if (autoUpdateConfigured.version && semver.valid(autoUpdateConfigured.version)) { + const localMirrordBinary = await getLocalMirrordBinary(autoUpdateConfigured.version); + if (localMirrordBinary) { + return localMirrordBinary; } + await downloadMirrordBinary(extensionMirrordPath, autoUpdateConfigured.version); + } else { + vscode.window.showErrorMessage(`Invalid version format ${autoUpdateConfigured.version}: must follow semver format`); } } + // Auto-update is enabled or no specific version specified. + const localMirrordBinary = await getLocalMirrordBinary(); + + if (localMirrordBinary) { + return localMirrordBinary; + } + + // No local mirrord binary found, download the latest supported version. + await downloadMirrordBinary(extensionMirrordPath, latestVersion); + return extensionMirrordPath.fsPath; } @@ -199,44 +227,4 @@ async function downloadMirrordBinary(destPath: Uri, version: string): Promise { await configManager.selectActiveConfig(); })); - globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.autoUpdateCommandId, async () => { - await toggleAutoUpdate(); - this.draw(); - })); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.settingsCommandId, configManager.changeSettings.bind(configManager))); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.toggleCommandId, this.toggle.bind(this))); globalContext.subscriptions.push(vscode.commands.registerCommand(MirrordStatus.submitFeedbackCommandId, this.submitFeedback.bind(this))); From ca76b8e5585bf6ac0ecdd04a2581d4f9076efa79 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Wed, 25 Oct 2023 22:56:33 -0400 Subject: [PATCH 08/24] .. --- src/binaryManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index 17f84052..cb583421 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -6,7 +6,7 @@ import { MirrordAPI } from './api'; import { Utils } from 'vscode-uri'; import * as fs from 'node:fs'; import { platform } from 'os'; -import { Uri, workspace, window, ProgressLocation, ExtensionMode, InputBoxOptions } from 'vscode'; +import { Uri, workspace, window, ProgressLocation, ExtensionMode } from 'vscode'; import { NotificationBuilder } from './notification'; import * as semver from 'semver'; From f2c460de321ba039c6564ebe4c648caec52637a6 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Thu, 26 Oct 2023 11:31:29 -0400 Subject: [PATCH 09/24] wip --- package.json | 5 ++ src/binaryManager.ts | 69 +++++++++++----------------- src/tests/e2e.ts | 10 ++-- test-workspace/.vscode/settings.json | 7 +++ 4 files changed, 45 insertions(+), 46 deletions(-) create mode 100644 test-workspace/.vscode/settings.json diff --git a/package.json b/package.json index 7a02394b..a01d3c4b 100644 --- a/package.json +++ b/package.json @@ -120,6 +120,11 @@ ], "default": null, "description": "Path to local mirrord installation." + }, + "mirrord.autoUpdate": { + "type": ["string", "boolean"], + "default": true, + "description": "Automatically update mirrord binary." } } }, diff --git a/src/binaryManager.ts b/src/binaryManager.ts index cb583421..28fa62cd 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -23,6 +23,22 @@ function getExtensionMirrordPath(): Uri { * Tries to find local mirrord in path or in extension storage. */ export async function getLocalMirrordBinary(version?: string): Promise { + try { + const mirrordPath = getExtensionMirrordPath(); + await workspace.fs.stat(mirrordPath); + if (version) { + const api = new MirrordAPI(mirrordPath.fsPath); + const installedVersion = await api.getBinaryVersion(); + if (installedVersion === version) { + return mirrordPath.fsPath; + } + } else { + return mirrordPath.fsPath; + } + + } catch (e) { + console.log("couldn't find mirrord in extension storage"); + } try { const mirrordPath = await which("mirrord"); if (version) { @@ -40,22 +56,6 @@ export async function getLocalMirrordBinary(version?: string): Promise { return configured; } -/** - * Auto-update configuration i.e. workspace settings for mirrord auto-update -*/ - -interface AutoUpdateConfiguration { - enabled: boolean; - version: string | null; -} - /** * Toggles auto-update of mirrord binary. * Criteria for auto-update: @@ -114,7 +105,7 @@ interface AutoUpdateConfiguration { * - if auto-update is enabled, then latest supported version is downloaded * - if auto-update is disabled, and a version is specified, then that version is downloaded * - if auto-update is disabled, and no version is specified, then local mirrord binary is used - * * - if auto-update is disabled, and no version is specified, and no local mirrord binary is found, then latest supported version is downloaded + * - if auto-update is disabled, and no version is specified, and no local mirrord binary is found, then latest supported version is downloaded * @returns Path to mirrord binary */ export async function getMirrordBinary(): Promise { @@ -124,35 +115,31 @@ export async function getMirrordBinary(): Promise { vscode.window.showInformationMessage(`Using mirrord binary specified in settings: ${configured}`); return configured; } + const latestVersion = await getLatestSupportedVersion(10000); - const autoUpdateConfigured: AutoUpdateConfiguration | null = vscode.workspace.getConfiguration().get("mirrord.autoUpdate", { enabled: true, version: null }); + const autoUpdateConfigured = vscode.workspace.getConfiguration().get("mirrord.autoUpdate", true); - const extensionMirrordPath = getExtensionMirrordPath(); - const latestVersion = await getLatestSupportedVersion(10000); - if (autoUpdateConfigured && !autoUpdateConfigured.enabled) { - if (autoUpdateConfigured.version && semver.valid(autoUpdateConfigured.version)) { - const localMirrordBinary = await getLocalMirrordBinary(autoUpdateConfigured.version); + if (typeof autoUpdateConfigured === 'string') { + if (semver.valid(autoUpdateConfigured)) { + const localMirrordBinary = await getLocalMirrordBinary(autoUpdateConfigured); if (localMirrordBinary) { return localMirrordBinary; } - await downloadMirrordBinary(extensionMirrordPath, autoUpdateConfigured.version); + await downloadMirrordBinary(getExtensionMirrordPath(), autoUpdateConfigured); + return getExtensionMirrordPath().fsPath; } else { - vscode.window.showErrorMessage(`Invalid version format ${autoUpdateConfigured.version}: must follow semver format`); + vscode.window.showErrorMessage(`Invalid version format ${autoUpdateConfigured}: must follow semver format`); } } - // Auto-update is enabled or no specific version specified. + // Auto-update is enabled or no specific version specified. const localMirrordBinary = await getLocalMirrordBinary(); - if (localMirrordBinary) { return localMirrordBinary; } - - // No local mirrord binary found, download the latest supported version. - await downloadMirrordBinary(extensionMirrordPath, latestVersion); - - return extensionMirrordPath.fsPath; + await downloadMirrordBinary(getExtensionMirrordPath(), latestVersion); + return getExtensionMirrordPath().fsPath; } /** diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index 7af89f19..9ab6fc22 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -15,7 +15,7 @@ const podToSelect = process.env.POD_TO_SELECT; * - Send traffic to the pod * - Tests successfully exit if "GET: Request completed" is found in the terminal */ -describe("mirrord sample flow test", function() { +describe("mirrord sample flow test", function () { this.timeout("6 minutes"); // --> mocha tests timeout this.bail(true); // --> stop tests on first failure @@ -26,7 +26,7 @@ describe("mirrord sample flow test", function() { const fileName = "app_flask.py"; const defaultTimeout = 10000; // = 10 seconds - before(async function() { + before(async function () { console.log("podToSelect: " + podToSelect); console.log("kubeService: " + kubeService); @@ -48,7 +48,7 @@ describe("mirrord sample flow test", function() { await ew.openEditor('app_flask.py'); }); - it("enable mirrord button", async function() { + it("enable mirrord button", async function () { const statusBar = new StatusBar(); await browser.driver.wait(async () => { @@ -80,7 +80,7 @@ describe("mirrord sample flow test", function() { }, defaultTimeout, "mirrord `enable` button not found -- timed out"); }); - it("select pod from quickpick", async function() { + it("select pod from quickpick", async function () { await startDebugging(); const inputBox = await InputBox.create(defaultTimeout * 2); // assertion that podToSelect is not undefined is done in "before" block @@ -108,7 +108,7 @@ describe("mirrord sample flow test", function() { await inputBox.selectQuickPick(podToSelect!); }); - it("wait for process to write to terminal", async function() { + it("wait for process to write to terminal", async function () { const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); const panel = new BottomBarPanel(); await browser.driver.wait(async () => { diff --git a/test-workspace/.vscode/settings.json b/test-workspace/.vscode/settings.json new file mode 100644 index 00000000..f18e2f8b --- /dev/null +++ b/test-workspace/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "mirrord.autoUpdate": { + "enabled": false, + "version": "3.70.0" + }, + "mirrord.binaryPath": null +} \ No newline at end of file From fceeb2a3fa468ec6db943204bf364b0dd9cbada8 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sun, 29 Oct 2023 11:31:35 -0400 Subject: [PATCH 10/24] .. --- src/binaryManager.ts | 25 ++++++++++++++++++------- src/extension.ts | 5 +++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index 28fa62cd..dca5e05e 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -102,10 +102,9 @@ async function getConfiguredMirrordBinary(): Promise { * Criteria for auto-update: * - Auto-update is enabled by default * - if mirrord binary path is mentioned in workspace settings, then that is used + * - if a version is specified, that version is downloaded * - if auto-update is enabled, then latest supported version is downloaded - * - if auto-update is disabled, and a version is specified, then that version is downloaded - * - if auto-update is disabled, and no version is specified, then local mirrord binary is used - * - if auto-update is disabled, and no version is specified, and no local mirrord binary is found, then latest supported version is downloaded + * - if auto-update is disabled, any local mirrord binary is used * @returns Path to mirrord binary */ export async function getMirrordBinary(): Promise { @@ -117,7 +116,9 @@ export async function getMirrordBinary(): Promise { } const latestVersion = await getLatestSupportedVersion(10000); - const autoUpdateConfigured = vscode.workspace.getConfiguration().get("mirrord.autoUpdate", true); + const autoUpdateConfigured = vscode.workspace.getConfiguration().get("mirrord.autoUpdate"); + + const extensionPath = getExtensionMirrordPath().fsPath; if (typeof autoUpdateConfigured === 'string') { @@ -127,19 +128,29 @@ export async function getMirrordBinary(): Promise { return localMirrordBinary; } await downloadMirrordBinary(getExtensionMirrordPath(), autoUpdateConfigured); - return getExtensionMirrordPath().fsPath; + return extensionPath; } else { vscode.window.showErrorMessage(`Invalid version format ${autoUpdateConfigured}: must follow semver format`); } } + if (typeof autoUpdateConfigured === 'boolean') { + if (!autoUpdateConfigured) { + const localMirrordBinary = await getLocalMirrordBinary(); + if (localMirrordBinary) { + return localMirrordBinary; + } + return extensionPath; + } + } + // Auto-update is enabled or no specific version specified. - const localMirrordBinary = await getLocalMirrordBinary(); + const localMirrordBinary = await getLocalMirrordBinary(latestVersion); if (localMirrordBinary) { return localMirrordBinary; } await downloadMirrordBinary(getExtensionMirrordPath(), latestVersion); - return getExtensionMirrordPath().fsPath; + return extensionPath; } /** diff --git a/src/extension.ts b/src/extension.ts index 684aca87..4a0180b3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import { ConfigurationProvider } from './debugger'; import { MirrordStatus } from './status'; +import { getMirrordBinary } from './binaryManager'; export let globalContext: vscode.ExtensionContext; @@ -12,6 +13,10 @@ export async function activate(context: vscode.ExtensionContext) { context.workspaceState.update('enabled', false); vscode.debug.registerDebugConfigurationProvider('*', new ConfigurationProvider(), 2); + + // start mirrord binary updates + await getMirrordBinary(); + new MirrordStatus(vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0)) .register() .draw(); From 12b1a7f35c061deb7ebc1df625b58b614c276e38 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sun, 29 Oct 2023 12:04:33 -0400 Subject: [PATCH 11/24] .. --- src/binaryManager.ts | 31 +++++++++++++++++++++++++------ src/extension.ts | 7 +++---- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index dca5e05e..dc50028a 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -21,6 +21,8 @@ function getExtensionMirrordPath(): Uri { /** * Tries to find local mirrord in path or in extension storage. + * @param version If specified, then the version of the binary is checked and matched path is returned if it matches. + * @returns Path to mirrord binary or null if not found */ export async function getLocalMirrordBinary(version?: string): Promise { try { @@ -105,9 +107,12 @@ async function getConfiguredMirrordBinary(): Promise { * - if a version is specified, that version is downloaded * - if auto-update is enabled, then latest supported version is downloaded * - if auto-update is disabled, any local mirrord binary is used + * + * @param extensionActivate If true, then a global state is set so that any changes to the workspace settings pertaining + * to mirrord binary auto-update will prompt the user to reload the window. * @returns Path to mirrord binary */ -export async function getMirrordBinary(): Promise { +export async function getMirrordBinary(extensionActivate?: boolean): Promise { const configured = await getConfiguredMirrordBinary(); if (configured) { @@ -115,13 +120,27 @@ export async function getMirrordBinary(): Promise { return configured; } const latestVersion = await getLatestSupportedVersion(10000); - const autoUpdateConfigured = vscode.workspace.getConfiguration().get("mirrord.autoUpdate"); - const extensionPath = getExtensionMirrordPath().fsPath; + // if extension is activating, then set a global state to what was read in the workspace settings + if (extensionActivate) { + globalContext.workspaceState.update('autoUpdate', autoUpdateConfigured); + } else { + // extension is active, check if auto-update setting has changed + const autoUpdate = globalContext.workspaceState.get('autoUpdate'); + if (autoUpdate !== autoUpdateConfigured) { + await new NotificationBuilder() + .withMessage("mirrord binary auto-update setting has changed, please reload the window for the change to take effect.") + .withGenericAction("Reload", async () => { + await vscode.commands.executeCommand("workbench.action.reloadWindow"); + }) + .warning(); + } + return extensionPath; + } - if (typeof autoUpdateConfigured === 'string') { + if (typeof autoUpdateConfigured === 'string') { if (semver.valid(autoUpdateConfigured)) { const localMirrordBinary = await getLocalMirrordBinary(autoUpdateConfigured); if (localMirrordBinary) { @@ -134,12 +153,12 @@ export async function getMirrordBinary(): Promise { } } - if (typeof autoUpdateConfigured === 'boolean') { + if (typeof autoUpdateConfigured === 'boolean') { if (!autoUpdateConfigured) { const localMirrordBinary = await getLocalMirrordBinary(); if (localMirrordBinary) { return localMirrordBinary; - } + } return extensionPath; } } diff --git a/src/extension.ts b/src/extension.ts index 4a0180b3..4a97d3b3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -12,10 +12,9 @@ export async function activate(context: vscode.ExtensionContext) { context.workspaceState.update('enabled', false); vscode.debug.registerDebugConfigurationProvider('*', new ConfigurationProvider(), 2); - - - // start mirrord binary updates - await getMirrordBinary(); + + // start mirrord binary updates, so that we avoid downloading mid session + await getMirrordBinary(true); new MirrordStatus(vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0)) .register() From cd959da0c48d62ffef0492f8c3812a0b7b38c087 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sun, 29 Oct 2023 13:31:45 -0400 Subject: [PATCH 12/24] .. --- src/binaryManager.ts | 9 ++++++++- test-workspace/.vscode/settings.json | 7 ------- 2 files changed, 8 insertions(+), 8 deletions(-) delete mode 100644 test-workspace/.vscode/settings.json diff --git a/src/binaryManager.ts b/src/binaryManager.ts index dc50028a..5ad56c01 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -122,6 +122,13 @@ export async function getMirrordBinary(extensionActivate?: boolean): Promise Date: Sun, 29 Oct 2023 14:00:20 -0400 Subject: [PATCH 13/24] bugfixes --- src/binaryManager.ts | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index 5ad56c01..d6e9f741 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -119,12 +119,17 @@ export async function getMirrordBinary(extensionActivate?: boolean): Promise Date: Sun, 29 Oct 2023 14:16:07 -0400 Subject: [PATCH 14/24] CR --- src/binaryManager.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index d6e9f741..af0f03a7 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -120,12 +120,17 @@ export async function getMirrordBinary(extensionActivate?: boolean): Promise { +async function getLatestSupportedVersion(): Promise { // commented out logic to avoid checking every X seconds // uncomment if hits performance or too annoying // let lastChecked = globalContext.globalState.get('binaryLastChecked', 0); From b1ad5961cfecc6710c5eb5721f3aac49df06295b Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Mon, 30 Oct 2023 09:59:41 -0400 Subject: [PATCH 15/24] . --- src/binaryManager.ts | 24 +++--------------------- src/extension.ts | 2 +- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index af0f03a7..e91e506b 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -82,7 +82,7 @@ async function getConfiguredMirrordBinary(): Promise { let latestVersion; try { - latestVersion = await getLatestSupportedVersion(1000); + latestVersion = await getLatestSupportedVersion(); } catch (err) { new NotificationBuilder() .withMessage(`failed to check latest supported version of mirrord binary, binary specified in settings may be outdated: ${err}`) @@ -112,7 +112,7 @@ async function getConfiguredMirrordBinary(): Promise { * to mirrord binary auto-update will prompt the user to reload the window. * @returns Path to mirrord binary */ -export async function getMirrordBinary(extensionActivate?: boolean): Promise { +export async function getMirrordBinary(): Promise { const configured = await getConfiguredMirrordBinary(); if (configured) { @@ -120,7 +120,7 @@ export async function getMirrordBinary(extensionActivate?: boolean): Promise { - await vscode.commands.executeCommand("workbench.action.reloadWindow"); - }) - .warning(); - return extensionPath; - } - } - if (typeof autoUpdateConfigured === 'string') { if (semver.valid(autoUpdateConfigured)) { const localMirrordBinary = await getLocalMirrordBinary(autoUpdateConfigured); diff --git a/src/extension.ts b/src/extension.ts index 4a97d3b3..3fc07442 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -14,7 +14,7 @@ export async function activate(context: vscode.ExtensionContext) { vscode.debug.registerDebugConfigurationProvider('*', new ConfigurationProvider(), 2); // start mirrord binary updates, so that we avoid downloading mid session - await getMirrordBinary(true); + await getMirrordBinary(); new MirrordStatus(vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0)) .register() From 5cb063a68f10b8ad4aa9d5f25afa7c898742122e Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sat, 18 Nov 2023 00:33:02 -0500 Subject: [PATCH 16/24] Background binary download with progress --- src/binaryManager.ts | 53 ++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index e91e506b..a58e9ad5 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -21,7 +21,7 @@ function getExtensionMirrordPath(): Uri { /** * Tries to find local mirrord in path or in extension storage. - * @param version If specified, then the version of the binary is checked and matched path is returned if it matches. + * @param version If specified, then the version of the binary is checked and matched path is returned. * @returns Path to mirrord binary or null if not found */ export async function getLocalMirrordBinary(version?: string): Promise { @@ -47,7 +47,7 @@ export async function getLocalMirrordBinary(version?: string): Promise { if (localMirrordBinary) { return localMirrordBinary; } + // donot block and download binary, instead download in background await downloadMirrordBinary(getExtensionMirrordPath(), autoUpdateConfigured); return extensionPath; } else { @@ -218,25 +219,35 @@ function getMirrordDownloadUrl(version: string): string { * @param destPath Path to download the binary to */ async function downloadMirrordBinary(destPath: Uri, version: string): Promise { - fs.mkdirSync(Utils.dirname(destPath).fsPath, { recursive: true }); - const response: AxiosResponse = await window.withProgress({ - location: ProgressLocation.Notification, + await window.withProgress({ + location: ProgressLocation.Window, title: "mirrord", cancellable: false - }, (progress, _) => { - progress.report({ increment: 0, "message": "Downloading mirrord binary..." }); - const p = axios.get( - getMirrordDownloadUrl(version), - { - onDownloadProgress: function (progressEvent) { - progress.report({ increment: progressEvent.progress, "message": "Downloading mirrord binary..." }); - }, - responseType: 'arraybuffer', - }); - - return p; - } - ); - fs.writeFileSync(destPath.fsPath, response.data); - fs.chmodSync(destPath.fsPath, 0o755); + }, async (progress) => { + return new Promise(async (resolve, reject) => { + fs.mkdirSync(Utils.dirname(destPath).fsPath, { recursive: true }); + try { + const response: AxiosResponse = await axios.get( + getMirrordDownloadUrl(version), + { + onDownloadProgress: function (progressEvent) { + progress.report({ increment: progressEvent.progress, "message": "Downloading mirrord binary..." }); + }, + responseType: 'arraybuffer', + }); + + fs.writeFileSync(destPath.fsPath, response.data); + fs.chmodSync(destPath.fsPath, 0o755); + new NotificationBuilder() + .withMessage(`Downloaded mirrord binary version ${version}`) + .info(); + resolve(); + } catch (error) { + new NotificationBuilder() + .withMessage(`Error downloading mirrord binary: ${error}`) + .error(); + reject(error); + } + }); + }); } \ No newline at end of file From 3cef8335cc2ca5d6aa031ed4058ae461630de6d7 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sat, 18 Nov 2023 00:56:59 -0500 Subject: [PATCH 17/24] Tests --- src/tests/e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index 9ab6fc22..548dc7aa 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -112,7 +112,7 @@ describe("mirrord sample flow test", function () { const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); const panel = new BottomBarPanel(); await browser.driver.wait(async () => { - return await debugToolbar.isDisplayed(); + return await debugToolbar.isDisplayed() && await panel.isDisplayed(); }, 2 * defaultTimeout, "debug toolbar not found -- timed out"); From ea855990dc270fb45901d3570594373ec116b675 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sat, 18 Nov 2023 01:14:43 -0500 Subject: [PATCH 18/24] Tests --- src/tests/e2e.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index 548dc7aa..d24950e7 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -110,11 +110,14 @@ describe("mirrord sample flow test", function () { it("wait for process to write to terminal", async function () { const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); + console.log("waiting for debug toolbar1"); const panel = new BottomBarPanel(); + console.log("waiting for debug toolbar2"); await browser.driver.wait(async () => { return await debugToolbar.isDisplayed() && await panel.isDisplayed(); }, 2 * defaultTimeout, "debug toolbar not found -- timed out"); + console.log("debug toolbar found"); let terminal = await panel.openTerminalView(); From fffe4b4935be3c97374d4c520c7e43041eca5097 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sat, 18 Nov 2023 01:20:13 -0500 Subject: [PATCH 19/24] Tests --- src/tests/e2e.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index d24950e7..eac457c3 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -121,18 +121,25 @@ describe("mirrord sample flow test", function () { let terminal = await panel.openTerminalView(); + console.log("terminal opened"); + await browser.driver.wait(async () => { const text = await terminal.getText(); return await terminal.isDisplayed() && text.includes("Press CTRL+C to quit"); }, 2 * defaultTimeout, "terminal text not found -- timed out"); + console.log("terminal text found"); await sendTrafficToPod(); + console.log("traffic sent to pod"); + await browser.driver.wait(async () => { const text = await terminal.getText(); return text.includes("GET: Request completed"); }, defaultTimeout, "terminal text not found -- timed out"); + console.log("terminal text found - traffic sent to pod"); + }); }); From f4f60c658b6ace17050c5dc7a1a4266510ffb251 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sat, 18 Nov 2023 01:28:13 -0500 Subject: [PATCH 20/24] Tests --- src/tests/e2e.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index eac457c3..37cd523a 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -112,14 +112,14 @@ describe("mirrord sample flow test", function () { const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); console.log("waiting for debug toolbar1"); const panel = new BottomBarPanel(); + let terminal = await panel.openTerminalView(); console.log("waiting for debug toolbar2"); await browser.driver.wait(async () => { return await debugToolbar.isDisplayed() && await panel.isDisplayed(); }, 2 * defaultTimeout, "debug toolbar not found -- timed out"); console.log("debug toolbar found"); - - let terminal = await panel.openTerminalView(); + console.log("terminal opened"); From 9e20dfd2ef376591d81025d85d17bde8fc258045 Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sat, 18 Nov 2023 01:37:47 -0500 Subject: [PATCH 21/24] Tests --- src/tests/e2e.ts | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index 37cd523a..7af89f19 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -15,7 +15,7 @@ const podToSelect = process.env.POD_TO_SELECT; * - Send traffic to the pod * - Tests successfully exit if "GET: Request completed" is found in the terminal */ -describe("mirrord sample flow test", function () { +describe("mirrord sample flow test", function() { this.timeout("6 minutes"); // --> mocha tests timeout this.bail(true); // --> stop tests on first failure @@ -26,7 +26,7 @@ describe("mirrord sample flow test", function () { const fileName = "app_flask.py"; const defaultTimeout = 10000; // = 10 seconds - before(async function () { + before(async function() { console.log("podToSelect: " + podToSelect); console.log("kubeService: " + kubeService); @@ -48,7 +48,7 @@ describe("mirrord sample flow test", function () { await ew.openEditor('app_flask.py'); }); - it("enable mirrord button", async function () { + it("enable mirrord button", async function() { const statusBar = new StatusBar(); await browser.driver.wait(async () => { @@ -80,7 +80,7 @@ describe("mirrord sample flow test", function () { }, defaultTimeout, "mirrord `enable` button not found -- timed out"); }); - it("select pod from quickpick", async function () { + it("select pod from quickpick", async function() { await startDebugging(); const inputBox = await InputBox.create(defaultTimeout * 2); // assertion that podToSelect is not undefined is done in "before" block @@ -108,38 +108,28 @@ describe("mirrord sample flow test", function () { await inputBox.selectQuickPick(podToSelect!); }); - it("wait for process to write to terminal", async function () { + it("wait for process to write to terminal", async function() { const debugToolbar = await DebugToolbar.create(2 * defaultTimeout); - console.log("waiting for debug toolbar1"); const panel = new BottomBarPanel(); - let terminal = await panel.openTerminalView(); - console.log("waiting for debug toolbar2"); await browser.driver.wait(async () => { - return await debugToolbar.isDisplayed() && await panel.isDisplayed(); + return await debugToolbar.isDisplayed(); }, 2 * defaultTimeout, "debug toolbar not found -- timed out"); - console.log("debug toolbar found"); - - console.log("terminal opened"); + let terminal = await panel.openTerminalView(); await browser.driver.wait(async () => { const text = await terminal.getText(); return await terminal.isDisplayed() && text.includes("Press CTRL+C to quit"); }, 2 * defaultTimeout, "terminal text not found -- timed out"); - console.log("terminal text found"); await sendTrafficToPod(); - console.log("traffic sent to pod"); - await browser.driver.wait(async () => { const text = await terminal.getText(); return text.includes("GET: Request completed"); }, defaultTimeout, "terminal text not found -- timed out"); - console.log("terminal text found - traffic sent to pod"); - }); }); From 28f88d66b4aef6d7ef14e17960e99dfb3e3ad42f Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sat, 18 Nov 2023 01:53:16 -0500 Subject: [PATCH 22/24] ... --- src/tests/runTests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/runTests.ts b/src/tests/runTests.ts index ffe01e25..55de0a4c 100644 --- a/src/tests/runTests.ts +++ b/src/tests/runTests.ts @@ -6,7 +6,7 @@ import { ExTester, ReleaseQuality } from 'vscode-extension-tester'; // https://github.com/redhat-developer/vscode-extension-tester/issues/485#issuecomment-1648050797 is fixed async function main(): Promise { - const version = "latest"; + const version = "1.83.1"; const testPath = path.join(__dirname, 'e2e.js'); const storageFolder = path.join(__dirname, '..', 'storage'); const extFolder = path.join(__dirname, '..', 'extensions'); From 0c912315c389cdb79e6ffbfd2daab71eab40413d Mon Sep 17 00:00:00 2001 From: infiniteregrets Date: Sat, 18 Nov 2023 15:49:46 -0500 Subject: [PATCH 23/24] .. --- src/binaryManager.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/binaryManager.ts b/src/binaryManager.ts index a58e9ad5..d4483319 100644 --- a/src/binaryManager.ts +++ b/src/binaryManager.ts @@ -49,7 +49,8 @@ export async function getLocalMirrordBinary(version?: string): Promise Date: Sat, 18 Nov 2023 15:51:32 -0500 Subject: [PATCH 24/24] changelog --- changelog.d/+pin-vsc-e2e.internal.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/+pin-vsc-e2e.internal.md diff --git a/changelog.d/+pin-vsc-e2e.internal.md b/changelog.d/+pin-vsc-e2e.internal.md new file mode 100644 index 00000000..ab878b38 --- /dev/null +++ b/changelog.d/+pin-vsc-e2e.internal.md @@ -0,0 +1 @@ +Pin vscode version for e2e, as it fails on latest release