feat: [CDE-576]: add devcontainer config for Jetbrains (#3215)

* feat: [CDE-576]: fix hardcoding
* feat: [CDE-576]: fix lint
* feat: [CDE-576]: lint
* feat: [CDE-576]: make IDE path configurable
* Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into CDE-576-devcontainer-json-intellij
* feat: [CDE-576]: fix script name
* feat: [CDE-576]: configure Jetbrains IDEs
* feat: [CDE-576]: change to intellij ide type
* feat: [CDE-576]: fix comments
* Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into CDE-576-devcontainer-json-intellij
* feat: [CDE-576]: add devcontainer config for Jetbrains
* feat: [CDE-552]: fix lint
* feat: [CDE-552]: wait for the ide to run
* feat: [CDE-552}: fix lint
* feat: [CDE-552}: address comments
* feat: [CDE-552}: add support for arm and amd architecture
* feat: [CDE-552}: fix lint
* feat: [CDE-552}: fix build
* Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into CDE-563-intellij-support
* feat: [CDE-552}: fix installation for intellij
* feat: [CDE-552}: fix installation for intellij
* feat: [CDE-552}: add install tools, setup and run scripts for intellij
* add intellij support

# Conflicts:
#	app/gitspace/infrastructure/trigger_infra_event.go
#	app/gitspace/orchestrator/utils/script_templates/setup_intellij.sh
BT-10437
Deepak Bhatt 2025-01-07 13:10:54 +00:00 committed by Harness
parent 2b59a4f68f
commit 19363d2b1a
18 changed files with 387 additions and 123 deletions

View File

@ -130,8 +130,9 @@ func getGitspaceScheme(ideType enum.IDEType, gitspaceSchemeFromMetadata string)
return gitspaceSchemeFromMetadata, nil
case enum.IDETypeVSCode:
return "ssh", nil
case enum.IDETypeIntellij:
return gitspaceSchemeFromMetadata, nil
case enum.IDETypeIntelliJ, enum.IDETypePyCharm, enum.IDETypeGoland, enum.IDETypeWebStorm, enum.IDETypeCLion,
enum.IDETypePHPStorm, enum.IDETypeRubyMine, enum.IDETypeRider:
return "ssh", nil
default:
return "", fmt.Errorf("unknown ideType %s", ideType)
}

View File

