Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/ide/gha-update-image/lib/common.ts
2499 views
1
// Copyright (c) 2024 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
import { $ } from "bun";
6
import path from "path";
7
import yaml from "yaml";
8
import { z } from "zod";
9
10
export const pathToProjectRoot = path.resolve(__dirname, "../../../../");
11
12
const pathToOutput = path.resolve("/tmp/__gh_output.txt");
13
14
export const appendGitHubOutput = async (kv: string) => {
15
console.log("Appending to GitHub output:", kv);
16
return await $`echo ${kv} >> ${pathToOutput}`;
17
};
18
19
// WORKSPACE.yaml
20
export const pathToWorkspaceYaml = path.resolve(pathToProjectRoot, "WORKSPACE.yaml");
21
const workspaceYamlSchema = z.object({
22
defaultArgs: z.object({
23
codeCommit: z.string(),
24
codeVersion: z.string(),
25
codeWebExtensionCommit: z.string(),
26
27
intellijDownloadUrl: z.string(),
28
golandDownloadUrl: z.string(),
29
pycharmDownloadUrl: z.string(),
30
phpstormDownloadUrl: z.string(),
31
rubymineDownloadUrl: z.string(),
32
webstormDownloadUrl: z.string(),
33
riderDownloadUrl: z.string(),
34
clionDownloadUrl: z.string(),
35
rustroverDownloadUrl: z.string(),
36
}),
37
});
38
export type IWorkspaceYaml = z.infer<typeof workspaceYamlSchema>;
39
export const readWorkspaceYaml = async () => {
40
const rawWorkspaceYaml = await Bun.file(pathToWorkspaceYaml).text();
41
const workspaceYamlObj = yaml.parse(rawWorkspaceYaml);
42
const workspaceYaml = workspaceYamlSchema.parse(workspaceYamlObj);
43
return {
44
rawText: rawWorkspaceYaml,
45
rawObj: workspaceYamlObj,
46
parsedObj: workspaceYaml,
47
};
48
};
49
50
// gradle-stable.properties
51
export const pathToBackendPluginGradleStable = path.resolve(
52
pathToProjectRoot,
53
"components/ide/jetbrains/backend-plugin/gradle-stable.properties",
54
);
55
56
// gradle-latest.properties
57
export const pathToBackendPluginGradleLatest = path.resolve(
58
pathToProjectRoot,
59
"components/ide/jetbrains/backend-plugin/gradle-latest.properties",
60
);
61
62
export const pathToBackendPluginDir = path.resolve(pathToProjectRoot, "components/ide/jetbrains/backend-plugin");
63
64
// ide-configmap.json
65
export const pathToConfigmap = path.resolve(
66
pathToProjectRoot,
67
"install/installer/pkg/components/ide-service/ide-configmap.json",
68
);
69
70
const IDEOptionSchema = z.object({
71
image: z.string(),
72
imageLayers: z.array(z.string()),
73
versions: z.array(
74
z.object({
75
version: z.string(),
76
image: z.string(),
77
imageLayers: z.array(z.string()),
78
}),
79
),
80
});
81
const ideConfigmapJsonSchema = z.object({
82
supervisorImage: z.string(),
83
ideOptions: z.object({
84
options: z.object({
85
code: IDEOptionSchema,
86
intellij: IDEOptionSchema,
87
goland: IDEOptionSchema,
88
pycharm: IDEOptionSchema,
89
phpstorm: IDEOptionSchema,
90
rubymine: IDEOptionSchema,
91
webstorm: IDEOptionSchema,
92
rider: IDEOptionSchema,
93
clion: IDEOptionSchema,
94
rustrover: IDEOptionSchema,
95
}),
96
}),
97
});
98
export type IIdeConfigmapJson = z.infer<typeof ideConfigmapJsonSchema>;
99
export const readIDEConfigmapJson = async () => {
100
const ideConfigmapJsonText = await Bun.file(pathToConfigmap).text();
101
const ideConfigmapJsonObj = JSON.parse(ideConfigmapJsonText);
102
const ideConfigmapJson = ideConfigmapJsonSchema.parse(ideConfigmapJsonObj);
103
return {
104
rawText: ideConfigmapJsonText,
105
rawObj: ideConfigmapJsonObj,
106
parsedObj: ideConfigmapJson,
107
};
108
};
109
110
const getInstallerVersion = async (version: string | undefined) => {
111
const v = version ? version : "main-gha.";
112
let tagInfo: string;
113
try {
114
tagInfo =
115
await $`git ls-remote --tags --sort=-v:refname https://github.com/gitpod-io/gitpod | grep ${v} | head -n1`.text();
116
} catch (e) {
117
if (e && e.exitCode === 141 && e.stdout) {
118
tagInfo = String(e.stdout);
119
} else {
120
throw new Error("Failed to fetch the latest main-gha. git tag: " + e.message);
121
}
122
}
123
const installationVersion =
124
await $`echo '${tagInfo}' | awk '{ print $2 }' | grep -o 'main-gha.[0-9]*' | cut -d'/' -f3`
125
.text()
126
.catch((e) => {
127
throw new Error("Failed to parse installer version from git tag: " + e);
128
});
129
return installationVersion.replaceAll("\n", "");
130
};
131
132
// installer versions
133
export const getLatestInstallerVersions = async (version?: string) => {
134
const installationVersion = await getInstallerVersion(version);
135
console.log("Fetching installer versions for", installationVersion);
136
const versionData =
137
await $`docker run --rm eu.gcr.io/gitpod-core-dev/build/versions:${installationVersion} cat /versions.yaml`
138
.text()
139
.catch((e) => {
140
throw new Error("Failed to get installer versions: " + e);
141
});
142
143
const versionObj = z.object({ version: z.string() });
144
return z
145
.object({
146
version: z.string(),
147
commit: z.string(),
148
components: z.object({
149
workspace: z.object({
150
codeImage: versionObj,
151
codeHelperImage: versionObj,
152
codeWebExtensionImage: versionObj,
153
desktopIdeImages: z.object({
154
clion: versionObj,
155
clionLatest: versionObj,
156
codeDesktop: versionObj,
157
codeDesktopInsiders: versionObj,
158
goland: versionObj,
159
golandLatest: versionObj,
160
intellij: versionObj,
161
intellijLatest: versionObj,
162
jbBackendPlugin: versionObj,
163
jbBackendPluginLatest: versionObj,
164
jbBackendPluginRider: versionObj,
165
jbBackendPluginLatestRider: versionObj,
166
jbLauncher: versionObj,
167
phpstorm: versionObj,
168
phpstormLatest: versionObj,
169
pycharm: versionObj,
170
pycharmLatest: versionObj,
171
rider: versionObj,
172
riderLatest: versionObj,
173
rubymine: versionObj,
174
rubymineLatest: versionObj,
175
rustrover: versionObj,
176
rustroverLatest: versionObj,
177
webstorm: versionObj,
178
webstormLatest: versionObj,
179
}),
180
}),
181
}),
182
})
183
.parse(yaml.parse(versionData));
184
};
185
186
export const renderInstallerIDEConfigMap = async (version?: string) => {
187
const installationVersion = await getInstallerVersion(version);
188
await $`docker run --rm -v /tmp:/tmp eu.gcr.io/gitpod-core-dev/build/installer:${installationVersion} config init --overwrite --log-level=error -c /tmp/gitpod.config.yaml`.catch(
189
(e) => {
190
throw new Error("Failed to render gitpod.config.yaml: " + e);
191
},
192
);
193
const ideConfigMapStr =
194
await $`cat /tmp/gitpod.config.yaml | docker run -i --rm eu.gcr.io/gitpod-core-dev/build/installer:${installationVersion} ide-configmap -c -`
195
.text()
196
.catch((e) => {
197
throw new Error(`Failed to render ide-configmap: ` + e);
198
});
199
const ideConfigmapJsonObj = JSON.parse(ideConfigMapStr);
200
const ideConfigmapJson = ideConfigmapJsonSchema.parse(ideConfigmapJsonObj);
201
return ideConfigmapJson;
202
};
203
204
export const getIDEVersionOfImage = async (img: string) => {
205
console.log(
206
"Fetching IDE version in image:",
207
`oci-tool fetch image ${img} | jq -r '.config.Labels["io.gitpod.ide.version"]'`,
208
);
209
const version = await $`oci-tool fetch image ${img} | jq -r '.config.Labels["io.gitpod.ide.version"]'`
210
.text()
211
.catch((e) => {
212
throw new Error("Failed to fetch ide version in image: " + e);
213
})
214
.then((str) => str.replaceAll("\n", ""));
215
console.log("IDE version in image:", version);
216
return version;
217
};
218
219