Skip to content

Commit c04d484

Browse files
committed
t
1 parent 93a68d3 commit c04d484

File tree

3 files changed

+135
-381
lines changed

3 files changed

+135
-381
lines changed

components/server/src/ide-service.ts

Lines changed: 59 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
* See License-AGPL.txt in the project root for license information.
55
*/
66

7-
import { JetBrainsConfig, TaskConfig, Workspace } from "@gitpod/gitpod-protocol";
7+
import { IDESettings, TaskConfig, User, Workspace } from "@gitpod/gitpod-protocol";
88
import { IDEOptions, IDEClient } from "@gitpod/gitpod-protocol/lib/ide-protocol";
9-
import { IDEServiceClient, IDEServiceDefinition } from "@gitpod/ide-service-api/lib/ide.pb";
9+
import {
10+
IDEServiceClient,
11+
IDEServiceDefinition,
12+
ResolveWorkspaceConfigRequest,
13+
ResolveWorkspaceConfigResponse,
14+
} from "@gitpod/ide-service-api/lib/ide.pb";
1015
import { inject, injectable } from "inversify";
1116

1217
export interface IDEConfig {
@@ -37,85 +42,62 @@ export class IDEService {
3742
}
3843
}
3944

40-
resolveGitpodTasks(ws: Workspace): TaskConfig[] {
41-
const tasks: TaskConfig[] = [];
42-
if (ws.config.tasks) {
43-
tasks.push(...ws.config.tasks);
45+
migrateSettings(user: User): IDESettings | undefined {
46+
if (!user?.additionalData?.ideSettings || user.additionalData.ideSettings.settingVersion === "2.0") {
47+
return undefined;
4448
}
45-
// 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
46-
if (ws.type === "prebuild" && ws.config.jetbrains) {
47-
let warmUp = "";
48-
for (const key in ws.config.jetbrains) {
49-
let productCode;
50-
if (key === "intellij") {
51-
productCode = "IIU";
52-
} else if (key === "goland") {
53-
productCode = "GO";
54-
} else if (key === "pycharm") {
55-
productCode = "PCP";
56-
} else if (key === "phpstorm") {
57-
productCode = "PS";
58-
} else if (key === "rubymine") {
59-
productCode = "RM";
60-
} else if (key === "webstorm") {
61-
productCode = "WS";
62-
} else if (key === "rider") {
63-
productCode = "RD";
64-
} else if (key === "clion") {
65-
productCode = "CL";
66-
}
67-
const prebuilds = productCode && ws.config.jetbrains[key as keyof JetBrainsConfig]?.prebuilds;
68-
if (prebuilds) {
69-
warmUp +=
70-
prebuilds.version === "latest"
71-
? ""
72-
: `
73-
echo 'warming up stable release of ${key}...'
74-
echo 'downloading stable ${key} backend...'
75-
mkdir /tmp/backend
76-
curl -sSLo /tmp/backend/backend.tar.gz "https://download.jetbrains.com/product?type=release&distribution=linux&code=${productCode}"
77-
tar -xf /tmp/backend/backend.tar.gz --strip-components=1 --directory /tmp/backend
78-
79-
echo 'configuring JB system config and caches aligned with runtime...'
80-
printf '\nshared.indexes.download.auto.consent=true' >> "/tmp/backend/bin/idea.properties"
81-
unset JAVA_TOOL_OPTIONS
82-
export IJ_HOST_CONFIG_BASE_DIR=/workspace/.config/JetBrains
83-
export IJ_HOST_SYSTEM_BASE_DIR=/workspace/.cache/JetBrains
84-
85-
echo 'running stable ${key} backend in warmup mode...'
86-
/tmp/backend/bin/remote-dev-server.sh warmup "$GITPOD_REPO_ROOT"
87-
88-
echo 'removing stable ${key} backend...'
89-
rm -rf /tmp/backend
90-
`;
91-
warmUp +=
92-
prebuilds.version === "stable"
93-
? ""
94-
: `
95-
echo 'warming up latest release of ${key}...'
96-
echo 'downloading latest ${key} backend...'
97-
mkdir /tmp/backend-latest
98-
curl -sSLo /tmp/backend-latest/backend-latest.tar.gz "https://download.jetbrains.com/product?type=release,eap,rc&distribution=linux&code=${productCode}"
99-
tar -xf /tmp/backend-latest/backend-latest.tar.gz --strip-components=1 --directory /tmp/backend-latest
100-
101-
echo 'configuring JB system config and caches aligned with runtime...'
102-
printf '\nshared.indexes.download.auto.consent=true' >> "/tmp/backend-latest/bin/idea.properties"
103-
unset JAVA_TOOL_OPTIONS
104-
export IJ_HOST_CONFIG_BASE_DIR=/workspace/.config/JetBrains-latest
105-
export IJ_HOST_SYSTEM_BASE_DIR=/workspace/.cache/JetBrains-latest
106-
107-
echo 'running ${key} backend in warmup mode...'
108-
/tmp/backend-latest/bin/remote-dev-server.sh warmup "$GITPOD_REPO_ROOT"
49+
const newIDESettings: IDESettings = {
50+
settingVersion: "2.0",
51+
};
52+
const ideSettings = user.additionalData.ideSettings;
53+
if (ideSettings.useDesktopIde) {
54+
if (ideSettings.defaultDesktopIde === "code-desktop") {
55+
newIDESettings.defaultIde = "code-desktop";
56+
} else if (ideSettings.defaultDesktopIde === "code-desktop-insiders") {
57+
newIDESettings.defaultIde = "code-desktop";
58+
newIDESettings.useLatestVersion = true;
59+
} else {
60+
newIDESettings.defaultIde = ideSettings.defaultDesktopIde;
61+
newIDESettings.useLatestVersion = ideSettings.useLatestVersion;
62+
}
63+
} else {
64+
const useLatest = ideSettings.defaultIde === "code-latest";
65+
newIDESettings.defaultIde = "code";
66+
newIDESettings.useLatestVersion = useLatest;
67+
}
68+
return newIDESettings;
69+
}
10970

110-
echo 'removing latest ${key} backend...'
111-
rm -rf /tmp/backend-latest
112-
`;
113-
}
71+
async resolveWorkspaceConfig(req: ResolveWorkspaceConfigRequest): Promise<ResolveWorkspaceConfigResponse> {
72+
for (let attempt = 0; attempt < 15; attempt++) {
73+
if (attempt != 0) {
74+
await new Promise((resolve) => setTimeout(resolve, 1000));
11475
}
115-
if (warmUp) {
116-
tasks.push({
117-
init: warmUp.trim(),
76+
const controller = new AbortController();
77+
setTimeout(() => controller.abort(), 1000);
78+
try {
79+
const resp = await this.ideService.resolveWorkspaceConfig(req, {
80+
signal: controller.signal,
11881
});
82+
return resp;
83+
} catch (e) {
84+
console.error("ide-service: failed to resolve workspace config: ", e);
85+
}
86+
}
87+
throw new Error("failed to resolve workspace IDE configuration");
88+
}
89+
90+
resolveGitpodTasks(ws: Workspace, ideConfig: ResolveWorkspaceConfigResponse): TaskConfig[] {
91+
const tasks: TaskConfig[] = [];
92+
if (ws.config.tasks) {
93+
tasks.push(...ws.config.tasks);
94+
}
95+
if (ideConfig.tasks) {
96+
try {
97+
let ideTasks: TaskConfig[] = JSON.parse(ideConfig.tasks);
98+
tasks.push(...ideTasks);
99+
} catch (e) {
100+
console.error("failed get tasks from ide config:", e);
119101
}
120102
}
121103
return tasks;

components/server/src/workspace/workspace-starter.spec.ts

Lines changed: 12 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@
55
*/
66

77
import { User } from "@gitpod/gitpod-protocol";
8-
import { IDEOption, IDEOptions } from "@gitpod/gitpod-protocol/lib/ide-protocol";
98
import * as chai from "chai";
10-
import { migrationIDESettings, chooseIDE } from "./workspace-starter";
9+
import { IDEService } from "../ide-service";
1110
const expect = chai.expect;
1211

13-
describe("workspace-starter", function () {
14-
describe("migrationIDESettings", function () {
12+
describe("ide-service", function () {
13+
describe("ideService.migrateSettings", function () {
14+
const ideService = new IDEService();
1515
it("with no ideSettings should be undefined", function () {
1616
const user: User = {
1717
id: "string",
1818
creationDate: "string",
1919
identities: [],
2020
additionalData: {},
2121
};
22-
const result = migrationIDESettings(user);
22+
const result = ideService.migrateSettings(user);
2323
expect(result).to.undefined;
2424
});
2525

@@ -36,7 +36,7 @@ describe("workspace-starter", function () {
3636
},
3737
},
3838
};
39-
const result = migrationIDESettings(user);
39+
const result = ideService.migrateSettings(user);
4040
expect(result).to.undefined;
4141
});
4242

@@ -52,7 +52,7 @@ describe("workspace-starter", function () {
5252
},
5353
},
5454
};
55-
const result = migrationIDESettings(user);
55+
const result = ideService.migrateSettings(user);
5656
expect(result?.defaultIde).to.equal("code");
5757
expect(result?.useLatestVersion ?? false).to.be.true;
5858
});
@@ -70,7 +70,7 @@ describe("workspace-starter", function () {
7070
},
7171
},
7272
};
73-
const result = migrationIDESettings(user);
73+
const result = ideService.migrateSettings(user);
7474
expect(result?.defaultIde).to.equal("code-desktop");
7575
expect(result?.useLatestVersion ?? false).to.be.true;
7676
});
@@ -88,7 +88,7 @@ describe("workspace-starter", function () {
8888
},
8989
},
9090
};
91-
const result = migrationIDESettings(user);
91+
const result = ideService.migrateSettings(user);
9292
expect(result?.defaultIde).to.equal("code-desktop");
9393
expect(result?.useLatestVersion ?? false).to.be.false;
9494
});
@@ -107,7 +107,7 @@ describe("workspace-starter", function () {
107107
},
108108
},
109109
};
110-
const result = migrationIDESettings(user);
110+
const result = ideService.migrateSettings(user);
111111
expect(result?.defaultIde).to.equal("intellij");
112112
expect(result?.useLatestVersion ?? false).to.be.false;
113113
});
@@ -126,7 +126,7 @@ describe("workspace-starter", function () {
126126
},
127127
},
128128
};
129-
const result = migrationIDESettings(user);
129+
const result = ideService.migrateSettings(user);
130130
expect(result?.defaultIde).to.equal("intellij");
131131
expect(result?.useLatestVersion ?? false).to.be.true;
132132
});
@@ -145,123 +145,9 @@ describe("workspace-starter", function () {
145145
},
146146
},
147147
};
148-
const result = migrationIDESettings(user);
148+
const result = ideService.migrateSettings(user);
149149
expect(result?.defaultIde).to.equal("code");
150150
expect(result?.useLatestVersion ?? false).to.be.true;
151151
});
152152
});
153-
describe("chooseIDE", async function () {
154-
const baseOpt: IDEOption = {
155-
title: "title",
156-
type: "desktop",
157-
logo: "",
158-
image: "image",
159-
latestImage: "latestImage",
160-
};
161-
const ideOptions: IDEOptions = {
162-
options: {
163-
code: Object.assign({}, baseOpt, { type: "browser" }),
164-
goland: Object.assign({}, baseOpt),
165-
"code-desktop": Object.assign({}, baseOpt),
166-
"no-latest": Object.assign({}, baseOpt),
167-
},
168-
defaultIde: "code",
169-
defaultDesktopIde: "code-desktop",
170-
};
171-
delete ideOptions.options["no-latest"].latestImage;
172-
173-
it("code with latest", function () {
174-
const useLatest = true;
175-
const hasPerm = false;
176-
const result = chooseIDE("code", ideOptions, useLatest, hasPerm);
177-
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
178-
});
179-
180-
it("code without latest", function () {
181-
const useLatest = false;
182-
const hasPerm = false;
183-
const result = chooseIDE("code", ideOptions, useLatest, hasPerm);
184-
expect(result.ideImage).to.equal(ideOptions.options["code"].image);
185-
});
186-
187-
it("desktop ide with latest", function () {
188-
const useLatest = true;
189-
const hasPerm = false;
190-
const result = chooseIDE("code-desktop", ideOptions, useLatest, hasPerm);
191-
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
192-
expect(result.desktopIdeImage).to.equal(ideOptions.options["code-desktop"].latestImage);
193-
});
194-
195-
it("desktop ide (JetBrains) without latest", function () {
196-
const useLatest = false;
197-
const hasPerm = false;
198-
const result = chooseIDE("goland", ideOptions, useLatest, hasPerm);
199-
expect(result.ideImage).to.equal(ideOptions.options["code"].image);
200-
expect(result.desktopIdeImage).to.equal(ideOptions.options["goland"].image);
201-
});
202-
203-
it("desktop ide with no latest image", function () {
204-
const useLatest = true;
205-
const hasPerm = false;
206-
const result = chooseIDE("no-latest", ideOptions, useLatest, hasPerm);
207-
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
208-
expect(result.desktopIdeImage).to.equal(ideOptions.options["no-latest"].image);
209-
});
210-
211-
it("unknown ide with custom permission should be unknown", function () {
212-
const customOptions = Object.assign({}, ideOptions);
213-
customOptions.options["unknown-custom"] = {
214-
title: "unknown title",
215-
type: "browser",
216-
logo: "",
217-
image: "",
218-
};
219-
const useLatest = true;
220-
const hasPerm = true;
221-
const result = chooseIDE("unknown-custom", customOptions, useLatest, hasPerm);
222-
expect(result.ideImage).to.equal("unknown-custom");
223-
});
224-
225-
it("unknown desktop ide with custom permission desktop should be unknown", function () {
226-
const customOptions = Object.assign({}, ideOptions);
227-
customOptions.options["unknown-custom"] = {
228-
title: "unknown title",
229-
type: "desktop",
230-
logo: "",
231-
image: "",
232-
};
233-
const useLatest = true;
234-
const hasPerm = true;
235-
const result = chooseIDE("unknown-custom", customOptions, useLatest, hasPerm);
236-
expect(result.desktopIdeImage).to.equal("unknown-custom");
237-
});
238-
239-
it("unknown browser ide without custom permission should fallback to code", function () {
240-
const customOptions = Object.assign({}, ideOptions);
241-
customOptions.options["unknown-custom"] = {
242-
title: "unknown title",
243-
type: "browser",
244-
logo: "",
245-
image: "",
246-
};
247-
const useLatest = true;
248-
const hasPerm = false;
249-
const result = chooseIDE("unknown-custom", customOptions, useLatest, hasPerm);
250-
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
251-
});
252-
253-
it("not exists ide with custom permission", function () {
254-
const useLatest = true;
255-
const hasPerm = true;
256-
const result = chooseIDE("not-exists", ideOptions, useLatest, hasPerm);
257-
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
258-
});
259-
260-
it("not exists ide with custom permission", function () {
261-
const useLatest = true;
262-
const hasPerm = false;
263-
const result = chooseIDE("not-exists", ideOptions, useLatest, hasPerm);
264-
expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage);
265-
});
266-
});
267153
});

0 commit comments

Comments
 (0)