@ -200,9 +200,17 @@ func AddIDECustomizationsArg(
devcontainerConfig types.DevcontainerConfig,
args map[gitspaceTypes.IDEArg]interface{},
) map[gitspaceTypes.IDEArg]interface{} {
if ideService.Type() == enum.IDETypeVSCodeWeb || ideService.Type() == enum.IDETypeVSCode {
if devcontainerConfig.Customizations.ExtractVSCodeSpec() != nil {
args[gitspaceTypes.VSCodeCustomizationArg] = *devcontainerConfig.Customizations.ExtractVSCodeSpec()
switch ideService.Type() {
case enum.IDETypeVSCodeWeb, enum.IDETypeVSCode:
vscodeSpecs := devcontainerConfig.Customizations.ExtractVSCodeSpec()
if vscodeSpecs != nil {
args[gitspaceTypes.VSCodeCustomizationArg] = *vscodeSpecs
}
case enum.IDETypeIntelliJ, enum.IDETypePyCharm, enum.IDETypeGoland, enum.IDETypeWebStorm, enum.IDETypeCLion,
enum.IDETypePHPStorm, enum.IDETypeRubyMine, enum.IDETypeRider:
jetbrainsSpecs := devcontainerConfig.Customizations.ExtractJetBrainsSpecs()
if jetbrainsSpecs != nil {
args[gitspaceTypes.JetBrainsCustomizationArg] = *jetbrainsSpecs
}
}
return args
@ -212,11 +220,18 @@ func AddIDEDownloadURLArg(
ideService ide.IDE,
args map[gitspaceTypes.IDEArg]interface{},
) map[gitspaceTypes.IDEArg]interface{} {
if ideService.Type() == enum.IDETypeIntellij {
args[gitspaceTypes.IDEDownloadURLArg] = types.IntellijDownloadURL{
Arm64: fmt.Sprintf(enum.IDEIntellijDownloadURLArm64Template, enum.IDEIntellijVer),
Amd64: fmt.Sprintf(enum.IDEIntellijDownloadURLAmd64Template, enum.IDEIntellijVer),
}
if !enum.IsJetBrainsIDE(ideService.Type()) {
// currently download url is only need for jetbrains IDEs
return args
}
ideType := ideService.Type()
ideDownloadURLTemplate := types.JetBrainsIDEDownloadURLTemplateMap[ideType]
args[gitspaceTypes.IDEDownloadURLArg] = types.IDEDownloadURLs{
Amd64Sha: ideDownloadURLTemplate.Amd64Sha,
Arm64Sha: ideDownloadURLTemplate.Arm64Sha,
Amd64: fmt.Sprintf(ideDownloadURLTemplate.Amd64, ideDownloadURLTemplate.Version),
Arm64: fmt.Sprintf(ideDownloadURLTemplate.Arm64, ideDownloadURLTemplate.Version),
}
return args
@ -226,10 +241,15 @@ func AddIDEDirNameArg(
ideService ide.IDE,
args map[gitspaceTypes.IDEArg]interface{},
) map[gitspaceTypes.IDEArg]interface{} {
if ideService.Type() == enum.IDETypeIntellij {
dirname := path.Join(".cache", "JetBrains", "RemoteDev", "dist", "intellij")
args[gitspaceTypes.IDEDIRNameArg] = dirname
if !enum.IsJetBrainsIDE(ideService.Type()) {
// currently dirname is only need for jetbrains IDEs
return args
}
ideType := ideService.Type()
dirname := path.Join(".cache", "JetBrains", "RemoteDev", "dist", ideType.String())
args[gitspaceTypes.IDEDIRNameArg] = dirname
return args
}

View File

@ -612,7 +612,7 @@ func (e *EmbeddedDockerOrchestrator) buildSetupSteps(
}
}
// setupGitspaceAndIDE initializes Gitspace and IDE by registering and executing the setup steps.
// setupGitspaceAndIDE initializes Gitspace and IdeType by registering and executing the setup steps.
func (e *EmbeddedDockerOrchestrator) setupGitspaceAndIDE(
ctx context.Context,
exec *devcontainer.Exec,

View File

@ -23,18 +23,18 @@ import (
func getIDEDownloadURL(
args map[gitspaceTypes.IDEArg]interface{},
) (types.IntellijDownloadURL, error) {
) (types.IDEDownloadURLs, error) {
downloadURL, exists := args[gitspaceTypes.IDEDownloadURLArg]
if !exists {
return types.IntellijDownloadURL{}, fmt.Errorf("ide download url not found")
return types.IDEDownloadURLs{}, fmt.Errorf("ide download url not found")
}
downloadURLStr, ok := downloadURL.(types.IntellijDownloadURL)
downloadURLs, ok := downloadURL.(types.IDEDownloadURLs)
if !ok {
return types.IntellijDownloadURL{}, fmt.Errorf("ide download url is not of type IntellijDownloadURL")
return types.IDEDownloadURLs{}, fmt.Errorf("ide download url is not of type JetBrainsSpecs")
}
return downloadURLStr, nil
return downloadURLs, nil
}
func getIDEDirName(args map[gitspaceTypes.IDEArg]interface{}) (string, error) {

View File

@ -24,11 +24,22 @@ type Factory struct {
ides map[enum.IDEType]IDE
}
func NewFactory(vscode *VSCode, vscodeWeb *VSCodeWeb, intellij *Intellij) Factory {
func NewFactory(
vscode *VSCode,
vscodeWeb *VSCodeWeb,
jetBrainsIDEsMap map[enum.IDEType]*JetBrainsIDE,
) Factory {
ides := make(map[enum.IDEType]IDE)
ides[enum.IDETypeVSCode] = vscode
ides[enum.IDETypeVSCodeWeb] = vscodeWeb
ides[enum.IDETypeIntellij] = intellij
ides[enum.IDETypeIntelliJ] = jetBrainsIDEsMap[enum.IDETypeIntelliJ]
ides[enum.IDETypePyCharm] = jetBrainsIDEsMap[enum.IDETypePyCharm]
ides[enum.IDETypeGoland] = jetBrainsIDEsMap[enum.IDETypeGoland]
ides[enum.IDETypeWebStorm] = jetBrainsIDEsMap[enum.IDETypeWebStorm]
ides[enum.IDETypeCLion] = jetBrainsIDEsMap[enum.IDETypeCLion]
ides[enum.IDETypePHPStorm] = jetBrainsIDEsMap[enum.IDETypePHPStorm]
ides[enum.IDETypeRubyMine] = jetBrainsIDEsMap[enum.IDETypeRubyMine]
ides[enum.IDETypeRider] = jetBrainsIDEsMap[enum.IDETypeRider]
return Factory{ides: ides}
}

View File

@ -28,54 +28,58 @@ import (
"github.com/harness/gitness/types/enum"
)
var _ IDE = (*Intellij)(nil)
var _ IDE = (*JetBrainsIDE)(nil)
const (
templateSetupIntellij string = "setup_intellij.sh"
templateRunRemoteIDEIntellij string = "run_intellij.sh"
templateSetupJetBrainsIDE string = "setup_jetbrains_ide.sh"
templateRunRemoteJetBrainsIDE string = "run_jetbrains_ide.sh"
intellijURLScheme string = "jetbrains-gateway"
)
type IntellijConfig struct {
type JetBrainsIDEConfig struct {
Port int
}
type Intellij struct {
config IntellijConfig
type JetBrainsIDE struct {
ideType enum.IDEType
config JetBrainsIDEConfig
}
func NewIntellijService(config *IntellijConfig) *Intellij {
return &Intellij{config: *config}
func NewJetBrainsIDEService(config *JetBrainsIDEConfig, ideType enum.IDEType) *JetBrainsIDE {
return &JetBrainsIDE{
ideType: ideType,
config: *config,
}
}
// Setup installs the SSH server inside the container.
func (ij *Intellij) Setup(
func (jb *JetBrainsIDE) Setup(
ctx context.Context,
exec *devcontainer.Exec,
args map[gitspaceTypes.IDEArg]interface{},
gitspaceLogger gitspaceTypes.GitspaceLogger,
) error {
gitspaceLogger.Info("Installing ssh-server inside container")
err := ij.setupSSHServer(ctx, exec, gitspaceLogger)
err := jb.setupSSHServer(ctx, exec, gitspaceLogger)
if err != nil {
return fmt.Errorf("failed to setup SSH server: %w", err)
}
gitspaceLogger.Info("Successfully installed ssh-server")
gitspaceLogger.Info("Installing intelliJ IDE inside container")
gitspaceLogger.Info(fmt.Sprintf("Installing %s IdeType inside container...", jb.ideType))
gitspaceLogger.Info("IDE setup output...")
err = ij.setupIntellijIDE(ctx, exec, args, gitspaceLogger)
err = jb.setupIntellijIDE(ctx, exec, args, gitspaceLogger)
if err != nil {
return fmt.Errorf("failed to setup IntelliJ IDE: %w", err)
return fmt.Errorf("failed to setup %s IdeType: %w", jb.ideType, err)
}
gitspaceLogger.Info("Successfully installed IntelliJ IDE")
gitspaceLogger.Info(fmt.Sprintf("Successfully installed %s IdeType", jb.ideType))
gitspaceLogger.Info("Successfully set up IDE inside container")
return nil
}
func (ij *Intellij) setupSSHServer(
func (jb *JetBrainsIDE) setupSSHServer(
ctx context.Context,
exec *devcontainer.Exec,
gitspaceLogger gitspaceTypes.GitspaceLogger,
@ -100,7 +104,7 @@ func (ij *Intellij) setupSSHServer(
return nil
}
func (ij *Intellij) setupIntellijIDE(
func (jb *JetBrainsIDE) setupIntellijIDE(
ctx context.Context,
exec *devcontainer.Exec,
args map[gitspaceTypes.IDEArg]interface{},
@ -126,11 +130,11 @@ func (ij *Intellij) setupIntellijIDE(
payload.IdeDirName = dirName
intellijIDEScript, err := utils.GenerateScriptFromTemplate(
templateSetupIntellij, &payload)
templateSetupJetBrainsIDE, &payload)
if err != nil {
return fmt.Errorf(
"failed to generate scipt to setup intellij idea from template %s: %w",
templateSetupIntellij,
templateSetupJetBrainsIDE,
err,
)
}
@ -138,43 +142,43 @@ func (ij *Intellij) setupIntellijIDE(
err = exec.ExecuteCommandInHomeDirAndLog(ctx, intellijIDEScript,
false, gitspaceLogger, true)
if err != nil {
return fmt.Errorf("failed to setup intellij IDE: %w", err)
return fmt.Errorf("failed to setup intellij IdeType: %w", err)
}
return nil
}
// Run runs the SSH server inside the container.
func (ij *Intellij) Run(
func (jb *JetBrainsIDE) Run(
ctx context.Context,
exec *devcontainer.Exec,
args map[gitspaceTypes.IDEArg]interface{},
gitspaceLogger gitspaceTypes.GitspaceLogger,
) error {
gitspaceLogger.Info("SSH server run output...")
err := ij.runSSHServer(ctx, exec, args, gitspaceLogger)
err := jb.runSSHServer(ctx, exec, args, gitspaceLogger)
if err != nil {
return err
}
gitspaceLogger.Info("Successfully run ssh-server")
gitspaceLogger.Info("Run Remote IntelliJ IDE...")
err = ij.runRemoteIDE(ctx, exec, args, gitspaceLogger)
gitspaceLogger.Info("Run Remote IntelliJ IdeType...")
err = jb.runRemoteIDE(ctx, exec, args, gitspaceLogger)
if err != nil {
return err
}
gitspaceLogger.Info("Successfully Run Remote IntelliJ IDE")
gitspaceLogger.Info("Successfully Run Remote IntelliJ IdeType")
return nil
}
func (ij *Intellij) runSSHServer(
func (jb *JetBrainsIDE) runSSHServer(
ctx context.Context,
exec *devcontainer.Exec,
_ map[gitspaceTypes.IDEArg]interface{},
gitspaceLogger gitspaceTypes.GitspaceLogger,
) error {
payload := gitspaceTypes.RunSSHServerPayload{
Port: strconv.Itoa(ij.config.Port),
Port: strconv.Itoa(jb.config.Port),
}
runSSHScript, err := utils.GenerateScriptFromTemplate(
templateRunSSHServer, &payload)
@ -192,7 +196,7 @@ func (ij *Intellij) runSSHServer(
return nil
}
func (ij *Intellij) runRemoteIDE(
func (jb *JetBrainsIDE) runRemoteIDE(
ctx context.Context,
exec *devcontainer.Exec,
args map[gitspaceTypes.IDEArg]interface{},
@ -216,32 +220,36 @@ func (ij *Intellij) runRemoteIDE(
payload.IdeDirName = dirName
runSSHScript, err := utils.GenerateScriptFromTemplate(
templateRunRemoteIDEIntellij, &payload)
templateRunRemoteJetBrainsIDE, &payload)
if err != nil {
return fmt.Errorf(
"failed to generate scipt to run intelliJ IDE from template %s: %w", templateRunSSHServer, err)
"failed to generate scipt to run intelliJ IdeType from template %s: %w", templateRunSSHServer, err)
}
err = exec.ExecuteCommandInHomeDirAndLog(ctx, runSSHScript, false, gitspaceLogger, true)
if err != nil {
return fmt.Errorf("failed to run intelliJ IDE: %w", err)
return fmt.Errorf("failed to run intelliJ IdeType: %w", err)
}
return nil
}
// Port returns the port on which the ssh-server is listening.
func (ij *Intellij) Port() *types.GitspacePort {
func (jb *JetBrainsIDE) Port() *types.GitspacePort {
return &types.GitspacePort{
Port: ij.config.Port,
Port: jb.config.Port,
Protocol: enum.CommunicationProtocolSSH,
}
}
func (jb *JetBrainsIDE) Type() enum.IDEType {
return jb.ideType
}
// GenerateURL returns the url to redirect user to ide(here to jetbrains gateway application).
func (ij *Intellij) GenerateURL(absoluteRepoPath, host, port, user string) string {
func (jb *JetBrainsIDE) GenerateURL(absoluteRepoPath, host, port, user string) string {
homePath := getHomePath(absoluteRepoPath)
idePath := path.Join(homePath, ".cache", "JetBrains", "RemoteDev", "dist", "intellij")
idePath := path.Join(homePath, ".cache", "JetBrains", "RemoteDev", "dist", jb.ideType.String())
ideURL := url.URL{
Scheme: intellijURLScheme,
Host: "", // Empty since we include the host and port in the path
@ -259,7 +267,3 @@ func (ij *Intellij) GenerateURL(absoluteRepoPath, host, port, user string) strin
return ideURL.String()
}
func (ij *Intellij) Type() enum.IDEType {
return enum.IDETypeIntellij
}

View File

@ -15,13 +15,15 @@
package ide
import (
"github.com/harness/gitness/types/enum"
"github.com/google/wire"
)
var WireSet = wire.NewSet(
ProvideVSCodeWebService,
ProvideVSCodeService,
ProvideIntellijService,
ProvideJetBrainsIDEsService,
ProvideIDEFactory,
)
@ -33,14 +35,23 @@ func ProvideVSCodeService(config *VSCodeConfig) *VSCode {
return NewVsCodeService(config)
}
func ProvideIntellijService(config *IntellijConfig) *Intellij {
return NewIntellijService(config)
func ProvideJetBrainsIDEsService(config *JetBrainsIDEConfig) map[enum.IDEType]*JetBrainsIDE {
return map[enum.IDEType]*JetBrainsIDE{
enum.IDETypeIntelliJ: NewJetBrainsIDEService(config, enum.IDETypeIntelliJ),
enum.IDETypePyCharm: NewJetBrainsIDEService(config, enum.IDETypePyCharm),
enum.IDETypeGoland: NewJetBrainsIDEService(config, enum.IDETypeGoland),
enum.IDETypeWebStorm: NewJetBrainsIDEService(config, enum.IDETypeWebStorm),
enum.IDETypeCLion: NewJetBrainsIDEService(config, enum.IDETypeCLion),
enum.IDETypePHPStorm: NewJetBrainsIDEService(config, enum.IDETypePHPStorm),
enum.IDETypeRubyMine: NewJetBrainsIDEService(config, enum.IDETypeRubyMine),
enum.IDETypeRider: NewJetBrainsIDEService(config, enum.IDETypeRider),
}
}
func ProvideIDEFactory(
vscode *VSCode,
vscodeWeb *VSCodeWeb,
intellij *Intellij,
jetBrainsIDEsMap map[enum.IDEType]*JetBrainsIDE,
) Factory {
return NewFactory(vscode, vscodeWeb, intellij)
return NewFactory(vscode, vscodeWeb, jetBrainsIDEsMap)
}

View File

@ -42,8 +42,9 @@ func InstallTools(
return err
}
return nil
case enum.IDETypeIntellij:
err := InstallToolsForIntellij(ctx, exec, gitspaceLogger)
case enum.IDETypeIntelliJ, enum.IDETypePyCharm, enum.IDETypeGoland, enum.IDETypeWebStorm, enum.IDETypeCLion,
enum.IDETypePHPStorm, enum.IDETypeRubyMine, enum.IDETypeRider:
err := InstallToolsForJetBrains(ctx, exec, ideType, gitspaceLogger)
if err != nil {
return err
}
@ -101,9 +102,10 @@ func InstallToolsForVsCode(
return nil
}
func InstallToolsForIntellij(
func InstallToolsForJetBrains(
ctx context.Context,
exec *devcontainer.Exec,
ideType enum.IDEType,
gitspaceLogger types.GitspaceLogger,
) error {
script, err := GenerateScriptFromTemplate(
@ -112,15 +114,15 @@ func InstallToolsForIntellij(
})
if err != nil {
return fmt.Errorf(
"failed to generate scipt to install tools for intellij from template %s: %w",
templateIntellijToolsInstallation, err)
"failed to generate scipt to install tools for %s from template %s: %w",
ideType, templateIntellijToolsInstallation, err)
}
gitspaceLogger.Info("Installing tools for intellij in container")
gitspaceLogger.Info(fmt.Sprintf("Installing tools for %s in container", ideType))
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, true, gitspaceLogger, false)
if err != nil {
return fmt.Errorf("failed to install tools for intellij: %w", err)
return fmt.Errorf("failed to install tools for %s: %w", ideType, err)
}
gitspaceLogger.Info("Successfully installed tools for intellij")
gitspaceLogger.Info(fmt.Sprintf("Successfully installed tools for %s in container", ideType))
return nil
}

View File

@ -23,11 +23,12 @@ import (
type IDEArg string
const (
VSCodeCustomizationArg IDEArg = "VSCODE_CUSTOMIZATION"
VSCodeProxyURIArg IDEArg = "VSCODE_PROXY_URI"
IDERepoNameArg IDEArg = "IDE_REPO_NAME"
IDEDownloadURLArg IDEArg = "IDE_DOWNLOAD_URL"
IDEDIRNameArg IDEArg = "IDE_DIR_NAME"
VSCodeCustomizationArg IDEArg = "VSCODE_CUSTOMIZATION"
JetBrainsCustomizationArg IDEArg = "JETBRAINS_CUSTOMIZATION"
VSCodeProxyURIArg IDEArg = "VSCODE_PROXY_URI"
IDERepoNameArg IDEArg = "IDE_REPO_NAME"
IDEDownloadURLArg IDEArg = "IDE_DOWNLOAD_URL"
IDEDIRNameArg IDEArg = "IDE_DIR_NAME"
)
type GitspaceLogger interface {

View File

@ -442,9 +442,9 @@ func ProvideIDEVSCodeConfig(config *types.Config) *ide.VSCodeConfig {
}
}
// ProvideIDEIntellijConfig loads the Intellij IDE config from the main config.
func ProvideIDEIntellijConfig(config *types.Config) *ide.IntellijConfig {
return &ide.IntellijConfig{
// ProvideIDEIntellijConfig loads the IdeType IDE config from the main config.
func ProvideIDEIntellijConfig(config *types.Config) *ide.JetBrainsIDEConfig {
return &ide.JetBrainsIDEConfig{
Port: config.IDE.Intellij.Port,
}
}

View File

@ -333,9 +333,9 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
vsCode := ide.ProvideVSCodeService(vsCodeConfig)
vsCodeWebConfig := server.ProvideIDEVSCodeWebConfig(config)
vsCodeWeb := ide.ProvideVSCodeWebService(vsCodeWebConfig)
intellijConfig := server.ProvideIDEIntellijConfig(config)
intellij := ide.ProvideIntellijService(intellijConfig)
ideFactory := ide.ProvideIDEFactory(vsCode, vsCodeWeb, intellij)
jetBrainsIDEConfig := server.ProvideIDEIntellijConfig(config)
v := ide.ProvideJetBrainsIDEsService(jetBrainsIDEConfig)
ideFactory := ide.ProvideIDEFactory(vsCode, vsCodeWeb, v)
passwordResolver := secret.ProvidePasswordResolver()
resolverFactory := secret.ProvideResolverFactory(passwordResolver)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, platformConnector, infraProvisioner, containerOrchestrator, eventsReporter, orchestratorConfig, ideFactory, resolverFactory)
@ -409,8 +409,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore)
principalController := principal.ProvideController(principalStore, authorizer)
usergroupController := usergroup2.ProvideController(userGroupStore, spaceStore, authorizer, searchService)
v := check2.ProvideCheckSanitizers()
checkController := check2.ProvideController(transactor, authorizer, spaceStore, checkStore, spaceCache, repoFinder, gitInterface, v, streamer)
v2 := check2.ProvideCheckSanitizers()
checkController := check2.ProvideController(transactor, authorizer, spaceStore, checkStore, spaceCache, repoFinder, gitInterface, v2, streamer)
systemController := system.NewController(principalStore, config)
blobConfig, err := server.ProvideBlobStoreConfig(config)
if err != nil {

View File

@ -17,12 +17,15 @@ package types
import (
"encoding/json"
"github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
)
const (
GitspaceCustomizationsKey CustomizationsKey = "harnessGitspaces"
VSCodeCustomizationsKey CustomizationsKey = "vscode"
GitspaceCustomizationsKey CustomizationsKey = "harnessGitspaces"
VSCodeCustomizationsKey CustomizationsKey = "vscode"
JetBrainsCustomizationsKey CustomizationsKey = "jetbrains"
)
type CustomizationsKey string
@ -31,8 +34,116 @@ func (ck CustomizationsKey) String() string {
return string(ck)
}
// DevContainerConfigCustomizations implements various Extract* function to extract out custom field defines in
// customization field in devcontainer.json.
type DevContainerConfigCustomizations map[string]interface{}
// VSCodeCustomizationSpecs contains details about vscode customization.
// eg:
//
// "customizations": {
// // Configure properties specific to VS Code.
// "vscode": {
// "settings": {
// "java.home": "/docker-java-home"
// },
// "extensions": [
// "streetsidesoftware.code-spell-checker"
// ]
// }
// }
type VSCodeCustomizationSpecs struct {
Extensions []string `json:"extensions"`
Settings map[string]interface{} `json:"settings"`
}
// GitspaceCustomizationSpecs contains details about harness platform connectors.
// eg:
//
// "customizations": {
// "harnessGitspaces": {
// "connectors": [
// {
// "type": "DockerRegistry",
// "identifier": "testharnessjfrog"
// },
// {
// "type": "Artifactory",
// "identifier": "testartifactoryconnector"
// }
// ]
// }
// }
type GitspaceCustomizationSpecs struct {
Connectors []struct {
Type string `json:"type"`
ID string `json:"identifier"`
} `json:"connectors"`
}
type JetBrainsBackend string
func (jb JetBrainsBackend) String() string {
return string(jb)
}
func (jb JetBrainsBackend) Valid() bool {
_, valid := ValidJetBrainsBackendSet[jb]
return valid
}
func (jb JetBrainsBackend) IdeType() enum.IDEType {
var ideType enum.IDEType
switch jb {
case IntelliJJetBrainsBackend:
ideType = enum.IDETypeIntelliJ
case GolandJetBrainsBackend:
ideType = enum.IDETypeGoland
case PyCharmJetBrainsBackend:
ideType = enum.IDETypePyCharm
case WebStormJetBrainsBackend:
ideType = enum.IDETypeWebStorm
case CLionJetBrainsBackend:
ideType = enum.IDETypeCLion
case PhpStormJetBrainsBackend:
ideType = enum.IDETypePHPStorm
case RubyMineJetBrainsBackend:
ideType = enum.IDETypeRubyMine
case RiderJetBrainsBackend:
ideType = enum.IDETypeRider
}
return ideType
}
const (
IntelliJJetBrainsBackend JetBrainsBackend = "IntelliJ"
GolandJetBrainsBackend JetBrainsBackend = "Goland"
PyCharmJetBrainsBackend JetBrainsBackend = "PyCharm"
WebStormJetBrainsBackend JetBrainsBackend = "WebStorm"
CLionJetBrainsBackend JetBrainsBackend = "CLion"
PhpStormJetBrainsBackend JetBrainsBackend = "PhpStorm"
RubyMineJetBrainsBackend JetBrainsBackend = "RubyMine"
RiderJetBrainsBackend JetBrainsBackend = "Rider"
)
var ValidJetBrainsBackendSet = map[JetBrainsBackend]struct{}{
IntelliJJetBrainsBackend: {},
GolandJetBrainsBackend: {},
PyCharmJetBrainsBackend: {},
WebStormJetBrainsBackend: {},
CLionJetBrainsBackend: {},
PhpStormJetBrainsBackend: {},
RubyMineJetBrainsBackend: {},
RiderJetBrainsBackend: {},
}
type JetBrainsCustomizationSpecs struct {
Backend JetBrainsBackend `json:"backend"`
Plugins []string `json:"plugins"`
}
func (dcc DevContainerConfigCustomizations) ExtractGitspaceSpec() *GitspaceCustomizationSpecs {
val, ok := dcc[GitspaceCustomizationsKey.String()]
if !ok {
@ -84,14 +195,28 @@ func (dcc DevContainerConfigCustomizations) ExtractVSCodeSpec() *VSCodeCustomiza
return &vsCodeCustomizationSpecs
}
type VSCodeCustomizationSpecs struct {
Extensions []string `json:"extensions"`
Settings map[string]interface{} `json:"settings"`
}
func (dcc DevContainerConfigCustomizations) ExtractJetBrainsSpecs() *JetBrainsCustomizationSpecs {
data, ok := dcc[JetBrainsCustomizationsKey.String()]
if !ok {
// Log that the key is missing, but return nil
log.Warn().Msgf("JetBrains customization key %q not found, returning empty struct",
JetBrainsCustomizationsKey)
return nil
}
type GitspaceCustomizationSpecs struct {
Connectors []struct {
Type string `json:"type"`
ID string `json:"identifier"`
} `json:"connectors"`
rawData, err := json.Marshal(data)
if err != nil {
// Log the error during marshalling and return nil
log.Printf("Failed to marshal data for key %q: %v", JetBrainsCustomizationsKey, err)
return nil
}
var jetbrainsSpecs JetBrainsCustomizationSpecs
if err := json.Unmarshal(rawData, &jetbrainsSpecs); err != nil {
// Log the error during unmarshalling and return nil
log.Printf("Failed to unmarshal data for key %q: %v", JetBrainsCustomizationsKey, err)
return nil
}
return &jetbrainsSpecs
}

View File

@ -16,12 +16,39 @@ package enum
type IDEType string
func (IDEType) Enum() []interface{} { return toInterfaceSlice(ideTypes) }
func (i IDEType) Enum() []interface{} { return toInterfaceSlice(ideTypes) }
var ideTypes = []IDEType{IDETypeVSCode, IDETypeVSCodeWeb, IDETypeIntellij}
func (i IDEType) String() string { return string(i) }
var ideTypes = []IDEType{IDETypeVSCode, IDETypeVSCodeWeb, IDETypeIntelliJ, IDETypePyCharm, IDETypeGoland,
IDETypeWebStorm, IDETypeCLion, IDETypePHPStorm, IDETypeRubyMine, IDETypeRider}
var jetBrainsIDESet = map[IDEType]struct{}{
IDETypeIntelliJ: {},
IDETypePyCharm: {},
IDETypeGoland: {},
IDETypeWebStorm: {},
IDETypeCLion: {},
IDETypePHPStorm: {},
IDETypeRubyMine: {},
IDETypeRider: {},
}
const (
IDETypeVSCode IDEType = "vs_code"
IDETypeVSCodeWeb IDEType = "vs_code_web"
IDETypeIntellij IDEType = "intellij"
// all jetbrains IDEs.
IDETypeIntelliJ IDEType = "intellij"
IDETypePyCharm IDEType = "pycharm"
IDETypeGoland IDEType = "goland"
IDETypeWebStorm IDEType = "webstorm"
IDETypeCLion IDEType = "clion"
IDETypePHPStorm IDEType = "phpstorm"
IDETypeRubyMine IDEType = "rubymine"
IDETypeRider IDEType = "rider"
)
func IsJetBrainsIDE(t IDEType) bool {
_, exist := jetBrainsIDESet[t]
return exist
}

View File

@ -1,21 +0,0 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package enum
const (
IDEIntellijDownloadURLAmd64Template string = "https://download.jetbrains.com/idea/ideaIU-%s.tar.gz"
IDEIntellijDownloadURLArm64Template string = "https://download.jetbrains.com/idea/ideaIU-%s-aarch64.tar.gz"
IDEIntellijVer string = "2024.3"
)

View File

@ -14,7 +14,9 @@
package types
type IntellijDownloadURL struct {
Arm64 string
Amd64 string
type IDEDownloadURLs struct {
Arm64Sha string
Amd64Sha string
Arm64 string
Amd64 string
}

81
types/jetbrains.go Normal file
View File

@ -0,0 +1,81 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import "github.com/harness/gitness/types/enum"
type JetBrainsIDEDownloadURLTemplates struct {
Version string
Amd64Sha string
Arm64Sha string
Amd64 string
Arm64 string
}
var JetBrainsIDEDownloadURLTemplateMap = map[enum.IDEType]JetBrainsIDEDownloadURLTemplates{
enum.IDETypeIntelliJ: {
// list of versions: https://www.jetbrains.com/idea/download/other.html
Version: "2024.3.1.1",
Amd64: "https://download.jetbrains.com/idea/ideaIU-%s.tar.gz",
Arm64: "https://download.jetbrains.com/idea/ideaIU-%s-aarch64.tar.gz",
},
enum.IDETypeGoland: {
// list of versions: https://www.jetbrains.com/go/download/other.html
Version: "2024.3.1",
Amd64: "https://download.jetbrains.com/go/goland-%s.tar.gz",
Arm64: "https://download.jetbrains.com/go/goland-%s-aarch64.tar.gz",
},
enum.IDETypePyCharm: {
// list of versions: https://www.jetbrains.com/pycharm/download/other.html
Version: "2024.3.1.1",
Amd64: "https://download.jetbrains.com/python/pycharm-professional-%s.tar.gz",
Arm64: "https://download.jetbrains.com/python/pycharm-professional-%s-aarch64.tar.gz",
},
enum.IDETypeWebStorm: {
// list of versions: https://www.jetbrains.com/webstorm/download/other.html
Version: "2024.3.1.1",
Amd64: "https://download.jetbrains.com/webstorm/WebStorm-%s.tar.gz",
Arm64: "https://download.jetbrains.com/webstorm/WebStorm-%s-aarch64.tar.gz",
},
enum.IDETypeCLion: {
// list of versions: https://www.jetbrains.com/clion/download/other.html
Version: "2024.3.1.1",
Amd64: "https://download.jetbrains.com/cpp/CLion-%s.tar.gz",
Arm64: "https://download.jetbrains.com/cpp/CLion-%s-aarch64.tar.gz",
},
enum.IDETypePHPStorm: {
// list of versions: https://www.jetbrains.com/phpstorm/download/other.html
Version: "2024.3.1.1",
Amd64: "https://download.jetbrains.com/webide/PhpStorm-%s.tar.gz",
Arm64: "https://download.jetbrains.com/webide/PhpStorm-%s-aarch64.tar.gz",
},
enum.IDETypeRubyMine: {
// list of versions: https://www.jetbrains.com/ruby/download/other.html
Version: "2024.3.1.1",
Amd64: "https://download.jetbrains.com/ruby/RubyMine-%s.tar.gz",
Arm64: "https://download.jetbrains.com/ruby/RubyMine-%s-aarch64.tar.gz",
},
enum.IDETypeRider: {
// list of versions: https://www.jetbrains.com/ruby/download/other.html
Version: "2024.3.1.1",
Amd64: "https://download.jetbrains.com/rider/JetBrains.Rider-%s.tar.gz",
Arm64: "https://download.jetbrains.com/rider/JetBrains.Rider-%s-aarch64.tar.gz",
},
}
type JetBrainsSpecs struct {
IDEType enum.IDEType
DownloadURls JetBrainsIDEDownloadURLTemplates
}