From c1d74532baae34d7a57ddaf409f8d319f9850f71 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 21 Apr 2022 06:22:41 +0000 Subject: [PATCH] [jb] allow to specify plugins per a product --- .../gitpod-protocol/data/gitpod-schema.json | 58 ++++++++++++++++++- .../gitpod-protocol/go/gitpod-config-types.go | 19 ++++++ components/ide/jetbrains/image/status/go.mod | 5 +- components/ide/jetbrains/image/status/go.sum | 3 +- components/ide/jetbrains/image/status/main.go | 56 ++++++++++++------ .../ide/jetbrains/image/status/main_test.go | 25 ++++++++ 6 files changed, 146 insertions(+), 20 deletions(-) create mode 100644 components/ide/jetbrains/image/status/main_test.go diff --git a/components/gitpod-protocol/data/gitpod-schema.json b/components/gitpod-protocol/data/gitpod-schema.json index 7becc3365cf851..ce10cf3a10ed2d 100644 --- a/components/gitpod-protocol/data/gitpod-schema.json +++ b/components/gitpod-protocol/data/gitpod-schema.json @@ -255,10 +255,66 @@ "properties": { "plugins": { "type": "array", - "description": "List of plugins which should be installed for users of this workspace. From the JetBrains Marketplace page, find a page of the required plugin, select 'Versions' tab, click any version to copy pluginId (short name such as org.rust.lang) of the plugin you want to install.", + "description": "List of plugins which should be installed for all JetBrains product for users of this workspace. From the JetBrains Marketplace page, find a page of the required plugin, select 'Versions' tab, click any version to copy pluginId (short name such as org.rust.lang) of the plugin you want to install.", "items": { "type": "string" } + }, + "intellij": { + "type": "object", + "description": "Configure IntelliJ integration", + "additionalProperties": false, + "properties": { + "plugins": { + "type": "array", + "description": "List of plugins which should be installed for users of this workspace. From the JetBrains Marketplace page, find a page of the required plugin, select 'Versions' tab, click any version to copy pluginId (short name such as org.rust.lang) of the plugin you want to install.", + "items": { + "type": "string" + } + } + } + }, + "goland": { + "type": "object", + "description": "Configure GoLand integration", + "additionalProperties": false, + "properties": { + "plugins": { + "type": "array", + "description": "List of plugins which should be installed for users of this workspace. From the JetBrains Marketplace page, find a page of the required plugin, select 'Versions' tab, click any version to copy pluginId (short name such as org.rust.lang) of the plugin you want to install.", + "items": { + "type": "string" + } + } + } + }, + "pycharm": { + "type": "object", + "description": "Configure PyCharm integration", + "additionalProperties": false, + "properties": { + "plugins": { + "type": "array", + "description": "List of plugins which should be installed for users of this workspace. From the JetBrains Marketplace page, find a page of the required plugin, select 'Versions' tab, click any version to copy pluginId (short name such as org.rust.lang) of the plugin you want to install.", + "items": { + "type": "string" + } + } + } + }, + "phpstorm": { + "type": "object", + "description": "Configure PhpStorm integration", + "additionalProperties": false, + "properties": { + "plugins": { + "type": "array", + "description": "List of plugins which should be installed for users of this workspace. From the JetBrains Marketplace page, find a page of the required plugin, select 'Versions' tab, click any version to copy pluginId (short name such as org.rust.lang) of the plugin you want to install.", + "items": { + "type": "string" + } + } + } } } }, diff --git a/components/gitpod-protocol/go/gitpod-config-types.go b/components/gitpod-protocol/go/gitpod-config-types.go index e8e02376d2cfc0..dcfa5a6f4d5112 100644 --- a/components/gitpod-protocol/go/gitpod-config-types.go +++ b/components/gitpod-protocol/go/gitpod-config-types.go @@ -150,6 +150,25 @@ type JetBrains struct { // List of plugins which should be installed for users of this workspace. From the JetBrains Marketplace page, find a page of the required plugin, select 'Versions' tab, click any version to copy pluginId (short name such as org.rust.lang) of the plugin you want to install. Plugins []string `yaml:"plugins,omitempty"` + + // Configure IntelliJ integration + IntelliJ *JetBrainsProduct `yaml:"intellij,omitempty"` + + // Configure GoLand integration + GoLand *JetBrainsProduct `yaml:"goland,omitempty"` + + // Configure PyCharm integration + PyCharm *JetBrainsProduct `yaml:"pycharm,omitempty"` + + // Configure PhpStorm integration + PhpStorm *JetBrainsProduct `yaml:"phpstorm,omitempty"` +} + +// Configure JetBrains product +type JetBrainsProduct struct { + + // List of plugins which should be installed for users of this workspace. From the JetBrains Marketplace page, find a page of the required plugin, select 'Versions' tab, click any version to copy pluginId (short name such as org.rust.lang) of the plugin you want to install. + Plugins []string `yaml:"plugins,omitempty"` } func (strct *Github) MarshalJSON() ([]byte, error) { diff --git a/components/ide/jetbrains/image/status/go.mod b/components/ide/jetbrains/image/status/go.mod index 5f714badc5f72f..0c16821de7dcf5 100644 --- a/components/ide/jetbrains/image/status/go.mod +++ b/components/ide/jetbrains/image/status/go.mod @@ -2,7 +2,10 @@ module github.com/gitpod-io/gitpod/jetbrains/status go 1.17 -require github.com/gitpod-io/gitpod/supervisor/api v0.0.0-00010101000000-000000000000 +require ( + github.com/gitpod-io/gitpod/supervisor/api v0.0.0-00010101000000-000000000000 + github.com/google/go-cmp v0.5.6 +) require ( github.com/golang/mock v1.6.0 // indirect diff --git a/components/ide/jetbrains/image/status/go.sum b/components/ide/jetbrains/image/status/go.sum index 29b0051eed0e02..febc144ae7eb51 100644 --- a/components/ide/jetbrains/image/status/go.sum +++ b/components/ide/jetbrains/image/status/go.sum @@ -144,8 +144,8 @@ github.com/sourcegraph/jsonrpc2 v0.0.0-20200429184054-15c2290dcb37/go.mod h1:Zaf github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -420,6 +420,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/components/ide/jetbrains/image/status/main.go b/components/ide/jetbrains/image/status/main.go index 4e4f45afa8f568..ae8d54a4e6e0f7 100644 --- a/components/ide/jetbrains/image/status/main.go +++ b/components/ide/jetbrains/image/status/main.go @@ -17,7 +17,9 @@ import ( "os" "os/exec" "path/filepath" + "reflect" "regexp" + "strings" "time" "github.com/hashicorp/go-version" @@ -51,7 +53,7 @@ func main() { log.Fatalf("Usage: %s []\n", os.Args[0]) } port := os.Args[1] - kind := os.Args[2] + alias := os.Args[2] label := "Open JetBrains IDE" if len(os.Args) > 3 { label = os.Args[3] @@ -73,7 +75,7 @@ func main() { version_2022_1, _ := version.NewVersion("2022.1") if version_2022_1.LessThanOrEqual(backendVersion) { - err = installPlugins(wsInfo) + err = installPlugins(wsInfo, alias) installPluginsCost := time.Now().Local().Sub(startTime).Milliseconds() if err != nil { log.WithError(err).WithField("cost", installPluginsCost).Error("installing repo plugins: done") @@ -125,7 +127,7 @@ func main() { response["link"] = gatewayLink response["label"] = label response["clientID"] = "jetbrains-gateway" - response["kind"] = kind + response["kind"] = alias w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(response) }) @@ -294,8 +296,8 @@ func resolveBackendVersion() (*version.Version, error) { return version.NewVersion(info.Version) } -func installPlugins(wsInfo *supervisor.WorkspaceInfoResponse) error { - plugins, err := getPlugins(wsInfo.GetCheckoutLocation()) +func installPlugins(wsInfo *supervisor.WorkspaceInfoResponse, alias string) error { + plugins, err := getPlugins(wsInfo.GetCheckoutLocation(), alias) if err != nil { return err } @@ -342,29 +344,49 @@ func installPlugins(wsInfo *supervisor.WorkspaceInfoResponse) error { return nil } -func getPlugins(repoRoot string) (plugins []string, err error) { +func getPlugins(repoRoot string, alias string) ([]string, error) { if repoRoot == "" { - err = errors.New("repoRoot is empty") - return + return nil, errors.New("repoRoot is empty") } data, err := os.ReadFile(filepath.Join(repoRoot, ".gitpod.yml")) if err != nil { // .gitpod.yml not exist is ok if errors.Is(err, os.ErrNotExist) { - err = nil - return + return nil, nil } - err = errors.New("read .gitpod.yml file failed: " + err.Error()) - return + return nil, errors.New("read .gitpod.yml file failed: " + err.Error()) } var config *gitpod.GitpodConfig if err = yaml.Unmarshal(data, &config); err != nil { - err = errors.New("unmarshal .gitpod.yml file failed" + err.Error()) - return + return nil, errors.New("unmarshal .gitpod.yml file failed" + err.Error()) } + if config == nil || config.JetBrains == nil { - err = errors.New("config.vscode field not exists") - return + return nil, nil + } + var plugins []string + if config.JetBrains.Plugins != nil { + plugins = append(plugins, config.JetBrains.Plugins...) + } + productConfig := getProductConfig(config, alias) + if productConfig != nil && productConfig.Plugins != nil { + plugins = append(plugins, productConfig.Plugins...) + } + return plugins, nil +} + +func getProductConfig(config *gitpod.GitpodConfig, alias string) *gitpod.JetBrainsProduct { + defer func() { + if err := recover(); err != nil { + log.WithField("error", err).WithField("alias", alias).Error("failed to extract JB product config") + } + }() + v := reflect.ValueOf(*config.JetBrains).FieldByNameFunc(func(s string) bool { + return strings.ToLower(s) == alias + }).Interface() + productConfig, ok := v.(*gitpod.JetBrainsProduct) + if !ok { + return nil } - return config.JetBrains.Plugins, nil + return productConfig } diff --git a/components/ide/jetbrains/image/status/main_test.go b/components/ide/jetbrains/image/status/main_test.go new file mode 100644 index 00000000000000..00e6284e37b1e0 --- /dev/null +++ b/components/ide/jetbrains/image/status/main_test.go @@ -0,0 +1,25 @@ +// 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. + +package main + +import ( + "testing" + + protocol "github.com/gitpod-io/gitpod/gitpod-protocol" + "github.com/google/go-cmp/cmp" +) + +func TestGetProductConfig(t *testing.T) { + expectation := &protocol.JetBrainsProduct{} + actual := getProductConfig(&protocol.GitpodConfig{ + JetBrains: &protocol.JetBrains{ + IntelliJ: expectation, + }, + }, "intellij") + + if diff := cmp.Diff(expectation, actual); diff != "" { + t.Errorf("unexpected output (-want +got):\n%s", diff) + } +}