Skip to content

Commit 4113cd3

Browse files
committed
[jb] experimental support of warm up in prebuilds
1 parent c1d7453 commit 4113cd3

File tree

7 files changed

+187
-3
lines changed

7 files changed

+187
-3
lines changed

components/gitpod-protocol/data/gitpod-schema.json

+64
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,22 @@
271271
"items": {
272272
"type": "string"
273273
}
274+
},
275+
"prebuilds": {
276+
"type": "object",
277+
"description": "Enable warming up of IntelliJ in prebuilds.",
278+
"additionalProperties": false,
279+
"properties": {
280+
"version": {
281+
"type": "string",
282+
"enum": [
283+
"stable",
284+
"latest",
285+
"both"
286+
],
287+
"description": "Whether only stable, latest or both versions should be warmed up. Default is stable only."
288+
}
289+
}
274290
}
275291
}
276292
},
@@ -285,6 +301,22 @@
285301
"items": {
286302
"type": "string"
287303
}
304+
},
305+
"prebuilds": {
306+
"type": "object",
307+
"description": "Enable warming up of GoLand in prebuilds.",
308+
"additionalProperties": false,
309+
"properties": {
310+
"version": {
311+
"type": "string",
312+
"enum": [
313+
"stable",
314+
"latest",
315+
"both"
316+
],
317+
"description": "Whether only stable, latest or both versions should be warmed up. Default is stable only."
318+
}
319+
}
288320
}
289321
}
290322
},
@@ -299,6 +331,22 @@
299331
"items": {
300332
"type": "string"
301333
}
334+
},
335+
"prebuilds": {
336+
"type": "object",
337+
"description": "Enable warming up of PyCharm in prebuilds.",
338+
"additionalProperties": false,
339+
"properties": {
340+
"version": {
341+
"type": "string",
342+
"enum": [
343+
"stable",
344+
"latest",
345+
"both"
346+
],
347+
"description": "Whether only stable, latest or both versions should be warmed up. Default is stable only."
348+
}
349+
}
302350
}
303351
}
304352
},
@@ -313,6 +361,22 @@
313361
"items": {
314362
"type": "string"
315363
}
364+
},
365+
"prebuilds": {
366+
"type": "object",
367+
"description": "Enable warming up of PhpStorm in prebuilds.",
368+
"additionalProperties": false,
369+
"properties": {
370+
"version": {
371+
"type": "string",
372+
"enum": [
373+
"stable",
374+
"latest",
375+
"both"
376+
],
377+
"description": "Whether only stable, latest or both versions should be warmed up. Default is stable only."
378+
}
379+
}
316380
}
317381
}
318382
}

components/gitpod-protocol/go/gitpod-config-types.go

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/gitpod-protocol/src/protocol.ts

+14
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,19 @@ export interface VSCodeConfig {
539539
extensions?: string[];
540540
}
541541

