diff --git a/cmd/daytona/config/const.go b/cmd/daytona/config/const.go index bd6de4a0d1..69ddf292e1 100644 --- a/cmd/daytona/config/const.go +++ b/cmd/daytona/config/const.go @@ -25,6 +25,7 @@ func GetBinaryUrls() map[os.OperatingSystem]string { func GetIdeList() []Ide { ides := []Ide{ {"vscode", "VS Code"}, + {"code-insiders", "VS Code Insiders"}, {"browser", "VS Code - Browser"}, {"cursor", "Cursor"}, {"ssh", "Terminal SSH"}, diff --git a/docs/daytona_code.md b/docs/daytona_code.md index f376ea8cce..46b9130223 100644 --- a/docs/daytona_code.md +++ b/docs/daytona_code.md @@ -9,7 +9,7 @@ daytona code [WORKSPACE] [PROJECT] [flags] ### Options ``` - -i, --ide string Specify the IDE (vscode, browser, cursor, ssh, jupyter, fleet, zed, clion, goland, intellij, phpstorm, pycharm, rider, rubymine, webstorm) + -i, --ide string Specify the IDE (vscode, code-insiders, browser, cursor, ssh, jupyter, fleet, zed, clion, goland, intellij, phpstorm, pycharm, rider, rubymine, webstorm) -y, --yes Automatically confirm any prompts ``` diff --git a/docs/daytona_create.md b/docs/daytona_create.md index 80accb7306..8be82e5183 100644 --- a/docs/daytona_create.md +++ b/docs/daytona_create.md @@ -17,7 +17,7 @@ daytona create [REPOSITORY_URL | PROJECT_CONFIG_NAME]... [flags] --devcontainer-path string Automatically assign the devcontainer builder with the path passed as the flag value --env stringArray Specify environment variables (e.g. --env 'KEY1=VALUE1' --env 'KEY2=VALUE2' ...') --git-provider-config string Specify the Git provider configuration ID or alias - -i, --ide string Specify the IDE (vscode, browser, cursor, ssh, jupyter, fleet, zed, clion, goland, intellij, phpstorm, pycharm, rider, rubymine, webstorm) + -i, --ide string Specify the IDE (vscode, code-insiders, browser, cursor, ssh, jupyter, fleet, zed, clion, goland, intellij, phpstorm, pycharm, rider, rubymine, webstorm) --manual Manually enter the Git repository --multi-project Workspace with multiple projects/repos --name string Specify the workspace name diff --git a/hack/docs/daytona_code.yaml b/hack/docs/daytona_code.yaml index 840cdf1741..6f2af3641a 100644 --- a/hack/docs/daytona_code.yaml +++ b/hack/docs/daytona_code.yaml @@ -5,7 +5,7 @@ options: - name: ide shorthand: i usage: | - Specify the IDE (vscode, browser, cursor, ssh, jupyter, fleet, zed, clion, goland, intellij, phpstorm, pycharm, rider, rubymine, webstorm) + Specify the IDE (vscode, code-insiders, browser, cursor, ssh, jupyter, fleet, zed, clion, goland, intellij, phpstorm, pycharm, rider, rubymine, webstorm) - name: "yes" shorthand: "y" default_value: "false" diff --git a/hack/docs/daytona_create.yaml b/hack/docs/daytona_create.yaml index d5ff472400..7e716aa97e 100644 --- a/hack/docs/daytona_create.yaml +++ b/hack/docs/daytona_create.yaml @@ -28,7 +28,7 @@ options: - name: ide shorthand: i usage: | - Specify the IDE (vscode, browser, cursor, ssh, jupyter, fleet, zed, clion, goland, intellij, phpstorm, pycharm, rider, rubymine, webstorm) + Specify the IDE (vscode, code-insiders, browser, cursor, ssh, jupyter, fleet, zed, clion, goland, intellij, phpstorm, pycharm, rider, rubymine, webstorm) - name: manual default_value: "false" usage: Manually enter the Git repository diff --git a/pkg/cmd/ide.go b/pkg/cmd/ide.go index c7af97a507..9ee95117ad 100644 --- a/pkg/cmd/ide.go +++ b/pkg/cmd/ide.go @@ -46,6 +46,11 @@ var ideCmd = &cobra.Command{ switch chosenIde.Id { case "vscode": ide_util.CheckAndAlertVSCodeInstalled() + case "code-insiders": + _, err := ide_util.GetVSCodeInsidersBinaryPath() + if err != nil { + log.Error(err) + } case "cursor": _, err := ide_util.GetCursorBinaryPath() if err != nil { diff --git a/pkg/cmd/workspace/code.go b/pkg/cmd/workspace/code.go index 59d356fbae..af658e6373 100644 --- a/pkg/cmd/workspace/code.go +++ b/pkg/cmd/workspace/code.go @@ -181,6 +181,8 @@ func openIDE(ideId string, activeProfile config.Profile, workspaceId string, pro switch ideId { case "vscode": return ide.OpenVSCode(activeProfile, workspaceId, projectName, projectProviderMetadata, gpgKey) + case "code-insiders": + return ide.OpenVSCodeInsiders(activeProfile, workspaceId, projectName, projectProviderMetadata, gpgKey) case "ssh": return ide.OpenTerminalSsh(activeProfile, workspaceId, projectName, gpgKey, nil) case "browser": diff --git a/pkg/ide/vscode-insiders.go b/pkg/ide/vscode-insiders.go new file mode 100644 index 0000000000..e204f3be1b --- /dev/null +++ b/pkg/ide/vscode-insiders.go @@ -0,0 +1,67 @@ +// Copyright 2024 Daytona Platforms Inc. +// SPDX-License-Identifier: Apache-2.0 + +package ide + +import ( + "errors" + "fmt" + "os/exec" + + "github.com/daytonaio/daytona/cmd/daytona/config" + "github.com/daytonaio/daytona/internal/util" + "github.com/daytonaio/daytona/pkg/build/devcontainer" +) + +func OpenVSCodeInsiders(activeProfile config.Profile, workspaceId string, projectName string, projectProviderMetadata string, gpgKey string) error { + path, err := GetVSCodeInsidersBinaryPath() + if err != nil { + return err + } + err = installRemoteSSHExtension(path) + if err != nil { + return err + } + + projectHostname := config.GetProjectHostname(activeProfile.Id, workspaceId, projectName) + + projectDir, err := util.GetProjectDir(activeProfile, workspaceId, projectName, gpgKey) + if err != nil { + return err + } + + commandArgument := fmt.Sprintf("vscode-remote://ssh-remote+%s/%s", projectHostname, projectDir) + + vscCommand := exec.Command(path, "--disable-extension", "ms-vscode-remote.remote-containers", "--folder-uri", commandArgument) + + err = vscCommand.Run() + if err != nil { + return err + } + + if projectProviderMetadata == "" { + return nil + } + + return setupVSCodeCustomizations(projectHostname, projectProviderMetadata, devcontainer.Vscode, "*/.vscode-server-insiders/*/bin/code-server-insiders", "$HOME/.vscode-server-insiders/data/Machine/settings.json", ".daytona-customizations-lock-vscode-insiders") +} + +func GetVSCodeInsidersBinaryPath() (string, error) { + path, err := exec.LookPath("code-insiders") + if err == nil { + return path, err + } + + redBold := "\033[1;31m" // ANSI escape code for red and bold + reset := "\033[0m" // ANSI escape code to reset text formatting + + errorMessage := "Please install Visual Studio Code Insiders from https://code.visualstudio.com/insiders/\n\n" + infoMessage := ` +If you have already installed Visual Studio Code Insiders, please ensure it is added to your PATH environment variable. +You can verify this by running the following command in your terminal: + + code-insiders +` + + return "", errors.New(redBold + errorMessage + reset + infoMessage) +} diff --git a/pkg/ide/vscode.go b/pkg/ide/vscode.go index faf19b6364..35fe0370f8 100644 --- a/pkg/ide/vscode.go +++ b/pkg/ide/vscode.go @@ -21,7 +21,7 @@ import ( func OpenVSCode(activeProfile config.Profile, workspaceId string, projectName string, projectProviderMetadata string, gpgKey string) error { CheckAndAlertVSCodeInstalled() - err := installRemoteSSHExtension() + err := installRemoteSSHExtension("code") if err != nil { return err } @@ -201,15 +201,15 @@ func isVSCodeInstalled() error { return err } -func installRemoteSSHExtension() error { - output, err := exec.Command("code", "--list-extensions").Output() +func installRemoteSSHExtension(binaryPath string) error { + output, err := exec.Command(binaryPath, "--list-extensions").Output() if err != nil { return err } if !strings.Contains(string(output), "ms-vscode-remote.remote-ssh") { fmt.Println("Installing Remote SSH extension...") - err = exec.Command("code", "--install-extension", "ms-vscode-remote.remote-ssh").Run() + err = exec.Command(binaryPath, "--install-extension", "ms-vscode-remote.remote-ssh").Run() if err != nil { return err }