Skip to content

allow to layout multiple JB product layers in the same image #15182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 9 additions & 16 deletions .github/workflows/jetbrains-auto-update-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,25 @@ jobs:
uses: google-github-actions/setup-gcloud@v0
with:
project_id: ${{ secrets.projectId }}
- name: Get Platform Version from JetBrains EAP Backend Plugin
id: platform-version
run: |
PLATFORM_VERSION=$(cat ./components/ide/jetbrains/backend-plugin/gradle-latest.properties | grep platformVersion= | sed 's/platformVersion=//' | sed 's/-EAP-CANDIDATE-SNAPSHOT//')
echo "::set-output name=result::$PLATFORM_VERSION"
echo $PLATFORM_VERSION
- name: Find IDE version to download
id: ide-version
run: |
curl -sL "https://data.services.jetbrains.com/products/releases?code=${{ inputs.productCode }}&type=eap,rc,release&platform=linux" > releases.json
IDE_VERSION=$(cat releases.json | jq -r -c 'first(.${{ inputs.productCode }}[] | select(.build | contains("${{ steps.platform-version.outputs.result }}")) | .build)')
IDE_BACKEND_VERSION=$(cat releases.json | jq -r '.${{ inputs.productCode }}[0].version')
rm releases.json
echo "::set-output name=result::$IDE_VERSION"
echo "::set-output name=ideBackendVersion::$IDE_BACKEND_VERSION"
echo $IDE_VERSION
echo $IDE_BACKEND_VERSION
IDE_VERSIONS_JSON=$(bash ./components/ide/jetbrains/image/resolve-latest-ide-version.sh ${{ inputs.productCode }})
IDE_BUILD_VERSION=$(echo "$IDE_VERSIONS_JSON" | jq -r .IDE_BUILD_VERSION)
IDE_VERSION=$(echo "$IDE_VERSIONS_JSON" | jq -r .IDE_VERSION)
echo "IDE_BUILD_VERSION: $IDE_BUILD_VERSION"
echo "IDE_VERSION: $IDE_VERSION"
echo "::set-output name=ideBuildVersion::$IDE_BUILD_VERSION"
echo "::set-output name=ideVersion::$IDE_VERSION"
- name: Leeway build
if: ${{ steps.ide-version.outputs.result }}
if: ${{ steps.ide-version.outputs.ideBuildVersion }}
env:
LEEWAY_MAX_PROVENANCE_BUNDLE_SIZE: "8388608"
run: |
gcloud auth configure-docker --quiet
export LEEWAY_WORKSPACE_ROOT=$(pwd)
cd components/ide/jetbrains/image
leeway build -Dversion=latest -DimageRepoBase=eu.gcr.io/gitpod-core-dev/build -DbuildNumber=${{ steps.ide-version.outputs.result }} .:${{ inputs.productId }}-latest -DjbBackendVersion=${{ steps.ide-version.outputs.ideBackendVersion }}
leeway build -Dversion=latest -DimageRepoBase=eu.gcr.io/gitpod-core-dev/build -DbuildNumber=${{ steps.ide-version.outputs.ideBuildVersion }} .:${{ inputs.productId }}-latest -DjbBackendVersion=${{ steps.ide-version.outputs.ideVersion }}
- name: Get previous job's status
id: lastrun
uses: filiptronicek/get-last-job-status@main
Expand Down
3 changes: 3 additions & 0 deletions components/ide/jetbrains/backend-plugin/leeway.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ FROM scratch
ARG JETBRAINS_BACKEND_QUALIFIER
# ensures right permissions for /ide-desktop-plugins
COPY --from=base_builder --chown=33333:33333 /ide-desktop-plugins/ /ide-desktop-plugins/
COPY --chown=33333:33333 components-ide-jetbrains-backend-plugin--plugin-${JETBRAINS_BACKEND_QUALIFIER}/build/gitpod-remote /ide-desktop-plugins/gitpod-remote-${JETBRAINS_BACKEND_QUALIFIER}/

