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