diff --git a/code/src/vs/workbench/services/workspaces/browser/che/devWorkspaceId.ts b/code/src/vs/workbench/services/workspaces/browser/che/devWorkspaceId.ts new file mode 100644 index 00000000000..530ec5c764d --- /dev/null +++ b/code/src/vs/workbench/services/workspaces/browser/che/devWorkspaceId.ts @@ -0,0 +1,24 @@ +/********************************************************************** + * Copyright (c) 2023 Red Hat, Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ***********************************************************************/ +/* eslint-disable header/header */ + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// NOTE: DO NOT CHANGE. Launcher updates this constant on workspace startup +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +const DEVWORKSPACE = "https://{{che-cluster}}.{{host}}/{{namespace}}/{{workspace-name}}/{{port}}/"; + +export function getDevWorkspaceId(): string | undefined { + // checking for "https://" guarantees we apply here the ID set by che-code launcher + if (DEVWORKSPACE && !DEVWORKSPACE.startsWith("https://")) { + return DEVWORKSPACE; + } + + return undefined; +} diff --git a/code/src/vs/workbench/services/workspaces/browser/workspaces.ts b/code/src/vs/workbench/services/workspaces/browser/workspaces.ts index 8bfc7e0e3f3..275c9bd5da3 100644 --- a/code/src/vs/workbench/services/workspaces/browser/workspaces.ts +++ b/code/src/vs/workbench/services/workspaces/browser/workspaces.ts @@ -6,6 +6,7 @@ import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace'; import { URI } from 'vs/base/common/uri'; import { hash } from 'vs/base/common/hash'; +import { getDevWorkspaceId } from 'vs/workbench/services/workspaces/browser/che/devWorkspaceId' // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // NOTE: DO NOT CHANGE. IDENTIFIERS HAVE TO REMAIN STABLE @@ -30,5 +31,5 @@ export function getSingleFolderWorkspaceIdentifier(folderUri: URI): ISingleFolde } function getWorkspaceId(uri: URI): string { - return hash(window.location.href + uri.toString()).toString(16); + return hash(getDevWorkspaceId() + uri.toString()).toString(16); } diff --git a/launcher/src/devworkspace-id.ts b/launcher/src/devworkspace-id.ts new file mode 100644 index 00000000000..c4162519b46 --- /dev/null +++ b/launcher/src/devworkspace-id.ts @@ -0,0 +1,45 @@ +/********************************************************************** + * Copyright (c) 2023 Red Hat, Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ***********************************************************************/ + +import { env } from "process"; +import { FILE_WORKBENCH_WEB_MAIN } from "./files"; +import * as fs from "./fs-extra"; + +const DEVWORKSPACE_ID_MASK = + "https://{{che-cluster}}.{{host}}/{{namespace}}/{{workspace-name}}/{{port}}/"; + +export class DevWorkspaceId { + async configure(): Promise { + console.log("# Setting curent DevWorkspace ID to che-code..."); + + if (!env.DEVWORKSPACE_ID) { + console.log(" > env.DEVWORKSPACE_ID is not set, skip this step"); + return; + } + + console.log(` > apply DevWorkspace ID [${env.DEVWORKSPACE_ID}]`); + + try { + await this.update( + FILE_WORKBENCH_WEB_MAIN, + DEVWORKSPACE_ID_MASK, + env.DEVWORKSPACE_ID + ); + } catch (err) { + console.error(`${err.message} Webviews will not work if CDN disabled.`); + } + } + + async update(file: string, text: string, newText: string): Promise { + const content = await fs.readFile(file); + const newContent = content.replace(text, newText); + await fs.writeFile(file, newContent); + } +} diff --git a/launcher/src/files.ts b/launcher/src/files.ts new file mode 100644 index 00000000000..09e880dcb7a --- /dev/null +++ b/launcher/src/files.ts @@ -0,0 +1,14 @@ +/********************************************************************** + * Copyright (c) 2023 Red Hat, Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ***********************************************************************/ + +export const FILE_WORKBENCH_WEB_MAIN = "out/vs/workbench/workbench.web.main.js"; + +export const FILE_EXTENSION_HOST_PROCESS = + "out/vs/workbench/api/node/extensionHostProcess.js"; diff --git a/launcher/src/fs-extra.ts b/launcher/src/fs-extra.ts index e1ebb9a102e..225f64e543e 100644 --- a/launcher/src/fs-extra.ts +++ b/launcher/src/fs-extra.ts @@ -13,7 +13,7 @@ * Why do we need to add the wrapper: * - it allows to get rid of using `fs-extra` package * - it allows to use common `node_modules` directory for launcher and VS Code - * - it simplifies writing tests and allows to easily mock of this module + * - it simplifies writing tests and allows to easily mock this module */ import * as fs from "fs"; diff --git a/launcher/src/main.ts b/launcher/src/main.ts index 85565d83163..bc6458dd7cd 100644 --- a/launcher/src/main.ts +++ b/launcher/src/main.ts @@ -9,6 +9,7 @@ ***********************************************************************/ import { CodeWorkspace } from "./code-workspace"; +import { DevWorkspaceId } from "./devworkspace-id"; import { NodeExtraCertificate } from "./node-extra-certificate"; import { OpenVSIXRegistry } from "./openvsix-registry"; import { VSCodeLauncher } from "./vscode-launcher"; @@ -22,6 +23,7 @@ import { WebviewResources } from "./webview-resources"; */ export class Main { async start(): Promise { + await new DevWorkspaceId().configure(); await new OpenVSIXRegistry().configure(); await new WebviewResources().configure(); await new NodeExtraCertificate().configure(); diff --git a/launcher/src/openvsix-registry.ts b/launcher/src/openvsix-registry.ts index b805525e39b..4ae3e7cb5cc 100644 --- a/launcher/src/openvsix-registry.ts +++ b/launcher/src/openvsix-registry.ts @@ -9,6 +9,7 @@ ***********************************************************************/ import { env } from "process"; +import { FILE_WORKBENCH_WEB_MAIN } from "./files"; import * as fs from "./fs-extra"; import { ProductJSON } from "./product-json"; @@ -74,7 +75,7 @@ export class OpenVSIXRegistry { await productJSON.save(); await this.update( - "out/vs/workbench/workbench.web.main.js", + FILE_WORKBENCH_WEB_MAIN, serviceURL, newServiceURL, itemURL, diff --git a/launcher/src/vscode-launcher.ts b/launcher/src/vscode-launcher.ts index c5402d769ed..f2c6d786495 100644 --- a/launcher/src/vscode-launcher.ts +++ b/launcher/src/vscode-launcher.ts @@ -16,8 +16,6 @@ import * as child_process from "child_process"; import { NODE_EXTRA_CERTIFICATE } from "./node-extra-certificate"; import { workspaceFilePath } from "./code-workspace"; -export const DEFAULT_PROJECTS_DIRECTORY = "/projects"; - export class VSCodeLauncher { async launch(): Promise { console.log("# Launching VS Code..."); diff --git a/launcher/src/webview-resources.ts b/launcher/src/webview-resources.ts index 511538f5382..f42480f30b6 100644 --- a/launcher/src/webview-resources.ts +++ b/launcher/src/webview-resources.ts @@ -13,9 +13,7 @@ import * as fs from "./fs-extra"; import { FlattenedDevfile } from "./flattened-devfile"; import { ProductJSON } from "./product-json"; -const FILE_WORKBENCH_WEB_MAIN = "out/vs/workbench/workbench.web.main.js"; -const FILE_EXTENSION_HOST_PROCESS = - "out/vs/workbench/api/node/extensionHostProcess.js"; +import { FILE_EXTENSION_HOST_PROCESS, FILE_WORKBENCH_WEB_MAIN } from "./files"; export class WebviewResources { /***************************************************************************************************************** diff --git a/launcher/tests/devworkspace-id.spec.ts b/launcher/tests/devworkspace-id.spec.ts new file mode 100644 index 00000000000..5ba06e68803 --- /dev/null +++ b/launcher/tests/devworkspace-id.spec.ts @@ -0,0 +1,63 @@ +/********************************************************************** + * Copyright (c) 2023 Red Hat, Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ***********************************************************************/ + +import * as fs from "../src/fs-extra"; +import { env } from "process"; + +import { DevWorkspaceId } from "../src/devworkspace-id"; + +const ORIGIN_WORKBENCH_WEB_MAIN = ` +some code, some code, a mask to be replaced https://{{che-cluster}}.{{host}}/{{namespace}}/{{workspace-name}}/{{port}}/, some code +`; + +const NEW_WORKBENCH_WEB_MAIN = ` +some code, some code, a mask to be replaced test-workspace-1234567890, some code +`; + +describe("Test setting DevWorkspace ID to VS Code", () => { + beforeEach(() => { + delete env.DEVWORKSPACE_ID; + }); + + test("should return if env.DEVWORKSPACE_ID is not set", async () => { + const readFileMock = jest.fn(); + Object.assign(fs, { + readFile: readFileMock, + }); + + const devWorkspaceId = new DevWorkspaceId(); + await devWorkspaceId.configure(); + + expect(readFileMock).toBeCalledTimes(0); + }); + + test("should apply env.DEVWORKSPACE_ID", async () => { + env.DEVWORKSPACE_ID = "test-workspace-1234567890"; + + const readFileMock = jest.fn(); + const writeFileMock = jest.fn(); + + Object.assign(fs, { + readFile: readFileMock, + writeFile: writeFileMock, + }); + + readFileMock.mockImplementation(() => ORIGIN_WORKBENCH_WEB_MAIN); + + const devWorkspaceId = new DevWorkspaceId(); + await devWorkspaceId.configure(); + + expect(readFileMock).toBeCalledTimes(1); + expect(writeFileMock).toBeCalledWith( + "out/vs/workbench/workbench.web.main.js", + NEW_WORKBENCH_WEB_MAIN + ); + }); +}); diff --git a/launcher/tests/main.spec.ts b/launcher/tests/main.spec.ts index 8855304805f..edd61e6c696 100644 --- a/launcher/tests/main.spec.ts +++ b/launcher/tests/main.spec.ts @@ -10,6 +10,13 @@ import { Main } from "../src/main"; +const setDevWorkspaceIdMock = jest.fn(); +jest.mock("../src/devworkspace-id", () => ({ + DevWorkspaceId: function () { + return { configure: setDevWorkspaceIdMock }; + }, +})); + const configureOpenVSIXRegistryMock = jest.fn(); jest.mock("../src/openvsix-registry", () => ({ OpenVSIXRegistry: function () { @@ -49,6 +56,7 @@ describe("Test main flow:", () => { test("should configure all the stuff", async () => { await new Main().start(); + expect(setDevWorkspaceIdMock).toBeCalled(); expect(configureOpenVSIXRegistryMock).toBeCalled(); expect(configureWebviewResourcesMock).toBeCalled(); expect(configureNodeExtraCertificate).toBeCalled();