Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[server] add editor prefix to choose custom IDE #9467

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion components/gitpod-protocol/src/context-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export namespace ContextURL {
export const IMAGEBUILD_PREFIX = "imagebuild";
export const SNAPSHOT_PREFIX = "snapshot";
export const REFERRER_PREFIX = "referrer:";
export const EDITOR_PREFIX = "editor:";

/**
* This function will (try to) return the HTTP(S) URL of the context the user originally created this workspace on.
Expand Down Expand Up @@ -94,7 +95,8 @@ export namespace ContextURL {
firstSegment === INCREMENTAL_PREBUILD_PREFIX ||
firstSegment === IMAGEBUILD_PREFIX ||
firstSegment === SNAPSHOT_PREFIX ||
firstSegment.startsWith(REFERRER_PREFIX)
firstSegment.startsWith(REFERRER_PREFIX) ||
firstSegment.startsWith(EDITOR_PREFIX)
) {
return segmentsToURL(1);
}
Expand Down
11 changes: 11 additions & 0 deletions components/gitpod-protocol/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,17 @@ export namespace PrebuiltWorkspaceContext {
}
}

export interface WithEditorContext extends WorkspaceContext {
ide: string;
useLatest?: boolean;
}

export namespace WithEditorContext {
export function is(context: any): context is WithEditorContext {
return context && "ide" in context;
}
}

export interface WithReferrerContext extends WorkspaceContext {
referrer: string;
referrerIde?: string;
Expand Down
2 changes: 2 additions & 0 deletions components/server/src/container-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import { DebugApp } from "./debug-app";
import { LocalMessageBroker, LocalRabbitMQBackedMessageBroker } from "./messaging/local-message-broker";
import { contentServiceBinder } from "@gitpod/content-service/lib/sugar";
import { ReferrerPrefixParser } from "./workspace/referrer-prefix-context-parser";
import { EditorPrefixParser } from "./workspace/editor-prefix-context-parser";
import { InstallationAdminTelemetryDataProvider } from "./installation-admin/telemetry-data-provider";

export const productionContainerModule = new ContainerModule((bind, unbind, isBound, rebind) => {
Expand Down Expand Up @@ -169,6 +170,7 @@ export const productionContainerModule = new ContainerModule((bind, unbind, isBo
bind(SnapshotContextParser).toSelf().inSingletonScope();
bind(IContextParser).to(SnapshotContextParser).inSingletonScope();
bind(IPrefixContextParser).to(ReferrerPrefixParser).inSingletonScope();
bind(IPrefixContextParser).to(EditorPrefixParser).inSingletonScope();
bind(IPrefixContextParser).to(EnvvarPrefixParser).inSingletonScope();
bind(IPrefixContextParser).to(ImageBuildPrefixContextParser).inSingletonScope();
bind(IPrefixContextParser).to(AdditionalContentPrefixContextParser).inSingletonScope();
Expand Down
25 changes: 25 additions & 0 deletions components/server/src/workspace/editor-prefix-context-parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright (c) 2020 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License-AGPL.txt in the project root for license information.
*/

import { IPrefixContextParser } from "./context-parser";
import { User, WorkspaceContext, WithEditorContext } from "@gitpod/gitpod-protocol";
import { injectable } from "inversify";

@injectable()
export class EditorPrefixParser implements IPrefixContextParser {
private readonly prefix = /^\/?editor:([^\/:]*?)(?::([^\/:]*?))?\//;

findPrefix(_: User, context: string): string | undefined {
return this.prefix.exec(context)?.[0] || undefined;
}

async handle(_: User, prefix: string, context: WorkspaceContext): Promise<WorkspaceContext | WithEditorContext> {
const matches = this.prefix.exec(prefix);
const ide = matches?.[1];
const useLatest = matches?.[2] === "latest";
return ide ? { ...context, ide, useLatest } : context;
}
}
14 changes: 14 additions & 0 deletions components/server/src/workspace/workspace-starter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,5 +249,19 @@ describe("workspace-starter", function () {
const result = chooseIDE("unknown-custom", customOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
});

it("not exists ide with custom permission", function () {
const useLatest = true;
const hasPerm = true;
const result = chooseIDE("not-exists", ideOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
});

it("not exists ide with custom permission", function () {
const useLatest = true;
const hasPerm = false;
const result = chooseIDE("not-exists", ideOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
});
});
});
17 changes: 11 additions & 6 deletions components/server/src/workspace/workspace-starter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ import * as path from "path";
import * as grpc from "@grpc/grpc-js";
import { IDEConfig, IDEConfigService } from "../ide-config";
import { EnvVarWithValue } from "@gitpod/gitpod-protocol/src/protocol";
import { WithReferrerContext } from "@gitpod/gitpod-protocol/lib/protocol";
import { WithEditorContext, WithReferrerContext } from "@gitpod/gitpod-protocol/lib/protocol";
import { IDEOption, IDEOptions } from "@gitpod/gitpod-protocol/lib/ide-protocol";
import { Deferred } from "@gitpod/gitpod-protocol/lib/util/deferred";
import { ExtendedUser } from "@gitpod/ws-manager/lib/constraints";
Expand Down Expand Up @@ -156,7 +156,7 @@ export const chooseIDE = (
const data: { desktopIdeImage?: string; ideImage: string } = {
ideImage: defaultIdeImage,
};
const chooseOption = ideOptions.options[ideChoice];
const chooseOption = ideOptions.options[ideChoice] ?? defaultIDEOption;
const isDesktopIde = chooseOption.type === "desktop";
if (isDesktopIde) {
data.desktopIdeImage = useLatest ? chooseOption?.latestImage ?? chooseOption?.image : chooseOption?.image;
Expand Down Expand Up @@ -607,8 +607,12 @@ export class WorkspaceStarter {
user.additionalData.ideSettings = migratted;
}

const ideChoice = user.additionalData?.ideSettings?.defaultIde;
const useLatest = !!user.additionalData?.ideSettings?.useLatestVersion;
const preferenceIDE = user.additionalData?.ideSettings?.defaultIde;
const perferenceUseLatest = !!user.additionalData?.ideSettings?.useLatestVersion;
const ideChoice = WithEditorContext.is(workspace.context) ? workspace.context.ide : preferenceIDE;
akosyakov marked this conversation as resolved.
Show resolved Hide resolved
const useLatest = WithEditorContext.is(workspace.context)
? workspace.context.useLatest ?? perferenceUseLatest
: perferenceUseLatest;

// TODO(cw): once we allow changing the IDE in the workspace config (i.e. .gitpod.yml), we must
// give that value precedence over the default choice.
Expand All @@ -618,7 +622,7 @@ export class WorkspaceStarter {
ideConfig: {
// We only check user setting because if code(insider) but desktopIde has no latestImage
// it still need to notice user that this workspace is using latest IDE
useLatest: user.additionalData?.ideSettings?.useLatestVersion,
useLatest,
},
};

Expand All @@ -635,9 +639,10 @@ export class WorkspaceStarter {

const referrerIde = this.resolveReferrerIDE(workspace, user, ideConfig);
if (referrerIde) {
configuration.desktopIdeImage = useLatest
configuration.desktopIdeImage = perferenceUseLatest
? referrerIde.option.latestImage ?? referrerIde.option.image
: referrerIde.option.image;
configuration.ideConfig!.useLatest = perferenceUseLatest;
if (!user.additionalData?.ideSettings) {
// A user does not have IDE settings configured yet configure it with a referrer ide as default.
const additionalData = user?.additionalData || {};
Expand Down