From 5efc4d01598e21fb134c30af50faba484ad430f8 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Wed, 18 Aug 2021 10:01:37 +0000 Subject: [PATCH] gitpod-desktop --- build/gulpfile.extensions.js | 2 +- build/gulpfile.gitpod.js | 2 +- build/lib/extensions.js | 2 +- build/lib/extensions.ts | 2 +- build/npm/dirs.js | 2 +- .../.vscodeignore | 0 extensions/gitpod-desktop/README.md | 5 + .../extension.webpack.config.js | 0 .../package.json | 23 +- extensions/gitpod-desktop/package.nls.json | 4 + extensions/gitpod-desktop/src/extension.ts | 403 ++++++++++++++++++ .../tsconfig.json | 0 extensions/gitpod-desktop/yarn.lock | 198 +++++++++ extensions/gitpod-remote-ssh/package.json | 2 +- extensions/gitpod-remote-ssh/src/extension.ts | 4 +- extensions/gitpod-ui/README.md | 5 - extensions/gitpod-ui/package.nls.json | 4 - extensions/gitpod-ui/src/extension.ts | 34 -- extensions/gitpod-ui/yarn.lock | 51 --- extensions/gitpod-web/package.json | 8 + extensions/gitpod/extension.webpack.config.js | 5 - extensions/gitpod/package.json | 113 +++-- extensions/gitpod/package.nls.json | 5 +- extensions/gitpod/src/extension.ts | 6 +- extensions/gitpod/src/features.ts | 27 ++ extensions/gitpod/yarn.lock | 10 - src/vs/gitpod/node/server.ts | 2 +- 27 files changed, 755 insertions(+), 164 deletions(-) rename extensions/{gitpod-ui => gitpod-desktop}/.vscodeignore (100%) create mode 100644 extensions/gitpod-desktop/README.md rename extensions/{gitpod-ui => gitpod-desktop}/extension.webpack.config.js (100%) rename extensions/{gitpod-ui => gitpod-desktop}/package.json (55%) create mode 100644 extensions/gitpod-desktop/package.nls.json create mode 100644 extensions/gitpod-desktop/src/extension.ts rename extensions/{gitpod-ui => gitpod-desktop}/tsconfig.json (100%) create mode 100644 extensions/gitpod-desktop/yarn.lock delete mode 100644 extensions/gitpod-ui/README.md delete mode 100644 extensions/gitpod-ui/package.nls.json delete mode 100644 extensions/gitpod-ui/src/extension.ts delete mode 100644 extensions/gitpod-ui/yarn.lock diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index 1ea1e1586ef3e..5902cb140ce6d 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -68,7 +68,7 @@ const compilations = [ 'gitpod/tsconfig.json', 'gitpod-remote-ssh/tsconfig.json', 'gitpod-web/tsconfig.json', - 'gitpod-ui/tsconfig.json', + 'gitpod-desktop/tsconfig.json', ]; const getBaseUrl = out => `https://ticino.blob.core.windows.net/sourcemaps/${commit}/${out}`; diff --git a/build/gulpfile.gitpod.js b/build/gulpfile.gitpod.js index 663fb3b0f627d..c8c5fb01fcd97 100644 --- a/build/gulpfile.gitpod.js +++ b/build/gulpfile.gitpod.js @@ -27,7 +27,7 @@ const rename = require('gulp-rename'); const ext = require('./lib/extensions'); const extensionsPath = path.join(path.dirname(__dirname), 'extensions'); -const marketplaceExtensions = ['gitpod', 'gitpod-ui', 'gitpod-remote-ssh']; +const marketplaceExtensions = ['gitpod', 'gitpod-desktop', 'gitpod-remote-ssh']; const outMarketplaceExtensions = 'out-gitpod-marketplace'; const cleanMarketplaceExtensions = task.define('clean-gitpod-marketplace-extensions', util.rimraf(outMarketplaceExtensions)); const bumpMarketplaceExtensions = task.define('bump-marketplace-extensions', () => { diff --git a/build/lib/extensions.js b/build/lib/extensions.js index fa8c1a71916ac..b6ffcad4b4cba 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -207,7 +207,7 @@ const excludedExtensions = [ 'vscode-custom-editor-tests', 'github-authentication', 'gitpod-remote-ssh', - 'gitpod-ui', + 'gitpod-desktop', ]; const marketplaceWebExtensionsExclude = new Set([ 'ms-vscode.node-debug', diff --git a/build/lib/extensions.ts b/build/lib/extensions.ts index 5abfa421b8b87..5ec5f39a0a228 100644 --- a/build/lib/extensions.ts +++ b/build/lib/extensions.ts @@ -242,7 +242,7 @@ const excludedExtensions = [ 'vscode-custom-editor-tests', 'github-authentication', 'gitpod-remote-ssh', - 'gitpod-ui', + 'gitpod-desktop', ]; const marketplaceWebExtensionsExclude = new Set([ diff --git a/build/npm/dirs.js b/build/npm/dirs.js index c31cc4a229616..ffb575d9cecd0 100644 --- a/build/npm/dirs.js +++ b/build/npm/dirs.js @@ -45,7 +45,7 @@ exports.dirs = [ 'extensions/gitpod', 'extensions/gitpod-remote-ssh', 'extensions/gitpod-web', - 'extensions/gitpod-ui', + 'extensions/gitpod-desktop', 'remote', 'remote/web', 'test/automation', diff --git a/extensions/gitpod-ui/.vscodeignore b/extensions/gitpod-desktop/.vscodeignore similarity index 100% rename from extensions/gitpod-ui/.vscodeignore rename to extensions/gitpod-desktop/.vscodeignore diff --git a/extensions/gitpod-desktop/README.md b/extensions/gitpod-desktop/README.md new file mode 100644 index 0000000000000..9d85ad0e0aeba --- /dev/null +++ b/extensions/gitpod-desktop/README.md @@ -0,0 +1,5 @@ +# Gitpod Desktop integration + +## Features + +This extension provides support for Gitpod Desktop integration. diff --git a/extensions/gitpod-ui/extension.webpack.config.js b/extensions/gitpod-desktop/extension.webpack.config.js similarity index 100% rename from extensions/gitpod-ui/extension.webpack.config.js rename to extensions/gitpod-desktop/extension.webpack.config.js diff --git a/extensions/gitpod-ui/package.json b/extensions/gitpod-desktop/package.json similarity index 55% rename from extensions/gitpod-ui/package.json rename to extensions/gitpod-desktop/package.json index 132061ac2286a..8b8885f662303 100644 --- a/extensions/gitpod-ui/package.json +++ b/extensions/gitpod-desktop/package.json @@ -1,9 +1,9 @@ { - "name": "gitpod-ui", + "name": "gitpod-desktop", "displayName": "%displayName%", "description": "%description%", "publisher": "gitpod", - "version": "0.0.11", + "version": "0.0.14", "license": "MIT", "preview": true, "repository": { @@ -21,20 +21,27 @@ ], "activationEvents": [ "*", - "onCommand:gitpod-ui.api.autoTunnel" + "onCommand:gitpod-desktop.api.autoTunnel" ], "main": "./out/extension.js", "scripts": { - "compile": "gulp compile-extension:gitpod-ui", - "watch": "gulp watch-extension:gitpod-ui", + "compile": "gulp compile-extension:gitpod-desktop", + "watch": "gulp watch-extension:gitpod-desktop", "vscode:prepublish": "npm run compile" }, "devDependencies": { - "@types/node": "^10.12.21" + "@types/node": "^10.12.21", + "@types/node-fetch": "^2.5.12", + "@types/tmp": "^0.2.1" }, "dependencies": { - "@gitpod/local-app-api-grpcweb": "ak-remote-ssh", + "@gitpod/local-app-api-grpcweb": "ak-vscode-desktop", "@improbable-eng/grpc-web-node-http-transport": "^0.14.0", + "node-fetch": "^2.6.1", + "tmp": "^0.2.1", "vscode-nls": "^5.0.0" - } + }, + "extensionDependencies": [ + "ms-vscode-remote.remote-ssh" + ] } diff --git a/extensions/gitpod-desktop/package.nls.json b/extensions/gitpod-desktop/package.nls.json new file mode 100644 index 0000000000000..87b44eb194759 --- /dev/null +++ b/extensions/gitpod-desktop/package.nls.json @@ -0,0 +1,4 @@ +{ + "displayName": "Gitpod Desktop", + "description": "Gitpod Desktop Support" +} diff --git a/extensions/gitpod-desktop/src/extension.ts b/extensions/gitpod-desktop/src/extension.ts new file mode 100644 index 0000000000000..89caa67286c29 --- /dev/null +++ b/extensions/gitpod-desktop/src/extension.ts @@ -0,0 +1,403 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Gitpod. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +/// + +import { AutoTunnelRequest, ResolveSSHConnectionRequest, ResolveSSHConnectionResponse } from '@gitpod/local-app-api-grpcweb/lib/localapp_pb'; +import { LocalAppClient } from '@gitpod/local-app-api-grpcweb/lib/localapp_pb_service'; +import { NodeHttpTransport } from '@improbable-eng/grpc-web-node-http-transport'; +import * as cp from 'child_process'; +import * as fs from 'fs'; +import * as http from 'http'; +import * as net from 'net'; +import fetch, { Response } from 'node-fetch'; +import { performance } from 'perf_hooks'; +import * as tmp from 'tmp'; +import * as util from 'util'; +import * as vscode from 'vscode'; +import { grpc } from '@improbable-eng/grpc-web'; +const streamPipeline = util.promisify(require('stream').pipeline); + +interface SSHConnectionParams { + workspaceId: string + instanceId: string + gitpodHost: string +} + +interface LocalAppConfig { + gitpodHost: string + configFile: string + apiPort: number + pid: number + logPath: string +} + +interface Lock { + value: string + deadline: number +} + +interface LocalAppInstallation { + path: string + etag: string | null +} + +export async function activate(context: vscode.ExtensionContext) { + const output = vscode.window.createOutputChannel('Gitpod'); + + // TODO(ak) commands to show logs and stop local apps + // TODO(ak) auto stop local apps if not used for 3 hours + + function throwIfCancelled(token: vscode.CancellationToken): void { + if (token.isCancellationRequested) { + throw new Error('cancelled'); + } + } + + const lockPrefix = 'lock/'; + const fastLockTimeout = 5000; + const slowLockTimeout = 30000; + function releaseStaleLocks(): void { + for (const key of context.globalState.keys()) { + if (key.startsWith(lockPrefix)) { + const lock = context.globalState.get(key); + if (typeof lock !== 'object' || performance.now() >= lock.deadline) { + const lockName = key.substr(lockPrefix.length); + output.appendLine(`cancel stale lock: ${lockName}`); + context.globalState.update(key, undefined); + } + } + } + } + let lockCount = 0; + async function withLock(lockName: string, op: (token: vscode.CancellationToken) => Promise, timeout: number): Promise { + output.appendLine(`acquiring lock: ${lockName}`); + const lockKey = lockPrefix + lockName; + const value = vscode.env.sessionId + '/' + lockCount++; + let currentLock: Lock | undefined; + let deadline: number | undefined; + const updateTimeout = 150; + while (currentLock?.value !== value) { + currentLock = context.globalState.get(lockKey); + if (!currentLock) { + deadline = performance.now() + timeout + updateTimeout * 2; + await context.globalState.update(lockKey, { value, deadline }); + } + // TODO(ak) env.globaState.onDidChange instead, see https://github.com/microsoft/vscode/issues/131182 + await new Promise(resolve => setTimeout(resolve, updateTimeout)); + currentLock = context.globalState.get(lockKey); + } + output.appendLine(`acquired lock: ${lockName}`); + const tokenSource = new vscode.CancellationTokenSource(); + let timer = setInterval(() => { + currentLock = context.globalState.get(lockKey); + if (currentLock?.value !== value) { + tokenSource.cancel(); + } + }, updateTimeout); + try { + const result = await op(tokenSource.token); + return result; + } finally { + if (timer) { + clearTimeout(timer); + } + output.appendLine(`released lock: ${lockName}`); + await context.globalState.update(lockKey, undefined); + } + } + + const releaseStaleLocksTimer = setInterval(() => releaseStaleLocks(), fastLockTimeout); + context.subscriptions.push(new vscode.Disposable(() => clearInterval(releaseStaleLocksTimer))); + + function downloadLocalApp(gitpodHost: string): Promise { + let downloadUri = vscode.Uri.parse(gitpodHost); + if (process.platform === 'win32') { + downloadUri = downloadUri.with({ + path: '/static/bin/gitpod-local-companion-windows.exe' + }); + } else if (process.platform === 'darwin') { + downloadUri = downloadUri.with({ + path: '/static/bin/gitpod-local-companion-darwin' + }); + } else { + downloadUri = downloadUri.with({ + path: '/static/bin/gitpod-local-companion-linux' + }); + } + output.appendLine(`fetching the local app from ${downloadUri.toString()}`); + return fetch(downloadUri.toString()); + } + + async function installLocalApp(download: Response, token: vscode.CancellationToken): Promise { + try { + const installationPath = await new Promise((resolve, reject) => + tmp.file({ prefix: 'gitpod-local-companion' }, (err, path) => { + if (err) { + return reject(err); + } + return resolve(path); + }) + ); + throwIfCancelled(token); + output.appendLine(`installing the local app to ${installationPath}`); + throwIfCancelled(token); + await streamPipeline(download.body, fs.createWriteStream(installationPath)); + throwIfCancelled(token); + if (process.platform !== 'win32') { + await fs.promises.chmod(installationPath, '755'); + throwIfCancelled(token); + } + const installation: LocalAppInstallation = { path: installationPath, etag: download.headers.get('etag') }; + output.appendLine(`installing the local app: ${JSON.stringify(installation, undefined, 2)}`); + return installation; + } catch (e) { + output.appendLine(`failed to install the local app: ${e}`); + throw e; + } + } + + async function startLocalApp(gitpodHost: string, installation: LocalAppInstallation, token: vscode.CancellationToken): Promise { + try { + const [configFile, apiPort] = await Promise.all([new Promise((resolve, reject) => + tmp.file({ prefix: 'gitpod_ssh_config' }, (err, path) => { + if (err) { + return reject(err); + } + return resolve(path); + }) + ), new Promise(resolve => { + const server = http.createServer(); + server.listen(0, 'localhost', () => { + resolve((server.address() as net.AddressInfo).port); + server.close(); + }); + })]); + throwIfCancelled(token); + output.appendLine(`starting the local app with the config: ${JSON.stringify({ gitpodHost, configFile, apiPort }, undefined, 2)}`); + const logPath = installation.path + '.log'; + let spawnTimer: NodeJS.Timeout | undefined; + const pid = await new Promise((resolve, reject) => { + const logStream = fs.createWriteStream(logPath); + logStream.on('error', reject); + logStream.on('open', () => { + if (token.isCancellationRequested) { + reject(new Error('cancelled')); + } + // TODO(ak) pass this window URL as oauth callback + const localAppProcess = cp.spawn(installation.path, { + detached: true, + stdio: ['ignore', logStream, logStream], + env: { + ...process.env, + GITPOD_HOST: gitpodHost, + GITPOD_LCA_SSH_CONFIG: configFile, + GITPOD_LCA_API_PORT: String(apiPort), + GITPOD_LCA_AUTO_TUNNEL: String(false), + GITPOD_LCA_AUTH_REDIRECT_URL: `${vscode.env.uriScheme}://${context.extension.id}${authCompletePath}` + } + }); + localAppProcess.on('error', reject); + localAppProcess.on('exit', code => reject(new Error('unexpectedly exit with code: ' + code))); + localAppProcess.unref(); + if (localAppProcess.pid) { + // TODO(ak) when Node.js > 14.17 + // localAppProcess.on('spwan', () => resolve(localAppProcess.pid))); + spawnTimer = setInterval(() => { + try { + process.kill(localAppProcess.pid, 0); + resolve(localAppProcess.pid); + } catch { } + }, 150); + } + }); + }).finally(() => { + if (spawnTimer) { + clearInterval(spawnTimer); + } + }); + output.appendLine(`the local app has been stared: ${JSON.stringify({ pid, logPath }, undefined, 2)}`); + return { gitpodHost, configFile, apiPort, pid, logPath }; + } catch (e) { + output.appendLine(`failed to start the local app: ${e}`); + throw e; + } + } + + /** + * **Important: it should not call the local app to manage in 30sec** + */ + async function ensureLocalApp(gitpodHost: string, configKey: string, installationKey: string, token: vscode.CancellationToken): Promise { + let download: Response | Error; + try { + download = await downloadLocalApp(gitpodHost); + throwIfCancelled(token); + if (!download.ok) { + download = new Error(`unexpected download response ${download.statusText} (${download.status})`); + } + } catch (e) { + download = e; + } + let config = context.globalState.get(configKey); + let installation = context.globalState.get(installationKey); + if (installation) { + const upgrade = !(download instanceof Error) && { etag: download.headers.get('etag'), url: download.url }; + if (upgrade && upgrade.etag && upgrade.etag !== installation.etag) { + output.appendLine(`the local app is outdated, upgrading: ${JSON.stringify({ installation, upgrade }, undefined, 2)}`); + installation = undefined; + if (config) { + try { + process.kill(config.pid); + } catch (e) { + output.appendLine(`failed to kill the outdated local app (pid: ${config.pid}): ${e}`); + } + } + config = undefined; + } + } + if (config) { + return config; + } + if (installation) { + try { + await fs.promises.access(installation.path, fs.constants.X_OK); + throwIfCancelled(token); + } catch { + installation = undefined; + } + } + if (!installation) { + if (download instanceof Error) { + throw download; + } + installation = await installLocalApp(download, token); + await context.globalState.update(installationKey, installation); + throwIfCancelled(token); + } + config = await startLocalApp(gitpodHost, installation, token); + await context.globalState.update(configKey, config); + throwIfCancelled(token); + return config; + } + + async function withLocalApp(gitpodHost: string, op: (client: LocalAppClient, config: LocalAppConfig) => Promise): Promise { + const gitpodAuthority = vscode.Uri.parse(gitpodHost).authority; + const configKey = 'config/' + gitpodAuthority; + const installationKey = 'installation/' + gitpodAuthority; + let restartAttempts = 0; + while (restartAttempts < 5) { + const config = await withLock(gitpodAuthority, token => + ensureLocalApp(gitpodHost, configKey, installationKey, token) + , slowLockTimeout); + const client = new LocalAppClient('http://localhost:' + config.apiPort, { transport: NodeHttpTransport() }); + try { + const result = await op(client, config); + return result; + } catch (e) { + let running: true | Error; + try { + process.kill(config.pid, 0); + running = true; + } catch (e2) { + running = e2; + } + if (running === true && (e.code === grpc.Code.Unavailable || e.code === grpc.Code.Unknown)) { + output.appendLine(`the local app (pid: ${config.pid}) is running, but the api endpoint is not ready: ${e}`); + output.appendLine(`retying again after 1s delay...`); + await new Promise(resolve => setTimeout(resolve, 1000)); + continue; + } + if (running === true) { + throw e; + } + output.appendLine(`failed to access the local app: ${e}`); + output.appendLine(`the local app (pid: ${config.pid}) is not running: ${running}`); + output.appendLine(`restarting the local app...`); + await withLock(gitpodAuthority, async () => { + if (JSON.stringify(context.globalState.get(configKey)) === JSON.stringify(config)) { + await context.globalState.update(configKey, undefined); + } + }, fastLockTimeout); + restartAttempts++; + } + } + throw new Error('failed to access the local app'); + } + + async function resolveSSHConnection({ instanceId, workspaceId, gitpodHost }: SSHConnectionParams): Promise { + return withLocalApp(gitpodHost, client => { + const request = new ResolveSSHConnectionRequest(); + request.setInstanceId(instanceId); + request.setWorkspaceId(workspaceId); + return new Promise((resolve, reject) => + client.resolveSSHConnection(request, (e, r) => r ? resolve(r) : reject(e)) + ); + }); + } + + const authCompletePath = '/auth-complete'; + context.subscriptions.push(vscode.window.registerUriHandler({ + handleUri: async uri => { + if (uri.path === authCompletePath) { + output.appendLine('auth completed'); + return; + } + output.appendLine('open workspace window: ' + uri.toString()); + const params: SSHConnectionParams = JSON.parse(uri.query); + try { + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + cancellable: false, + title: `Connecting to Gitpod workspace: ${params.workspaceId}` + }, async () => { + const connection = await resolveSSHConnection(params); + + const config = vscode.workspace.getConfiguration('remote.SSH'); + const defaultExtensions = config.get('defaultExtensions') || []; + if (defaultExtensions.indexOf('gitpod.gitpod-remote-ssh') === -1) { + defaultExtensions.unshift('gitpod.gitpod-remote-ssh'); + await config.update('defaultExtensions', defaultExtensions, vscode.ConfigurationTarget.Global); + } + // TODO(ak) notify a user about config file changes? + const gitpodConfigFile = connection.getConfigFile(); + const currentConfigFile = config.get('configFile'); + if (currentConfigFile === gitpodConfigFile) { + // invalidate cached SSH targets from the current config file + await config.update('configFile', undefined, vscode.ConfigurationTarget.Global); + } + await config.update('configFile', gitpodConfigFile, vscode.ConfigurationTarget.Global); + // TODO(ak) ensure that vscode.ssh-remote is installed + await vscode.commands.executeCommand('vscode.openFolder', vscode.Uri.parse(`vscode-remote://ssh-remote+${connection.getHost()}${uri.path || '/'}`), { + forceNewWindow: true + }); + }); + } catch (e) { + vscode.window.showErrorMessage(`Failed to connect to Gitpod workspace ${params.workspaceId}: ${e}`); + output.appendLine(`failed to open uri: ${e}`); + throw e; + } + } + })); + + if (vscode.env.remoteName === undefined || context.extension.extensionKind !== vscode.ExtensionKind.UI) { + return; + } + + context.subscriptions.push(vscode.commands.registerCommand('gitpod-desktop.api.autoTunnel', async (gitpodHost: string, instanceId: string, enabled: boolean) => { + try { + await withLocalApp(gitpodHost, client => { + const request = new AutoTunnelRequest(); + request.setInstanceId(instanceId); + request.setEnabled(enabled); + return new Promise((resolve, reject) => + client.autoTunnel(request, (e, r) => r ? resolve(undefined) : reject(e)) + ); + }); + } catch (e) { + console.error('failed to disable auto tunneling', e); + } + })); +} + +export function deactivate() { } diff --git a/extensions/gitpod-ui/tsconfig.json b/extensions/gitpod-desktop/tsconfig.json similarity index 100% rename from extensions/gitpod-ui/tsconfig.json rename to extensions/gitpod-desktop/tsconfig.json diff --git a/extensions/gitpod-desktop/yarn.lock b/extensions/gitpod-desktop/yarn.lock new file mode 100644 index 0000000000000..6226fa25ca600 --- /dev/null +++ b/extensions/gitpod-desktop/yarn.lock @@ -0,0 +1,198 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@gitpod/local-app-api-grpcweb@ak-vscode-desktop": + version "0.1.5-ak-vscode-desktop.10" + resolved "https://registry.yarnpkg.com/@gitpod/local-app-api-grpcweb/-/local-app-api-grpcweb-0.1.5-ak-vscode-desktop.10.tgz#85ae5128dacc7cb7ae0ddbfe36b826302e969f83" + integrity sha512-YX7zKRQjb0O58DM2e5rAb9VQNZELSHUJXW8ZkIogqe4YY6kQFgl5eTs2Tyj6EsHt1N/du4UR/9Wt4SQ0I0QmYg== + dependencies: + "@gitpod/supervisor-api-grpcweb" "0.1.5-prs-core-dev-kubeconfig.3" + "@improbable-eng/grpc-web" "0.14.0" + google-protobuf "^3.17.0" + +"@gitpod/supervisor-api-grpcweb@0.1.5-prs-core-dev-kubeconfig.3": + version "0.1.5-prs-core-dev-kubeconfig.3" + resolved "https://registry.yarnpkg.com/@gitpod/supervisor-api-grpcweb/-/supervisor-api-grpcweb-0.1.5-prs-core-dev-kubeconfig.3.tgz#ce6844841dd66435c77c3ef74cb1833f23038400" + integrity sha512-d7Def3zFVarb2vueYLmJ+hRkaNEkK84r2B0xWtYT/OLr323NMWiPYlWePPis7Vt7WBV9u69erCtTqP7jAqu2Tg== + dependencies: + "@improbable-eng/grpc-web" "^0.14.0" + +"@improbable-eng/grpc-web-node-http-transport@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.0.tgz#3edf05360541b2d7ba799ec0144780a7a9a99383" + integrity sha512-NGZJgY8zTTWM//9oGdJZ+acmCgcgUcqxu3NV3GMFxw35D+3xkdEz599r9O7urg1Vv0+LzXDvfWEg7qg1Ec8x1w== + +"@improbable-eng/grpc-web@0.14.0", "@improbable-eng/grpc-web@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.14.0.tgz#a71c5af471dcef6a2810798f71f93ed8d6ac3817" + integrity sha512-ag1PTMWpBZKGi6GrEcZ4lkU5Qag23Xjo10BmnK9qyx4TMmSVcWmQ3rECirfQzm2uogrM9n1M6xfOpFsJP62ivA== + dependencies: + browser-headers "^0.4.1" + +"@types/node-fetch@^2.5.12": + version "2.5.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" + integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "16.6.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.2.tgz#331b7b9f8621c638284787c5559423822fdffc50" + integrity sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA== + +"@types/node@^10.12.21": + version "10.17.60" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" + integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== + +"@types/tmp@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.2.1.tgz#83ecf4ec22a8c218c71db25f316619fe5b986011" + integrity sha512-7cTXwKP/HLOPVgjg+YhBdQ7bMiobGMuoBmrGmqwIWJv8elC6t1DfVc/mn4fD9UE1IjhwmhaQ5pGVXkmXbH0rhg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-headers@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02" + integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +glob@^7.1.3: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +google-protobuf@^3.17.0: + version "3.17.3" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.17.3.tgz#f87595073545a77946c8f0b67c302c5f7646d700" + integrity sha512-OVPzcSWIAJ+d5yiHyeaLrdufQtrvaBrF4JQg+z8ynTkbO3uFcujqXszTumqg1cGsAsjkWnI+M5B1xZ19yR4Wyg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +mime-db@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" + integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== + +mime-types@^2.1.12: + version "2.1.32" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" + integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== + dependencies: + mime-db "1.49.0" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + +vscode-nls@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" + integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= diff --git a/extensions/gitpod-remote-ssh/package.json b/extensions/gitpod-remote-ssh/package.json index d811e65472e08..4bd359d980462 100644 --- a/extensions/gitpod-remote-ssh/package.json +++ b/extensions/gitpod-remote-ssh/package.json @@ -3,7 +3,7 @@ "displayName": "%displayName%", "description": "%description%", "publisher": "gitpod", - "version": "0.0.11", + "version": "0.0.14", "license": "MIT", "preview": true, "repository": { diff --git a/extensions/gitpod-remote-ssh/src/extension.ts b/extensions/gitpod-remote-ssh/src/extension.ts index d15a631fca587..0d65780dd1dba 100644 --- a/extensions/gitpod-remote-ssh/src/extension.ts +++ b/extensions/gitpod-remote-ssh/src/extension.ts @@ -28,8 +28,8 @@ export async function activate(context: vscode.ExtensionContext) { registerCLI(gitpodContext); // For port tunneling we rely on Remote SSH capabilities - // and gitpod.gitpod-ui to disable auto tunneling from the current local machine. - vscode.commands.executeCommand('gitpod-ui.api.autoTunnel', gitpodContext.info.getInstanceId(), false); + // and gitpod.gitpod-desktop to disable auto tunneling from the current local machine. + vscode.commands.executeCommand('gitpod-desktop.api.autoTunnel', gitpodContext.info.getGitpodHost(), gitpodContext.info.getInstanceId(), false); // TODO // - auth? diff --git a/extensions/gitpod-ui/README.md b/extensions/gitpod-ui/README.md deleted file mode 100644 index 6ec29acd4abdb..0000000000000 --- a/extensions/gitpod-ui/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Gitpod Web integration - -## Features - -This extension provides support for Gitpod UI integration. diff --git a/extensions/gitpod-ui/package.nls.json b/extensions/gitpod-ui/package.nls.json deleted file mode 100644 index c319097c03a79..0000000000000 --- a/extensions/gitpod-ui/package.nls.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "displayName": "Gitpod UI", - "description": "Gitpod UI Support" -} diff --git a/extensions/gitpod-ui/src/extension.ts b/extensions/gitpod-ui/src/extension.ts deleted file mode 100644 index 136bade78859b..0000000000000 --- a/extensions/gitpod-ui/src/extension.ts +++ /dev/null @@ -1,34 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Gitpod. All rights reserved. - *--------------------------------------------------------------------------------------------*/ - -/// - -import { AutoTunnelRequest } from '@gitpod/local-app-api-grpcweb/lib/localapp_pb'; -import { LocalAppClient } from '@gitpod/local-app-api-grpcweb/lib/localapp_pb_service'; -import { grpc } from '@improbable-eng/grpc-web'; -import { NodeHttpTransport } from '@improbable-eng/grpc-web-node-http-transport'; -import * as vscode from 'vscode'; - -export async function activate(context: vscode.ExtensionContext) { - if (vscode.env.remoteName === undefined || context.extension.extensionKind !== vscode.ExtensionKind.UI) { - return; - } - - grpc.setDefaultTransport(NodeHttpTransport()); - const defaultApiPort = 63100; // TODO(ak) settings - const client = new LocalAppClient('http://localhost:' + defaultApiPort); - - context.subscriptions.push(vscode.commands.registerCommand('gitpod-ui.api.autoTunnel', (instanceId: string, enabled: boolean) => { - const request = new AutoTunnelRequest(); - request.setInstanceId(instanceId); - request.setEnabled(enabled); - client.autoTunnel(request, e => { - if (e) { - console.error('failed to disable auto tunneling', e); - } - }); - })); -} - -export function deactivate() { } diff --git a/extensions/gitpod-ui/yarn.lock b/extensions/gitpod-ui/yarn.lock deleted file mode 100644 index 84300a3b3f498..0000000000000 --- a/extensions/gitpod-ui/yarn.lock +++ /dev/null @@ -1,51 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@gitpod/local-app-api-grpcweb@ak-remote-ssh": - version "0.1.5-ak-remote-ssh.2" - resolved "https://registry.yarnpkg.com/@gitpod/local-app-api-grpcweb/-/local-app-api-grpcweb-0.1.5-ak-remote-ssh.2.tgz#6b3738ec7f240fb9c8c3e04a9bbfdb4bbbd41205" - integrity sha512-Z09CgciGhIngrMEw5V/0aGcpiIORN/UpmEExBlNEdGSlbF9j803kaAo5TLmGHSL++RwOHgQzZN6CoTCrbX8NLA== - dependencies: - "@gitpod/supervisor-api-grpcweb" "0.1.5-at-prebuild-page.43" - "@improbable-eng/grpc-web" "0.14.0" - google-protobuf "^3.17.0" - -"@gitpod/supervisor-api-grpcweb@0.1.5-at-prebuild-page.43": - version "0.1.5-at-prebuild-page.43" - resolved "https://registry.yarnpkg.com/@gitpod/supervisor-api-grpcweb/-/supervisor-api-grpcweb-0.1.5-at-prebuild-page.43.tgz#a7ee638c8d28ce945701bc865b7fdced9de6bfa3" - integrity sha512-jM3amS9FSGIeZ5ZObPWl+vHyweO+KMR5GPBQQ57oQD/dvLGymcMyC6QuOeFaBcna/yLXa5WTRM5M+Y10lftKVg== - dependencies: - "@improbable-eng/grpc-web" "^0.14.0" - -"@improbable-eng/grpc-web-node-http-transport@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.0.tgz#3edf05360541b2d7ba799ec0144780a7a9a99383" - integrity sha512-NGZJgY8zTTWM//9oGdJZ+acmCgcgUcqxu3NV3GMFxw35D+3xkdEz599r9O7urg1Vv0+LzXDvfWEg7qg1Ec8x1w== - -"@improbable-eng/grpc-web@0.14.0", "@improbable-eng/grpc-web@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.14.0.tgz#a71c5af471dcef6a2810798f71f93ed8d6ac3817" - integrity sha512-ag1PTMWpBZKGi6GrEcZ4lkU5Qag23Xjo10BmnK9qyx4TMmSVcWmQ3rECirfQzm2uogrM9n1M6xfOpFsJP62ivA== - dependencies: - browser-headers "^0.4.1" - -"@types/node@^10.12.21": - version "10.17.60" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" - integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== - -browser-headers@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02" - integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg== - -google-protobuf@^3.17.0: - version "3.17.3" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.17.3.tgz#f87595073545a77946c8f0b67c302c5f7646d700" - integrity sha512-OVPzcSWIAJ+d5yiHyeaLrdufQtrvaBrF4JQg+z8ynTkbO3uFcujqXszTumqg1cGsAsjkWnI+M5B1xZ19yR4Wyg== - -vscode-nls@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" - integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== diff --git a/extensions/gitpod-web/package.json b/extensions/gitpod-web/package.json index 752ecc96e7b2a..e6624ee6e7614 100644 --- a/extensions/gitpod-web/package.json +++ b/extensions/gitpod-web/package.json @@ -100,6 +100,14 @@ "command": "gitpod.stop.ws", "group": "gitpod@50", "when": "gitpod.workspaceOwned == true" + }, + { + "command": "gitpod.openInStable", + "group": "gitpod@60" + }, + { + "command": "gitpod.openInInsiders", + "group": "gitpod@70" } ], "accounts/context": [ diff --git a/extensions/gitpod/extension.webpack.config.js b/extensions/gitpod/extension.webpack.config.js index 981155bdc9b20..e18229a8e170a 100644 --- a/extensions/gitpod/extension.webpack.config.js +++ b/extensions/gitpod/extension.webpack.config.js @@ -17,10 +17,5 @@ module.exports = withDefaults({ }, externals: { 'keytar': 'commonjs keytar' - }, - resolve: { - alias: { - 'uuid': path.resolve(__dirname, 'node_modules/uuid/dist/esm-node/index.js') - } } }); diff --git a/extensions/gitpod/package.json b/extensions/gitpod/package.json index 7212f5bd7e83c..9951fb5bbb40d 100644 --- a/extensions/gitpod/package.json +++ b/extensions/gitpod/package.json @@ -3,7 +3,7 @@ "displayName": "%displayName%", "description": "%description%", "publisher": "gitpod", - "version": "0.0.11", + "version": "0.0.14", "license": "MIT", "preview": true, "repository": { @@ -28,68 +28,92 @@ { "command": "gitpod.stop.ws", "title": "%stopWorkspace%", - "enablement": "gitpod.workspaceOwned == true" + "enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true" }, { "command": "gitpod.open.settings", - "title": "%openSettings%" + "title": "%openSettings%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.accessControl", - "title": "%openAccessControl%" + "title": "%openAccessControl%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.context", - "title": "%openContext%" + "title": "%openContext%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.dashboard", - "title": "%openDashboard%" + "title": "%openDashboard%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.documentation", - "title": "%openDocumentation%" + "title": "%openDocumentation%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.twitter", - "title": "%openTwitter%" + "title": "%openTwitter%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.discord", - "title": "%openDiscord%" + "title": "%openDiscord%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.discourse", - "title": "%openDiscourse%" + "title": "%openDiscourse%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.reportIssue", - "title": "%reportIssue%" + "title": "%reportIssue%", + "enablement": "gitpod.inWorkspace == true" }, { "command": "gitpod.upgradeSubscription", "title": "%upgradeSubscription%", - "enablement": "gitpod.workspaceOwned == true" + "enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true" }, { "command": "gitpod.ExtendTimeout", "title": "%extendTimeout%", - "enablement": "gitpod.workspaceOwned == true" + "enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true" }, { "command": "gitpod.takeSnapshot", "title": "%takeSnapshot%", - "enablement": "gitpod.workspaceOwned == true" + "enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true" }, { "command": "gitpod.shareWorkspace", "title": "%shareWorkspace%", - "enablement": "gitpod.workspaceOwned == true && gitpod.workspaceShared == false" + "enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true && gitpod.workspaceShared == false" }, { "command": "gitpod.stopSharingWorkspace", "title": "%stopSharingWorkspace%", - "enablement": "gitpod.workspaceOwned == true && gitpod.workspaceShared == true" + "enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true && gitpod.workspaceShared == true" + }, + { + "command": "gitpod.openInStable", + "title": "%openInStable%", + "enablement": "gitpod.inWorkspace == true && gitpod.UIKind == 'web'" + }, + { + "command": "gitpod.openInInsiders", + "title": "%openInInsiders%", + "enablement": "gitpod.inWorkspace == true && gitpod.UIKind == 'web'" + }, + { + "command": "gitpod.openInBrowser", + "title": "%openInBrowser%", + "enablement": "gitpod.inWorkspace == true && gitpod.UIKind == 'desktop'" } ], "menus": { @@ -97,68 +121,92 @@ { "command": "gitpod.stop.ws", "group": "remote_00_gitpod_navigation@10", - "when": "gitpod.workspaceOwned == true" + "when": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true" }, { "command": "gitpod.open.settings", - "group": "remote_00_gitpod_navigation@20" + "group": "remote_00_gitpod_navigation@20", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.accessControl", - "group": "remote_00_gitpod_navigation@30" + "group": "remote_00_gitpod_navigation@30", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.context", - "group": "remote_00_gitpod_navigation@40" + "group": "remote_00_gitpod_navigation@40", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.dashboard", - "group": "remote_00_gitpod_navigation@50" + "group": "remote_00_gitpod_navigation@50", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.documentation", - "group": "remote_00_gitpod_navigation@60" + "group": "remote_00_gitpod_navigation@60", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.twitter", - "group": "remote_00_gitpod_navigation@70" + "group": "remote_00_gitpod_navigation@70", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.discord", - "group": "remote_00_gitpod_navigation@80" + "group": "remote_00_gitpod_navigation@80", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.open.discourse", - "group": "remote_00_gitpod_navigation@81" + "group": "remote_00_gitpod_navigation@81", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.reportIssue", - "group": "remote_00_gitpod_navigation@90" + "group": "remote_00_gitpod_navigation@90", + "when": "gitpod.inWorkspace == true" }, { "command": "gitpod.upgradeSubscription", "group": "remote_00_gitpod_navigation@100", - "when": "gitpod.workspaceOwned == true" + "when": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true" }, { "command": "gitpod.ExtendTimeout", "group": "remote_00_gitpod_navigation@110", - "when": "gitpod.workspaceOwned == true" + "when": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true" }, { "command": "gitpod.takeSnapshot", "group": "remote_00_gitpod_navigation@120", - "when": "gitpod.workspaceOwned == true" + "when": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true" }, { "command": "gitpod.shareWorkspace", "group": "remote_00_gitpod_navigation@130", - "when": "gitpod.workspaceOwned == true && gitpod.workspaceShared == false" + "when": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true && gitpod.workspaceShared == false" }, { "command": "gitpod.stopSharingWorkspace", "group": "remote_00_gitpod_navigation@130", - "when": "gitpod.workspaceOwned == true && gitpod.workspaceShared == true" + "when": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true && gitpod.workspaceShared == true" + }, + { + "command": "gitpod.openInStable", + "group": "remote_00_gitpod_navigation@900", + "when": "gitpod.inWorkspace == true && gitpod.UIKind == 'web'" + }, + { + "command": "gitpod.openInInsiders", + "group": "remote_00_gitpod_navigation@1000", + "when": "gitpod.inWorkspace == true && gitpod.UIKind == 'web'" + }, + { + "command": "gitpod.openInBrowser", + "group": "remote_00_gitpod_navigation@1000", + "when": "gitpod.inWorkspace == true && gitpod.UIKind == 'desktop'" } ] } @@ -170,17 +218,14 @@ }, "devDependencies": { "@types/node": "^10.12.21", - "@types/uuid": "8.0.0", "@types/ws": "^7.2.6" }, "dependencies": { "@gitpod/gitpod-protocol": "main", "@gitpod/supervisor-api-grpc": "main", - "@types/uuid": "^8.3.1", "bufferutil": "^4.0.1", "reconnecting-websocket": "^4.4.0", "utf-8-validate": "^5.0.2", - "uuid": "^8.2.0", "vscode-nls": "^5.0.0", "ws": "^7.3.1", "yaml": "^1.10.0" diff --git a/extensions/gitpod/package.nls.json b/extensions/gitpod/package.nls.json index 941bec0f4b32d..3d5c07d335cd1 100644 --- a/extensions/gitpod/package.nls.json +++ b/extensions/gitpod/package.nls.json @@ -15,5 +15,8 @@ "extendTimeout": "Gitpod: Extend Workspace Timeout", "takeSnapshot": "Gitpod: Share Workspace Snapshot", "shareWorkspace": "Gitpod: Share Running Workspace", - "stopSharingWorkspace": "Gitpod: Stop Sharing Running Workspace" + "stopSharingWorkspace": "Gitpod: Stop Sharing Running Workspace", + "openInStable": "Gitpod: Open in VS Code", + "openInInsiders": "Gitpod: Open in VS Code Insiders", + "openInBrowser": "Gitpod: Open in Browser" } diff --git a/extensions/gitpod/src/extension.ts b/extensions/gitpod/src/extension.ts index 592162a79c698..260e1021d9aac 100644 --- a/extensions/gitpod/src/extension.ts +++ b/extensions/gitpod/src/extension.ts @@ -5,7 +5,6 @@ import * as vscode from 'vscode'; import { createGitpodExtensionContext, GitpodExtensionContext, registerDefaultLayout, registerNotifications, registerWorkspaceCommands, registerWorkspaceSharing, registerWorkspaceTimeout } from './features'; import { GitpodExtension } from './gitpod'; -import { v4 } from 'uuid'; import { performance } from 'perf_hooks'; let gitpodContext: GitpodExtensionContext | undefined; @@ -16,8 +15,10 @@ export async function activate(context: vscode.ExtensionContext): Promise openDesktop('vscode'))); + context.subscriptions.push(vscode.commands.registerCommand('gitpod.openInInsiders', () => openDesktop('vscode-insiders'))); + } + // TODO(ak) fetch from supervisor info endpoint + const workspaceUrl = process.env.GITPOD_WORKSPACE_URL; + if (vscode.env.uiKind === vscode.UIKind.Desktop && workspaceUrl) { + vscode.commands.executeCommand('setContext', 'gitpod.UIKind', 'desktop'); + context.subscriptions.push(vscode.commands.registerCommand('gitpod.openInBrowser', () => + vscode.env.openExternal(vscode.Uri.parse(workspaceUrl)) + )); + } + const communityStatusBarItem = vscode.window.createStatusBarItem('gitpod.community', vscode.StatusBarAlignment.Right, -100); communityStatusBarItem.name = 'Chat with us on Discourse'; context.subscriptions.push(communityStatusBarItem); diff --git a/extensions/gitpod/yarn.lock b/extensions/gitpod/yarn.lock index 47f31d5e46c31..11d07c40bb62e 100644 --- a/extensions/gitpod/yarn.lock +++ b/extensions/gitpod/yarn.lock @@ -60,11 +60,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.35.tgz#58058f29b870e6ae57b20e4f6e928f02b7129f56" integrity sha512-gXx7jAWpMddu0f7a+L+txMplp3FnHl53OhQIF9puXKq3hDGY/GjH+MF04oWnV/adPSCrbtHumDCFwzq2VhltWA== -"@types/uuid@^8.3.1": - version "8.3.1" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f" - integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg== - "@types/ws@^7.2.6": version "7.2.6" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.2.6.tgz#516cbfb818310f87b43940460e065eb912a4178d" @@ -402,11 +397,6 @@ uuid@^3.2.1, uuid@^3.3.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.2.0: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - vscode-jsonrpc@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz#9bab9c330d89f43fc8c1e8702b5c36e058a01794" diff --git a/src/vs/gitpod/node/server.ts b/src/vs/gitpod/node/server.ts index 79cf87711bd43..bc43467e1294a 100644 --- a/src/vs/gitpod/node/server.ts +++ b/src/vs/gitpod/node/server.ts @@ -75,7 +75,7 @@ main({ port, main: path.join(APP_ROOT, 'out', 'vs', 'gitpod', 'browser', 'workbench', 'workbench.html'), mainDev: path.join(APP_ROOT, 'out', 'vs', 'gitpod', 'browser', 'workbench', 'workbench-dev.html'), - skipExtensions: new Set(['vscode.github-authentication', 'gitpod.gitpod-remote-ssh', 'gitpod.gitpod-ui']), + skipExtensions: new Set(['vscode.github-authentication', 'gitpod.gitpod-remote-ssh', 'gitpod.gitpod-desktop']), configure: services => { services.set(IExtensionManagementCLIService, new SyncDescriptor(ExtensionManagementCLIService)); },