From efd03db168ba39dac509365899de53a282bdef7f Mon Sep 17 00:00:00 2001 From: "jan-david.wiederstein" Date: Mon, 17 Jun 2024 19:18:40 +0200 Subject: [PATCH 1/2] added ci-pipeline panel --- media/codesphere-logo.svg | 4 + package.json | 17 ++ src/CiPipelineProvider.ts | 138 ++++++++++ src/SidebarProvider.ts | 15 +- src/extension.ts | 12 +- src/ts/wsService.ts | 30 ++ webviews/components/CiPipeline.svelte | 376 ++++++++++++++++++++++++++ webviews/components/Codesphere.svelte | 24 +- webviews/pages/cipipeline.ts | 7 + 9 files changed, 607 insertions(+), 16 deletions(-) create mode 100644 media/codesphere-logo.svg create mode 100644 src/CiPipelineProvider.ts create mode 100644 webviews/components/CiPipeline.svelte create mode 100644 webviews/pages/cipipeline.ts diff --git a/media/codesphere-logo.svg b/media/codesphere-logo.svg new file mode 100644 index 0000000..8252a4c --- /dev/null +++ b/media/codesphere-logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/package.json b/package.json index 4c94acd..a76ec69 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,14 @@ "title": "Codesphere", "icon": "media/codesphere.svg" } + ], + "panel": [ + { + "id": "ci-pipeline", + "title": "Ci-Pipeline", + "icon": "media/codesphere.svg", + "order": 10 + } ] }, "views": { @@ -52,6 +60,15 @@ "icon": "media/Codesphere.svg", "contextualTitle": "Codesphere" } + ], + "ci-pipeline": [ + { + "type": "webview", + "id": "ci-pipeline", + "name": "Ci-Pipeline", + "contextualTitle": "Ci Pipeline", + "when": "codesphere.isLoggedIn && codesphere.workspaceOverview" + } ] }, "menus": { diff --git a/src/CiPipelineProvider.ts b/src/CiPipelineProvider.ts new file mode 100644 index 0000000..4ed8ed9 --- /dev/null +++ b/src/CiPipelineProvider.ts @@ -0,0 +1,138 @@ +import * as vscode from "vscode"; +import { getNonce } from "./ts/getNonce"; +import * as wsLib from 'ws'; +const { setupWs, + request, + getUaSocket, + checkCiPipelineStructure + } = require('./ts/wsService'); + +export class CiPipelineProvider implements vscode.WebviewViewProvider { + _view?: vscode.WebviewView; + _doc?: vscode.TextDocument; + + constructor(private readonly _extensionUri: vscode.Uri, public extensionContext: vscode.ExtensionContext) {} + + + + public resolveWebviewView(webviewView: vscode.WebviewView) { + this._view = webviewView; + let cache = this.extensionContext.globalState; + + webviewView.webview.options = { + // Allow scripts in the webview + enableScripts: true, + + localResourceRoots: [this._extensionUri], + }; + + webviewView.webview.html = this._getHtmlWebview(webviewView.webview); + + webviewView.webview.onDidReceiveMessage(async (data) => { + let socket: any; + let uaSocket = getUaSocket(); + + switch (data.type) { + case "getCiPipelineStages": { + const socketURL = `wss://${data.value.dataCenterId}.codesphere.com/workspace-proxy`; + console.log(socketURL + `socketURL`); + const accessToken = await this.extensionContext.secrets.get("codesphere.accessToken") as string; + const workspaceID: number = parseInt(data.value.workspaceId); + socket = await setupWs(new wsLib.WebSocket(socketURL), "workspace-proxy", accessToken, cache, workspaceID); + + uaSocket = getUaSocket(); + let ciStructure: any; + const ciPipelineCheck = checkCiPipelineStructure(uaSocket, 324); + ciPipelineCheck.then((ci: any) => { + ciStructure = ci; + console.log('ciStructure: ' + JSON.stringify(ciStructure)); + this._view?.webview.postMessage({ + type: "CIPipelineStages", + value: { + 'CIArray': `${JSON.stringify(ciStructure)}` + } + }); + } + ); + + await request(uaSocket, "pipelineStream", { workspaceId: workspaceID}, "workspace-proxy", 324); + + break; + } + + case "currentWorkspace": { + const workspace: any = await cache.get("codesphere.workspaceOverview"); + + const workspaceId = workspace.id; + const teamId = workspace.teamId; + const dataCenterId = workspace.dataCenterId; + + this._view?.webview.postMessage({ + type: "currentWorkspace", + value: { + 'currentWorkspace': `${workspaceId}`, + 'teamId': `${teamId}`, + 'dcId': `${dataCenterId}` + } + }); + + break; + } + } + }); + } + + + public updateWebviewContent() { + if (this._view) { + this._view.webview.html = this._getHtmlWebview(this._view.webview); + } + } + + public revive(panel: vscode.WebviewView) { + this._view = panel; + } + + + private _getHtmlWebview(webview: vscode.Webview) { + const styleResetUri = webview.asWebviewUri( + vscode.Uri.joinPath(this._extensionUri, "media", "reset.css") + ); + const scriptUri = webview.asWebviewUri( + vscode.Uri.joinPath(this._extensionUri, "out", "compiled/cipipeline.js") + ); + const styleMainUri = webview.asWebviewUri( + vscode.Uri.joinPath(this._extensionUri, "out", "compiled/cipipeline.css") + ); + const styleVSCodeUri = webview.asWebviewUri( + vscode.Uri.joinPath(this._extensionUri, "media", "vscode.css") + ); + + // Use a nonce to only allow a specific script to be run. + const nonce = getNonce(); + + return ` + + + + + + + + + + + + + + + `; + } +} \ No newline at end of file diff --git a/src/SidebarProvider.ts b/src/SidebarProvider.ts index 672d39d..e35cb29 100644 --- a/src/SidebarProvider.ts +++ b/src/SidebarProvider.ts @@ -68,6 +68,8 @@ export class SidebarProvider implements vscode.WebviewViewProvider { vscode.commands.executeCommand('setContext', 'codesphere.isLoggedIn', true); cache.update("codesphere.isLoggedIn", true); webviewView.webview.html = this._getHtmlWebviewOverview(webviewView.webview); + cache.update('codesphere.workspaceOverview', cache.get('codesphere.currentWorkspace')); + vscode.commands.executeCommand('setContext', 'codesphere.workspaceOverview', cache.get('codesphere.currentWorkspace')); console.log('Congratulations, your extension "codesphere" is now active! You are logged in.'); let currentWorkspace = parseInt(cache.get('codesphere.currentWorkspace') as string); @@ -128,6 +130,10 @@ export class SidebarProvider implements vscode.WebviewViewProvider { cache.update("codesphere.activeTunnel", {}); } + if (!cache.get("codesphere.workspaceOverview")) { + cache.update("codesphere.workspaceOverview", ''); + } + cache.setKeysForSync(["codesphere.isLoggedIn", "codesphere.accessTokenCache", "codesphere.teams", @@ -135,7 +141,8 @@ export class SidebarProvider implements vscode.WebviewViewProvider { "codesphere.userData", "codesphere.lastCode", "codesphere.activeTunnel", - "codesphere.currentWorkspace"]); + "codesphere.currentWorkspace", + "codesphere.workspaceOverview"]); webviewView.webview.onDidReceiveMessage(async (data) => { let socket: any; @@ -670,6 +677,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { return; } webviewView.webview.html = this._getHtmlWebviewOverview(webviewView.webview); + vscode.commands.executeCommand('setContext', 'codesphere.workspaceOverview', data.value.workspaceId); const workspacesInTeam: any = cache.get("codesphere.workspaces"); const teamId = data.value.teamId; @@ -679,6 +687,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { ); cache.update("codesphere.currentconnectedWorkspace", selectedWorkspace); + cache.update("codesphere.workspaceOverview", selectedWorkspace); if (selectedWorkspace === cache.get("codesphere.currentWorkspace")) { vscode.commands.executeCommand('codesphere.openOverView', selectedWorkspace); @@ -694,6 +703,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider { } else { console.error("Workspace not found with ID:", data.value.workspaceId); } + break; } @@ -717,8 +727,11 @@ export class SidebarProvider implements vscode.WebviewViewProvider { if (!data.value) { return; } + // todo: check wether it is mandatory to erease the currentWorkspace context. I dont think so but at the moment i dont want to destroy anything webviewView.webview.html = this._getHtmlForWebviewAfterSignIn(webviewView.webview); vscode.commands.executeCommand('setContext', 'codesphere.currentWorkspace', ""); + vscode.commands.executeCommand('setContext', 'codesphere.workspaceOverview', ''); + cache.update('codesphere.workspaceOverview', ''); vscode.commands.executeCommand('codesphere.backToMenu'); break; } diff --git a/src/extension.ts b/src/extension.ts index 046b0a5..20ce3fa 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import { SidebarProvider } from './SidebarProvider'; import { FileTreeProvider } from './FileTreeProvider'; +import { CiPipelineProvider } from './CiPipelineProvider'; import { NoCurrentWorkspaceProvider } from './NoCurrentWorkspaceProvider'; import { reloadCache } from './ts/reloadCache'; import { exec } from 'child_process'; @@ -16,14 +17,12 @@ function getWorkspaceRootPath(): string { } export function activate(context: vscode.ExtensionContext) { - - vscode.ExtensionKind.UI; - const sidebarProvider = new SidebarProvider(context.extensionUri, context); const noCurrentWorkspaceProvider = new NoCurrentWorkspaceProvider(context.extensionUri); const rootPath: string = getWorkspaceRootPath(); const fileTreeProvider = new FileTreeProvider(rootPath); console.log('roothPath is: ', rootPath); + const ciPipelineProvider = new CiPipelineProvider(context.extensionUri, context); const remoteName = vscode.env.remoteName; console.log('remote name ' + remoteName); @@ -62,6 +61,13 @@ export function activate(context: vscode.ExtensionContext) { ) ); + context.subscriptions.push( + vscode.window.registerWebviewViewProvider( + 'ci-pipeline', + ciPipelineProvider + ) + ); + const userData: any = context.globalState.get("codesphere.userData"); const gitEmail: string = userData.email || ""; let gitFirstName: string = userData.firstName || ""; diff --git a/src/ts/wsService.ts b/src/ts/wsService.ts index b5a5dbd..d1cf7b4 100644 --- a/src/ts/wsService.ts +++ b/src/ts/wsService.ts @@ -513,6 +513,35 @@ const isVSIX = async (deploymentSocket: any) => { }); }; +const checkCiPipelineStructure = async (deploymentSocket: any, endpointId: number) => { + return new Promise((resolve, reject) => { + const messageHandler = (msg: any) => { + try { + let msgTest = msg.toString(); + let parsedMsg = JSON.parse(msgTest); + + if (msgTest.includes(`"endpointId":${endpointId}`)) { + console.log(`ci-Structure` + msgTest) + deploymentSocket.off("message", messageHandler); + deploymentSocket.off("error", errorHandler); + resolve(parsedMsg.reply); + } + } catch (error) { + console.error("Error parsing message:", error); + reject(error); + } + }; + + const errorHandler = (err: any) => { + console.log("Socket exited with error:" + err); + reject(err); + }; + + deploymentSocket.on("message", messageHandler); + deploymentSocket.on("error", errorHandler); + }); +}; + @@ -535,6 +564,7 @@ module.exports = { getRemoteURL, getGitHubToken, isVSIX, + checkCiPipelineStructure, getUaSocket: () => uaSocket, getDsSocket: () => dsSocket }; \ No newline at end of file diff --git a/webviews/components/CiPipeline.svelte b/webviews/components/CiPipeline.svelte new file mode 100644 index 0000000..c2a7723 --- /dev/null +++ b/webviews/components/CiPipeline.svelte @@ -0,0 +1,376 @@ + + + + +
+ + + + + + +

CI Pipeline

+
+ +
+
+

+ Stages +

+
+
+ + + + + +
Prepare
+
+ +
+
+
+ + + + + + +
Test
+
+ +
+
+
+ + + +
Run
+
+ +
+
+ +
+
+

{selectedStage}

+ + {#if selectedStage == "run"} + Note: This stage restarts if any step fails. + {/if} +
+
+ {#if showPrepare} + {#each prepareStageSteps as step} +
toggleAccordion(step.name)} role="presentation"> + +
+ + {#if step.open} + + + + {:else} + + + + {/if} + {#if step.name == undefined} + {step.command} + {:else} + {step.name} + {/if} +
+
+
+ {step.command} +
+
+
+ {/each} + {/if} + + {#if showTest == true} +
+ {/if} + + {#if showRun == true} +
+ {/if} +
+
+
\ No newline at end of file diff --git a/webviews/components/Codesphere.svelte b/webviews/components/Codesphere.svelte index 21a2512..e3c919f 100644 --- a/webviews/components/Codesphere.svelte +++ b/webviews/components/Codesphere.svelte @@ -270,18 +270,18 @@
toggleAccordion(team.id)} role="presentation">
- - {#if team.open} - - - - {:else} - - - - {/if} - {team.name} -
+ + {#if team.open} + + + + {:else} + + + + {/if} + {team.name} +
{#if team.avatarUrl} Team Avatar diff --git a/webviews/pages/cipipeline.ts b/webviews/pages/cipipeline.ts new file mode 100644 index 0000000..84a2800 --- /dev/null +++ b/webviews/pages/cipipeline.ts @@ -0,0 +1,7 @@ +import App from "../components/CiPipeline.svelte"; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file From 16fcbaf730d1a6d3a73993c51469916e66a90c37 Mon Sep 17 00:00:00 2001 From: "jan-david.wiederstein" Date: Tue, 18 Jun 2024 12:08:05 +0200 Subject: [PATCH 2/2] testing --- package.json | 14 +++++++++++++- src/extension.ts | 19 ++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a76ec69..65fda1e 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,21 @@ "Other" ], "pricing": "Free", + "enabledApiProposals": [ + "resolvers", + "terminalDataWriteEvent", + "contribViewsRemote" + ], "activationEvents": [ + "onResolveAuthority:codesphere", + "onView:remoteHosts", "*" ], + "capabilities": { + "untrustedWorkspaces": { + "supported": true + } + }, "main": "./dist/extension.js", "contributes": { "viewsContainers": { @@ -116,7 +128,7 @@ "title": "Back to menu" } ], - "extensionKind": ["workspace"] + "extensionKind": ["ui"] }, "extensionPack": [ "ms-vscode-remote.vscode-remote-extensionpack" diff --git a/src/extension.ts b/src/extension.ts index 20ce3fa..6d732da 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -17,6 +17,19 @@ function getWorkspaceRootPath(): string { } export function activate(context: vscode.ExtensionContext) { + //testing + + const config = vscode.workspace.getConfiguration('remote.tunnels'); + + // Beispielhafte Einstellungen abrufen und anzeigen + const portMappings = config.get('portMappings'); + const auth = config.get('auth'); + const connectionTimeout = config.get('connectionTimeout'); + + console.log('portMappings: ', portMappings); + console.log('auth: ', auth); + console.log('connectionTimeout: ', connectionTimeout); + const sidebarProvider = new SidebarProvider(context.extensionUri, context); const noCurrentWorkspaceProvider = new NoCurrentWorkspaceProvider(context.extensionUri); const rootPath: string = getWorkspaceRootPath(); @@ -36,8 +49,6 @@ export function activate(context: vscode.ExtensionContext) { const machineId = vscode.env.machineId; console.log('machine id ' + machineId); - const config = vscode.workspace.getConfiguration('remote.tunnels'); - console.log('config ' + JSON.stringify(config)); context.subscriptions.push( @@ -225,4 +236,6 @@ export function activate(context: vscode.ExtensionContext) { // This method is called when your extension is deactivated -export function deactivate() {} \ No newline at end of file +export function deactivate() { + +} \ No newline at end of file