# added for backwards compatibility, can be removed in the future
COPY --chown=33333:33333 components-ide-jetbrains-backend-plugin--plugin-${JETBRAINS_BACKEND_QUALIFIER}/build/gitpod-remote /ide-desktop-plugins/gitpod-remote/
1 change: 1 addition & 0 deletions components/ide/jetbrains/cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func Execute() {

func getCliApiUrl() *url.URL {
var backendPort = 63342
// TODO look up under alias + qualifier, i.e. intellij or intellij-latest
if _, fileStatError := os.Stat("/ide-desktop/bin/idea-cli-dev"); !errors.Is(fileStatError, os.ErrNotExist) {
backendPort = backendPort + 1
}
Expand Down
4 changes: 2 additions & 2 deletions components/ide/jetbrains/image/BUILD.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const generateIDEBuildPackage = function (ideConfig, qualifier) {
let pkg = {
name,
type: "docker",
srcs: ["startup.sh", `supervisor-ide-config_${ideConfig.name}.json`],
srcs: ["startup.sh", `supervisor-ide-config_${name}.json`],
deps: ["components/ide/jetbrains/image/status:app", `:download-${name}`, "components/ide/jetbrains/cli:app"],
config: {
dockerfile: "leeway.Dockerfile",
Expand All @@ -63,7 +63,7 @@ const generateIDEBuildPackage = function (ideConfig, qualifier) {
},
buildArgs: {
JETBRAINS_DOWNLOAD_QUALIFIER: name,
SUPERVISOR_IDE_CONFIG: `supervisor-ide-config_${ideConfig.name}.json`,
SUPERVISOR_IDE_CONFIG: `supervisor-ide-config_${name}.json`,
JETBRAINS_BACKEND_QUALIFIER: qualifier,
JETBRAINS_BACKEND_VERSION: getIDEVersion(qualifier, args[`${ideConfig.name}DownloadUrl`]),
},
Expand Down
58 changes: 58 additions & 0 deletions components/ide/jetbrains/image/create-supervisor-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.

// @ts-check
const fs = require("fs");

const ideConfigs = [
{
name: "intellij",
displayName: "IntelliJ IDEA",
},
{
name: "goland",
displayName: "GoLand",
},
{
name: "pycharm",
displayName: "PyCharm",
},
{
name: "phpstorm",
displayName: "PhpStorm",
},
{
name: "rubymine",
displayName: "RubyMine",
},
{
name: "webstorm",
displayName: "WebStorm",
},
{
name: "rider",
displayName: "Rider",
},
{
name: "clion",
displayName: "CLion",
},
];

["stable", "latest"].forEach((qualifier) => {
ideConfigs.forEach((ideConfig) => {
const name = ideConfig.name + (qualifier === "stable" ? "" : "-" + qualifier);
const template = {
entrypoint: `/ide-desktop/${name}/status`,
entrypointArgs: ["{DESKTOPIDEPORT}", ideConfig.name, `Open in ${ideConfig.displayName}`],
readinessProbe: {
type: "http",
http: {
path: "/status",
},
},
};
fs.writeFileSync(`supervisor-ide-config_${name}.json`, JSON.stringify(template, null, 2), "utf-8");
});
});
8 changes: 7 additions & 1 deletion components/ide/jetbrains/image/hot-deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ echo "Product: $product"
qualifier=${2:-latest}
echo "Qualifier: $qualifier"

product_code=${3}
echo "Product Code: $product_code"

if [ "$qualifier" == "stable" ]; then
component=$product
else
Expand All @@ -31,7 +34,10 @@ echo "Image Version: $version"
bldfn="/tmp/build-$version.tar.gz"

docker ps &> /dev/null || (echo "You need a working Docker daemon. Maybe set DOCKER_HOST?"; exit 1)
leeway build -Dversion="$version" -DimageRepoBase=eu.gcr.io/gitpod-core-dev/build ".:$component" --save "$bldfn"
IDE_VERSIONS_JSON=$(bash "$ROOT_DIR/components/ide/jetbrains/image/resolve-latest-ide-version.sh" "$product_code")
IDE_BUILD_VERSION=$(echo "$IDE_VERSIONS_JSON" | jq -r .IDE_BUILD_VERSION)
IDE_VERSION=$(echo "$IDE_VERSIONS_JSON" | jq -r .IDE_VERSION)
leeway build -Dversion="$version" -DimageRepoBase=eu.gcr.io/gitpod-core-dev/build -DbuildNumber="$IDE_BUILD_VERSION" -DjbBackendVersion="$IDE_VERSION" ".:$component" --save "$bldfn"
dev_image="$(tar xfO "$bldfn" ./imgnames.txt | head -n1)"
echo "Dev Image: $dev_image"

Expand Down
14 changes: 7 additions & 7 deletions components/ide/jetbrains/image/leeway.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ ARG SUPERVISOR_IDE_CONFIG
# ensures right permissions for /ide-desktop
COPY --from=base_builder --chown=33333:33333 /ide-desktop/ /ide-desktop/
COPY --chown=33333:33333 ${SUPERVISOR_IDE_CONFIG} /ide-desktop/supervisor-ide-config.json
COPY --chown=33333:33333 components-ide-jetbrains-image--download-${JETBRAINS_DOWNLOAD_QUALIFIER}/backend /ide-desktop/backend
COPY --chown=33333:33333 components-ide-jetbrains-image-status--app/status /ide-desktop
COPY --chown=33333:33333 components-ide-jetbrains-image--download-${JETBRAINS_DOWNLOAD_QUALIFIER}/backend /ide-desktop/${JETBRAINS_DOWNLOAD_QUALIFIER}/backend
COPY --chown=33333:33333 components-ide-jetbrains-image-status--app/status /ide-desktop/${JETBRAINS_DOWNLOAD_QUALIFIER}

ARG JETBRAINS_BACKEND_QUALIFIER
ENV GITPOD_ENV_SET_JETBRAINS_BACKEND_QUALIFIER ${JETBRAINS_BACKEND_QUALIFIER}

COPY --chown=33333:33333 components-ide-jetbrains-cli--app/cli /ide-desktop/bin/idea-cli
ENV GITPOD_ENV_APPEND_PATH /ide-desktop/bin:
COPY --chown=33333:33333 components-ide-jetbrains-cli--app/cli /ide-desktop/${JETBRAINS_DOWNLOAD_QUALIFIER}/bin/idea-cli
ENV GITPOD_ENV_APPEND_PATH /ide-desktop/${JETBRAINS_DOWNLOAD_QUALIFIER}/bin:

# editor config
ENV GITPOD_ENV_SET_EDITOR "/ide-desktop/bin/idea-cli open"
ENV GITPOD_ENV_SET_EDITOR "/ide-desktop/${JETBRAINS_DOWNLOAD_QUALIFIER}/bin/idea-cli open"
ENV GITPOD_ENV_SET_VISUAL "$GITPOD_ENV_SET_EDITOR"
ENV GITPOD_ENV_SET_GP_OPEN_EDITOR "$GITPOD_ENV_SET_EDITOR"
ENV GITPOD_ENV_SET_GIT_EDITOR "$GITPOD_ENV_SET_EDITOR --wait"
ENV GITPOD_ENV_SET_GP_PREVIEW_BROWSER "/ide-desktop/bin/idea-cli preview"
ENV GITPOD_ENV_SET_GP_EXTERNAL_BROWSER "/ide-desktop/bin/idea-cli preview"
ENV GITPOD_ENV_SET_GP_PREVIEW_BROWSER "/ide-desktop/${JETBRAINS_DOWNLOAD_QUALIFIER}/bin/idea-cli preview"
ENV GITPOD_ENV_SET_GP_EXTERNAL_BROWSER "/ide-desktop/${JETBRAINS_DOWNLOAD_QUALIFIER}/bin/idea-cli preview"

LABEL "io.gitpod.ide.version"=$JETBRAINS_BACKEND_VERSION
18 changes: 18 additions & 0 deletions components/ide/jetbrains/image/resolve-latest-ide-version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash
# Copyright (c) 2022 Gitpod GmbH. All rights reserved.
# Licensed under the GNU Affero General Public License (AGPL).
# See License-AGPL.txt in the project root for license information.

set -Eeuo pipefail

ROOT_DIR="$(dirname "$0")/../../../.."
PRODUCT_CODE=${1}
TEMP_FILENAME=$(mktemp)
PLUGIN_PLATFORM_VERSION=$(grep platformVersion= "$ROOT_DIR/components/ide/jetbrains/backend-plugin/gradle-latest.properties" | sed 's/platformVersion=//' | sed 's/-EAP-CANDIDATE-SNAPSHOT//') # Example: PLUGIN_PLATFORM_VERSION: 223.7571

curl -sL "https://data.services.jetbrains.com/products/releases?code=$PRODUCT_CODE&type=eap,rc,release&platform=linux" > "$TEMP_FILENAME"
IDE_BUILD_VERSION=$(jq -r -c "first(.${PRODUCT_CODE}[] | select(.build | contains(\"$PLUGIN_PLATFORM_VERSION\")) | .build)" < "$TEMP_FILENAME") # Example: IDE_BUILD_VERSION: 223.7571.176
IDE_VERSION=$(jq -r ".${PRODUCT_CODE}[0].version" < "$TEMP_FILENAME") # Example: IDE_VERSION: 2022.3
rm "$TEMP_FILENAME"

echo "{\"IDE_BUILD_VERSION\": \"$IDE_BUILD_VERSION\", \"IDE_VERSION\": \"$IDE_VERSION\"}"
63 changes: 38 additions & 25 deletions components/ide/jetbrains/image/status/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ var (
Version = ""
)

const BackendPath = "/ide-desktop/backend"
const ProductInfoPath = BackendPath + "/product-info.json"

type LaunchContext struct {
startTime time.Time

port string
alias string
label string

qualifier string
productDir string
backendDir string
info *ProductInfo
backendVersion *version.Version
wsInfo *supervisor.WorkspaceInfoResponse
Expand Down Expand Up @@ -99,7 +99,16 @@ func main() {
label = os.Args[3]
}

info, err := resolveProductInfo()
qualifier := os.Getenv("JETBRAINS_BACKEND_QUALIFIER")
if qualifier == "stable" {
qualifier = ""
} else {
qualifier = "-" + qualifier
}
productDir := "/ide-desktop/" + alias + qualifier
backendDir := productDir + "/backend"

info, err := resolveProductInfo(backendDir)
if err != nil {
log.WithError(err).Error("failed to resolve product info")
return
Expand All @@ -124,6 +133,9 @@ func main() {
alias: alias,
label: label,

qualifier: qualifier,
productDir: productDir,
backendDir: backendDir,
info: info,
backendVersion: backendVersion,
wsInfo: wsInfo,
Expand Down Expand Up @@ -359,19 +371,12 @@ func launch(launchCtx *LaunchContext) {
idePrefix = "idea"
}
// [idea64|goland64|pycharm64|phpstorm64].vmoptions
launchCtx.vmOptionsFile = fmt.Sprintf("/ide-desktop/backend/bin/%s64.vmoptions", idePrefix)
launchCtx.vmOptionsFile = fmt.Sprintf(launchCtx.backendDir+"/bin/%s64.vmoptions", idePrefix)
err = configureVMOptions(gitpodConfig, launchCtx.alias, launchCtx.vmOptionsFile)
if err != nil {
log.WithError(err).Error("failed to configure vmoptions")
}

qualifier := os.Getenv("JETBRAINS_BACKEND_QUALIFIER")
if qualifier == "stable" {
qualifier = ""
} else {
qualifier = "-" + qualifier
}

var riderSolutionFile string
if launchCtx.alias == "rider" {
riderSolutionFile, err = findRiderSolutionFile(projectDir)
Expand All @@ -380,10 +385,10 @@ func launch(launchCtx *LaunchContext) {
}
}

configDir := fmt.Sprintf("/workspace/.config/JetBrains%s", qualifier)
configDir := fmt.Sprintf("/workspace/.config/JetBrains%s", launchCtx.qualifier)
launchCtx.projectDir = projectDir
launchCtx.configDir = configDir
launchCtx.systemDir = fmt.Sprintf("/workspace/.cache/JetBrains%s", qualifier)
launchCtx.systemDir = fmt.Sprintf("/workspace/.cache/JetBrains%s", launchCtx.qualifier)
launchCtx.riderSolutionFile = riderSolutionFile
launchCtx.projectContextDir = resolveProjectContextDir(launchCtx)
launchCtx.projectConfigDir = fmt.Sprintf("%s/RemoteDev-%s/%s", configDir, launchCtx.info.ProductCode, strings.ReplaceAll(launchCtx.projectContextDir, "/", "_"))
Expand All @@ -407,7 +412,7 @@ func launch(launchCtx *LaunchContext) {
}

// install gitpod plugin
err = linkRemotePlugin()
err = linkRemotePlugin(launchCtx)
if err != nil {
log.WithError(err).Error("failed to install gitpod-remote plugin")
}
Expand Down Expand Up @@ -445,7 +450,7 @@ func run(launchCtx *LaunchContext) {
}

// resolveUserEnvs emulats the interactive login shell to ensure that all user defined shell scripts are loaded
func resolveUserEnvs() (userEnvs []string, err error) {
func resolveUserEnvs(launchCtx *LaunchContext) (userEnvs []string, err error) {
shell := os.Getenv("SHELL")
if shell == "" {
shell = "/bin/bash"
Expand All @@ -454,7 +459,7 @@ func resolveUserEnvs() (userEnvs []string, err error) {
if err != nil {
return
}
envCmd := exec.Command(shell, []string{"-ilc", "/ide-desktop/status env " + mark.String()}...)
envCmd := exec.Command(shell, []string{"-ilc", launchCtx.productDir + "/status env " + mark.String()}...)
envCmd.Stderr = os.Stderr
output, err := envCmd.Output()
if err != nil {
Expand All @@ -469,7 +474,7 @@ func resolveUserEnvs() (userEnvs []string, err error) {

func remoteDevServerCmd(args []string, launchCtx *LaunchContext) *exec.Cmd {
if launchCtx.env == nil {
userEnvs, err := resolveUserEnvs()
userEnvs, err := resolveUserEnvs(launchCtx)
if err == nil {
launchCtx.env = append(launchCtx.env, userEnvs...)
} else {
Expand All @@ -484,15 +489,15 @@ func remoteDevServerCmd(args []string, launchCtx *LaunchContext) *exec.Cmd {
fmt.Sprintf("IJ_HOST_SYSTEM_BASE_DIR=%s", launchCtx.systemDir),
)

// instead put them into /ide-desktop/backend/bin/idea64.vmoptions
// instead put them into /ide-desktop/${alias}${qualifier}/backend/bin/idea64.vmoptions
// otherwise JB will complain to a user on each startup
// by default remote dev already set -Xmx2048m, see /ide-desktop/backend/plugins/remote-dev-server/bin/launcher.sh
// by default remote dev already set -Xmx2048m, see /ide-desktop/${alias}${qualifier}/backend/plugins/remote-dev-server/bin/launcher.sh
launchCtx.env = append(launchCtx.env, "JAVA_TOOL_OPTIONS=")

log.WithField("env", launchCtx.env).Debug("resolved launch env")
}

cmd := exec.Command(BackendPath+"/bin/remote-dev-server.sh", args...)
cmd := exec.Command(launchCtx.backendDir+"/bin/remote-dev-server.sh", args...)
cmd.Env = launchCtx.env
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
Expand Down Expand Up @@ -619,8 +624,8 @@ type ProductInfo struct {
ProductCode string `json:"productCode"`
}

func resolveProductInfo() (*ProductInfo, error) {
f, err := os.Open(ProductInfoPath)
func resolveProductInfo(backendDir string) (*ProductInfo, error) {
f, err := os.Open(backendDir + "/product-info.json")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -764,12 +769,20 @@ func getProductConfig(config *gitpod.GitpodConfig, alias string) *gitpod.Jetbrai
return productConfig
}

func linkRemotePlugin() error {
remotePluginDir := BackendPath + "/plugins/gitpod-remote"
func linkRemotePlugin(launchCtx *LaunchContext) error {
remotePluginDir := launchCtx.backendDir + "/plugins/gitpod-remote"
_, err := os.Stat(remotePluginDir)
if err == nil || !errors.Is(err, os.ErrNotExist) {
return nil
}

// added for backwards compatibility, can be removed in the future
sourceDir := "/ide-desktop-plugins/gitpod-remote-" + os.Getenv("JETBRAINS_BACKEND_QUALIFIER")
_, err = os.Stat(sourceDir)
if err == nil {
return os.Symlink(sourceDir, remotePluginDir)
}

return os.Symlink("/ide-desktop-plugins/gitpod-remote", remotePluginDir)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"entrypoint": "/ide-desktop/clion-latest/status",
"entrypointArgs": [
"{DESKTOPIDEPORT}",
"clion",
"Open in CLion"
],
"readinessProbe": {
"type": "http",
"http": {
"path": "/status"
}
}
}
Loading