Skip to content

Commit

Permalink
t
Browse files Browse the repository at this point in the history
  • Loading branch information
akosyakov committed Dec 2, 2022
1 parent 93a68d3 commit c04d484
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 381 deletions.
136 changes: 59 additions & 77 deletions components/server/src/ide-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
* See License-AGPL.txt in the project root for license information.
*/

import { JetBrainsConfig, TaskConfig, Workspace } from "@gitpod/gitpod-protocol";
import { IDESettings, TaskConfig, User, Workspace } from "@gitpod/gitpod-protocol";
import { IDEOptions, IDEClient } from "@gitpod/gitpod-protocol/lib/ide-protocol";
import { IDEServiceClient, IDEServiceDefinition } from "@gitpod/ide-service-api/lib/ide.pb";
import {
IDEServiceClient,
IDEServiceDefinition,
ResolveWorkspaceConfigRequest,
ResolveWorkspaceConfigResponse,
} from "@gitpod/ide-service-api/lib/ide.pb";
import { inject, injectable } from "inversify";

export interface IDEConfig {
Expand Down Expand Up @@ -37,85 +42,62 @@ export class IDEService {
}
}

resolveGitpodTasks(ws: Workspace): TaskConfig[] {
const tasks: TaskConfig[] = [];
if (ws.config.tasks) {
tasks.push(...ws.config.tasks);
migrateSettings(user: User): IDESettings | undefined {
if (!user?.additionalData?.ideSettings || user.additionalData.ideSettings.settingVersion === "2.0") {
return undefined;
}
// TODO(ak) it is a hack to get users going, we should rather layer JB products on prebuild workspaces and move logic to corresponding images
if (ws.type === "prebuild" && ws.config.jetbrains) {
let warmUp = "";
for (const key in ws.config.jetbrains) {
let productCode;
if (key === "intellij") {
productCode = "IIU";
} else if (key === "goland") {
productCode = "GO";
} else if (key === "pycharm") {
productCode = "PCP";
} else if (key === "phpstorm") {
productCode = "PS";
} else if (key === "rubymine") {
productCode = "RM";
} else if (key === "webstorm") {
productCode = "WS";
} else if (key === "rider") {
productCode = "RD";
} else if (key === "clion") {
productCode = "CL";
}
const prebuilds = productCode && ws.config.jetbrains[key as keyof JetBrainsConfig]?.prebuilds;
if (prebuilds) {
warmUp +=
prebuilds.version === "latest"
? ""
: `
echo 'warming up stable release of ${key}...'
echo 'downloading stable ${key} backend...'
mkdir /tmp/backend
curl -sSLo /tmp/backend/backend.tar.gz "https://download.jetbrains.com/product?type=release&distribution=linux&code=${productCode}"
tar -xf /tmp/backend/backend.tar.gz --strip-components=1 --directory /tmp/backend
echo 'configuring JB system config and caches aligned with runtime...'
printf '\nshared.indexes.download.auto.consent=true' >> "/tmp/backend/bin/idea.properties"
unset JAVA_TOOL_OPTIONS
export IJ_HOST_CONFIG_BASE_DIR=/workspace/.config/JetBrains
export IJ_HOST_SYSTEM_BASE_DIR=/workspace/.cache/JetBrains
echo 'running stable ${key} backend in warmup mode...'
/tmp/backend/bin/remote-dev-server.sh warmup "$GITPOD_REPO_ROOT"
echo 'removing stable ${key} backend...'
rm -rf /tmp/backend
`;
warmUp +=
prebuilds.version === "stable"
? ""
: `
echo 'warming up latest release of ${key}...'
echo 'downloading latest ${key} backend...'
mkdir /tmp/backend-latest
curl -sSLo /tmp/backend-latest/backend-latest.tar.gz "https://download.jetbrains.com/product?type=release,eap,rc&distribution=linux&code=${productCode}"
tar -xf /tmp/backend-latest/backend-latest.tar.gz --strip-components=1 --directory /tmp/backend-latest
echo 'configuring JB system config and caches aligned with runtime...'
printf '\nshared.indexes.download.auto.consent=true' >> "/tmp/backend-latest/bin/idea.properties"
unset JAVA_TOOL_OPTIONS
export IJ_HOST_CONFIG_BASE_DIR=/workspace/.config/JetBrains-latest
export IJ_HOST_SYSTEM_BASE_DIR=/workspace/.cache/JetBrains-latest
echo 'running ${key} backend in warmup mode...'
/tmp/backend-latest/bin/remote-dev-server.sh warmup "$GITPOD_REPO_ROOT"
const newIDESettings: IDESettings = {
settingVersion: "2.0",
};
const ideSettings = user.additionalData.ideSettings;
if (ideSettings.useDesktopIde) {
if (ideSettings.defaultDesktopIde === "code-desktop") {
newIDESettings.defaultIde = "code-desktop";
} else if (ideSettings.defaultDesktopIde === "code-desktop-insiders") {
newIDESettings.defaultIde = "code-desktop";
newIDESettings.useLatestVersion = true;
} else {
newIDESettings.defaultIde = ideSettings.defaultDesktopIde;
newIDESettings.useLatestVersion = ideSettings.useLatestVersion;
}
} else {
const useLatest = ideSettings.defaultIde === "code-latest";
newIDESettings.defaultIde = "code";
newIDESettings.useLatestVersion = useLatest;
}
return newIDESettings;
}

echo 'removing latest ${key} backend...'
rm -rf /tmp/backend-latest
`;
}
async resolveWorkspaceConfig(req: ResolveWorkspaceConfigRequest): Promise<ResolveWorkspaceConfigResponse> {
for (let attempt = 0; attempt < 15; attempt++) {
if (attempt != 0) {
await new Promise((resolve) => setTimeout(resolve, 1000));
}
if (warmUp) {
tasks.push({
init: warmUp.trim(),
const controller = new AbortController();
setTimeout(() => controller.abort(), 1000);
try {
const resp = await this.ideService.resolveWorkspaceConfig(req, {
signal: controller.signal,
});
return resp;
} catch (e) {
console.error("ide-service: failed to resolve workspace config: ", e);
}
}
throw new Error("failed to resolve workspace IDE configuration");
}

resolveGitpodTasks(ws: Workspace, ideConfig: ResolveWorkspaceConfigResponse): TaskConfig[] {
const tasks: TaskConfig[] = [];
if (ws.config.tasks) {
tasks.push(...ws.config.tasks);
}
if (ideConfig.tasks) {
try {
let ideTasks: TaskConfig[] = JSON.parse(ideConfig.tasks);
tasks.push(...ideTasks);
} catch (e) {
console.error("failed get tasks from ide config:", e);
}
}
return tasks;
Expand Down
138 changes: 12 additions & 126 deletions components/server/src/workspace/workspace-starter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@
*/

import { User } from "@gitpod/gitpod-protocol";
import { IDEOption, IDEOptions } from "@gitpod/gitpod-protocol/lib/ide-protocol";
import * as chai from "chai";
import { migrationIDESettings, chooseIDE } from "./workspace-starter";
import { IDEService } from "../ide-service";
const expect = chai.expect;

describe("workspace-starter", function () {
describe("migrationIDESettings", function () {
describe("ide-service", function () {
describe("ideService.migrateSettings", function () {
const ideService = new IDEService();
it("with no ideSettings should be undefined", function () {
const user: User = {
id: "string",
creationDate: "string",
identities: [],
additionalData: {},
};
const result = migrationIDESettings(user);
const result = ideService.migrateSettings(user);
expect(result).to.undefined;
});

Expand All @@ -36,7 +36,7 @@ describe("workspace-starter", function () {
},
},
};
const result = migrationIDESettings(user);
const result = ideService.migrateSettings(user);
expect(result).to.undefined;
});

Expand All @@ -52,7 +52,7 @@ describe("workspace-starter", function () {
},
},
};
const result = migrationIDESettings(user);
const result = ideService.migrateSettings(user);
expect(result?.defaultIde).to.equal("code");
expect(result?.useLatestVersion ?? false).to.be.true;
});
Expand All @@ -70,7 +70,7 @@ describe("workspace-starter", function () {
},
},
};
const result = migrationIDESettings(user);
const result = ideService.migrateSettings(user);
expect(result?.defaultIde).to.equal("code-desktop");
expect(result?.useLatestVersion ?? false).to.be.true;
});
Expand All @@ -88,7 +88,7 @@ describe("workspace-starter", function () {
},
},
};
const result = migrationIDESettings(user);
const result = ideService.migrateSettings(user);
expect(result?.defaultIde).to.equal("code-desktop");
expect(result?.useLatestVersion ?? false).to.be.false;
});
Expand All @@ -107,7 +107,7 @@ describe("workspace-starter", function () {
},
},
};
const result = migrationIDESettings(user);
const result = ideService.migrateSettings(user);
expect(result?.defaultIde).to.equal("intellij");
expect(result?.useLatestVersion ?? false).to.be.false;
});
Expand All @@ -126,7 +126,7 @@ describe("workspace-starter", function () {
},
},
};
const result = migrationIDESettings(user);
const result = ideService.migrateSettings(user);
expect(result?.defaultIde).to.equal("intellij");
expect(result?.useLatestVersion ?? false).to.be.true;
});
Expand All @@ -145,123 +145,9 @@ describe("workspace-starter", function () {
},
},
};
const result = migrationIDESettings(user);
const result = ideService.migrateSettings(user);
expect(result?.defaultIde).to.equal("code");
expect(result?.useLatestVersion ?? false).to.be.true;
});
});
describe("chooseIDE", async function () {
const baseOpt: IDEOption = {
title: "title",
type: "desktop",
logo: "",
image: "image",
latestImage: "latestImage",
};
const ideOptions: IDEOptions = {
options: {
code: Object.assign({}, baseOpt, { type: "browser" }),
goland: Object.assign({}, baseOpt),
"code-desktop": Object.assign({}, baseOpt),
"no-latest": Object.assign({}, baseOpt),
},
defaultIde: "code",
defaultDesktopIde: "code-desktop",
};
delete ideOptions.options["no-latest"].latestImage;

it("code with latest", function () {
const useLatest = true;
const hasPerm = false;
const result = chooseIDE("code", ideOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
});

it("code without latest", function () {
const useLatest = false;
const hasPerm = false;
const result = chooseIDE("code", ideOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal(ideOptions.options["code"].image);
});

it("desktop ide with latest", function () {
const useLatest = true;
const hasPerm = false;
const result = chooseIDE("code-desktop", ideOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
expect(result.desktopIdeImage).to.equal(ideOptions.options["code-desktop"].latestImage);
});

it("desktop ide (JetBrains) without latest", function () {
const useLatest = false;
const hasPerm = false;
const result = chooseIDE("goland", ideOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal(ideOptions.options["code"].image);
expect(result.desktopIdeImage).to.equal(ideOptions.options["goland"].image);
});

it("desktop ide with no latest image", function () {
const useLatest = true;
const hasPerm = false;
const result = chooseIDE("no-latest", ideOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
expect(result.desktopIdeImage).to.equal(ideOptions.options["no-latest"].image);
});

it("unknown ide with custom permission should be unknown", function () {
const customOptions = Object.assign({}, ideOptions);
customOptions.options["unknown-custom"] = {
title: "unknown title",
type: "browser",
logo: "",
image: "",
};
const useLatest = true;
const hasPerm = true;
const result = chooseIDE("unknown-custom", customOptions, useLatest, hasPerm);
expect(result.ideImage).to.equal("unknown-custom");
});

it("unknown desktop ide with custom permission desktop should be unknown", function () {
const customOptions = Object.assign({}, ideOptions);
customOptions.options["unknown-custom"] = {
title: "unknown title",
type: "desktop",
logo: "",
image: "",
};
const useLatest = true;
const hasPerm = true;
const result = chooseIDE("unknown-custom", customOptions, useLatest, hasPerm);
expect(result.desktopIdeImage).to.equal("unknown-custom");
});

it("unknown browser ide without custom permission should fallback to code", function () {
const customOptions = Object.assign({}, ideOptions);
customOptions.options["unknown-custom"] = {
title: "unknown title",
type: "browser",
logo: "",
image: "",
};
const useLatest = true;
const hasPerm = false;
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);
});
});
});
Loading

0 comments on commit c04d484

Please sign in to comment.