542+
export interface JetBrainsConfig {
543+
intellij?: JetBrainsProductConfig;
544+
goland?: JetBrainsProductConfig;
545+
pycharm?: JetBrainsProductConfig;
546+
phpstorm?: JetBrainsProductConfig;
547+
}
548+
export interface JetBrainsProductConfig {
549+
prebuilds?: JetBrainsPrebuilds;
550+
}
551+
export interface JetBrainsPrebuilds {
552+
version?: "stable" | "latest" | "both";
553+
}
554+
542555
export interface RepositoryCloneInformation {
543556
url: string;
544557
checkoutLocation?: string;
@@ -555,6 +568,7 @@ export interface WorkspaceConfig {
555568
gitConfig?: { [config: string]: string };
556569
github?: GithubAppConfig;
557570
vscode?: VSCodeConfig;
571+
jetbrains?: JetBrainsConfig;
558572

559573
/** deprecated. Enabled by default **/
560574
experimentalNetwork?: boolean;

components/gitpod-protocol/src/workspace-instance.ts

+1
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ export interface WorkspaceInstanceRepoStatus {
207207
// ConfigurationIdeConfig ide config of WorkspaceInstanceConfiguration
208208
export interface ConfigurationIdeConfig {
209209
useLatest?: boolean;
210+
desktopIdeAlias?: string;
210211
}
211212

212213
// WorkspaceInstanceConfiguration contains all per-instance configuration

components/server/src/container-module.ts

+2
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,12 @@ import { LocalMessageBroker, LocalRabbitMQBackedMessageBroker } from "./messagin
9797
import { contentServiceBinder } from "@gitpod/content-service/lib/sugar";
9898
import { ReferrerPrefixParser } from "./workspace/referrer-prefix-context-parser";
9999
import { InstallationAdminTelemetryDataProvider } from "./installation-admin/telemetry-data-provider";
100+
import { IDEService } from "./ide-service";
100101

101102
export const productionContainerModule = new ContainerModule((bind, unbind, isBound, rebind) => {
102103
bind(Config).toConstantValue(ConfigFile.fromFile());
103104
bind(IDEConfigService).toSelf().inSingletonScope();
105+
bind(IDEService).toSelf().inSingletonScope();
104106

105107
bind(UserService).toSelf().inSingletonScope();
106108
bind(UserDeletionService).toSelf().inSingletonScope();

components/server/src/ide-service.ts

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License-AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { JetBrainsConfig, TaskConfig, Workspace } from "@gitpod/gitpod-protocol";
8+
import { injectable } from "inversify";
9+
10+
@injectable()
11+
export class IDEService {
12+
resolveGitpodTasks(ws: Workspace): TaskConfig[] {
13+
const tasks: TaskConfig[] = [];
14+
if (ws.config.tasks) {
15+
tasks.push(...ws.config.tasks);
16+
}
17+
// 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
18+
if (ws.type === "prebuild" && ws.config.jetbrains) {
19+
let warmUp = "";
20+
for (const key in ws.config.jetbrains) {
21+
let productCode;
22+
if (key === "intellij") {
23+
productCode = "IIU";
24+
} else if (key === "goland") {
25+
productCode = "GO";
26+
} else if (key === "pycharm") {
27+
productCode = "PCP";
28+
} else if (key === "phpstorm") {
29+
productCode = "PS";
30+
}
31+
const prebuilds = productCode && ws.config.jetbrains[key as keyof JetBrainsConfig]?.prebuilds;
32+
if (prebuilds) {
33+
warmUp +=
34+
prebuilds.version === "latest"
35+
? ""
36+
: `
37+
echo 'warming up stable release of ${key}...'
38+
echo 'downloading stable ${key} backend...'
39+
mkdir /tmp/backend && cd /tmp/backend || exit 1
40+
curl -sSLo backend.tar.gz "https://download.jetbrains.com/product?type=release&distribution=linux&code=${productCode}" && tar -xf backend.tar.gz --strip-components=1 && rm backend.tar.gz
41+
42+
echo 'configuring JB system config and caches aligned with runtime...'
43+
printf '\nshared.indexes.download.auto.consent=true' >> "/tmp/backend/bin/idea.properties"
44+
unset JAVA_TOOL_OPTIONS
45+
export IJ_HOST_CONFIG_BASE_DIR=/workspace/.config/JetBrains
46+
export IJ_HOST_SYSTEM_BASE_DIR=/workspace/.cache/JetBrains
47+
48+
echo 'running stable ${key} backend in warmup mode...'
49+
/tmp/backend/bin/remote-dev-server.sh warmup "$GITPOD_REPO_ROOT"
50+
51+
echo 'removing stable ${key} backend...'
52+
rm -rf /tmp/backend
53+
`;
54+
warmUp +=
55+
prebuilds.version === "stable"
56+
? ""
57+
: `
58+
echo 'warming up latest release of ${key}...'
59+
echo 'downloading latest ${key} backend...'
60+
mkdir /tmp/backend-latest && cd /tmp/backend-latest || exit 1
61+
curl -sSLo backend-latest.tar.gz "https://download.jetbrains.com/product?type=release,eap,rc&distribution=linux&code=${productCode}" && tar -xf backend-latest.tar.gz --strip-components=1 && rm backend-latest.tar.gz
62+
63+
echo 'configuring JB system config and caches aligned with runtime...'
64+
printf '\nshared.indexes.download.auto.consent=true' >> "/tmp/backend-latest/bin/idea.properties"
65+
unset JAVA_TOOL_OPTIONS
66+
export IJ_HOST_CONFIG_BASE_DIR=/workspace/.config/JetBrains-latest
67+
export IJ_HOST_SYSTEM_BASE_DIR=/workspace/.cache/JetBrains-latest
68+
69+
echo 'running ${key} backend in warmup mode...'
70+
/tmp/backend-latest/bin/remote-dev-server.sh warmup "$GITPOD_REPO_ROOT"
71+
72+
echo 'removing latest ${key} backend...'
73+
rm -rf /tmp/backend-latest
74+
`;
75+
}
76+
}
77+
if (warmUp) {
78+
tasks.push({
79+
init: `|${warmUp}`,
80+
});
81+
}
82+
}
83+
return tasks;
84+
}
85+
}

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

+11-3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import { Deferred } from "@gitpod/gitpod-protocol/lib/util/deferred";
109109
import { ExtendedUser } from "@gitpod/ws-manager/lib/constraints";
110110
import { increaseFailedInstanceStartCounter, increaseSuccessfulInstanceStartCounter } from "../prometheus-metrics";
111111
import { ContextParser } from "./context-parser-service";
112+
import { IDEService } from "../ide-service";
112113

113114
export interface StartWorkspaceOptions {
114115
rethrow?: boolean;
@@ -119,6 +120,7 @@ export interface StartWorkspaceOptions {
119120
const MAX_INSTANCE_START_RETRIES = 2;
120121
const INSTANCE_START_RETRY_INTERVAL_SECONDS = 2;
121122

123+
// TODO(ak) move to IDE service
122124
export const migrationIDESettings = (user: User) => {
123125
if (!user?.additionalData?.ideSettings || user.additionalData.ideSettings.settingVersion === "2.0") {
124126
return;
@@ -145,6 +147,7 @@ export const migrationIDESettings = (user: User) => {
145147
return newIDESettings;
146148
};
147149

150+
// TODO(ak) move to IDE service
148151
export const chooseIDE = (
149152
ideChoice: string,
150153
ideOptions: IDEOptions,
@@ -181,6 +184,7 @@ export class WorkspaceStarter {
181184
@inject(WorkspaceManagerClientProvider) protected readonly clientProvider: WorkspaceManagerClientProvider;
182185
@inject(Config) protected readonly config: Config;
183186
@inject(IDEConfigService) private readonly ideConfigService: IDEConfigService;
187+
@inject(IDEService) private readonly ideService: IDEService;
184188
@inject(TracedWorkspaceDB) protected readonly workspaceDb: DBWithTracing<WorkspaceDB>;
185189
@inject(TracedUserDB) protected readonly userDB: DBWithTracing<UserDB>;
186190
@inject(TokenProvider) protected readonly tokenProvider: TokenProvider;
@@ -598,6 +602,7 @@ export class WorkspaceStarter {
598602
excludeFeatureFlags: NamedWorkspaceFeatureFlag[],
599603
ideConfig: IDEConfig,
600604
): Promise<WorkspaceInstance> {
605+
//#endregion IDE resolution TODO(ak) move to IDE service
601606
// TODO: Compatible with ide-config not deployed, need revert after ide-config deployed
602607
delete ideConfig.ideOptions.options["code-latest"];
603608
delete ideConfig.ideOptions.options["code-desktop-insiders"];
@@ -654,6 +659,7 @@ export class WorkspaceStarter {
654659
});
655660
}
656661
}
662+
//#endregion
657663

658664
let featureFlags: NamedWorkspaceFeatureFlag[] = workspace.config._featureFlags || [];
659665
featureFlags = featureFlags.concat(this.config.workspaceDefaults.defaultFeatureFlags);
@@ -706,6 +712,7 @@ export class WorkspaceStarter {
706712
return instance;
707713
}
708714

715+
// TODO(ak) move to IDE service
709716
protected resolveReferrerIDE(
710717
workspace: Workspace,
711718
user: User,
@@ -1129,12 +1136,13 @@ export class WorkspaceStarter {
11291136
envvars.push(contextEnv);
11301137

11311138
log.debug("Workspace config", workspace.config);
1132-
if (!!workspace.config.tasks) {
1133-
// The task config is interpreted by Theia only, there's little point in transforming it into something
1139+
const tasks = this.ideService.resolveGitpodTasks(workspace);
1140+
if (tasks.length) {
1141+
// The task config is interpreted by supervisor only, there's little point in transforming it into something
11341142
// wsman understands and back into the very same structure.
11351143
const ev = new EnvironmentVariable();
11361144
ev.setName("GITPOD_TASKS");
1137-
ev.setValue(JSON.stringify(workspace.config.tasks));
1145+
ev.setValue(JSON.stringify(tasks));
11381146
envvars.push(ev);
11391147
}
11401148

0 commit comments

Comments
 (0)