From bbae3d105f910a25f19f2896edc5421aa1a7689f Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Thu, 31 Jul 2025 16:51:32 +0000 Subject: [PATCH 01/10] feat: add `vscode-desktop-core` module --- .../modules/vscode-desktop-core/README.md | 14 +++ .../modules/vscode-desktop-core/main.test.ts | 100 +++++++++++++++++ .../coder/modules/vscode-desktop-core/main.tf | 105 ++++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 registry/coder/modules/vscode-desktop-core/README.md create mode 100644 registry/coder/modules/vscode-desktop-core/main.test.ts create mode 100644 registry/coder/modules/vscode-desktop-core/main.tf diff --git a/registry/coder/modules/vscode-desktop-core/README.md b/registry/coder/modules/vscode-desktop-core/README.md new file mode 100644 index 00000000..ced483dd --- /dev/null +++ b/registry/coder/modules/vscode-desktop-core/README.md @@ -0,0 +1,14 @@ +--- +display_name: Coder VSCode Desktop Core +description: Building block for modules that need to link to an external VSCode-based IDE +icon: ../../../../.icons/coder.svg +verified: true +tags: [internal, library] +--- + +# VS Code Desktop Core + +> [!CAUTION] +> We do not recommend using this module directly. Instead, please consider using one of our [Tasks-compatible AI agent modules](https://registry.coder.com/modules?search=tag%3Atasks). + +The VSCode Desktop Core module is a building block for modules that need to expose access to VSCode-based IDEs. It is intended primarily for internal use by Coder to create modules for VSCode-based IDEs. diff --git a/registry/coder/modules/vscode-desktop-core/main.test.ts b/registry/coder/modules/vscode-desktop-core/main.test.ts new file mode 100644 index 00000000..e7b01966 --- /dev/null +++ b/registry/coder/modules/vscode-desktop-core/main.test.ts @@ -0,0 +1,100 @@ +import { describe, expect, it } from "bun:test"; +import { + runTerraformApply, + runTerraformInit, + testRequiredVariables, +} from "~test"; + +// hardcoded coder_app name in main.tf +const appName = "vscode-desktop"; + +const defaultVariables = { + agent_id: "foo", + web_app_icon: "/icon/code.svg", + web_app_slug: "vscode", + web_app_display_name: "VS Code Desktop", + protocol: "vscode", +} + +describe("vscode-desktop-core", async () => { + await runTerraformInit(import.meta.dir); + + testRequiredVariables(import.meta.dir, defaultVariables); + + it("default output", async () => { + const state = await runTerraformApply(import.meta.dir, defaultVariables); + expect(state.outputs.ide_uri.value).toBe( + `${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`, + ); + + const coder_app = state.resources.find( + (res) => res.type === "coder_app" && res.name === appName, + ); + + expect(coder_app).not.toBeNull(); + expect(coder_app?.instances.length).toBe(1); + expect(coder_app?.instances[0].attributes.order).toBeNull(); + }); + + it("adds folder", async () => { + const state = await runTerraformApply(import.meta.dir, { + folder: "/foo/bar", + + ...defaultVariables + }); + + expect(state.outputs.ide_uri.value).toBe( + `${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`, + ); + }); + + it("adds folder and open_recent", async () => { + const state = await runTerraformApply(import.meta.dir, { + folder: "/foo/bar", + open_recent: "true", + + ...defaultVariables, + }); + expect(state.outputs.ide_uri.value).toBe( + `${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`, + ); + }); + + it("adds folder but not open_recent", async () => { + const state = await runTerraformApply(import.meta.dir, { + folder: "/foo/bar", + openRecent: "false", + + ...defaultVariables, + }); + expect(state.outputs.ide_uri.value).toBe( + `${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`, + ); + }); + + it("adds open_recent", async () => { + const state = await runTerraformApply(import.meta.dir, { + open_recent: "true", + + ...defaultVariables, + }); + expect(state.outputs.ide_uri.value).toBe( + `${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`, + ); + }); + + it("expect order to be set", async () => { + const state = await runTerraformApply(import.meta.dir, { + web_app_order: "22", + ...defaultVariables + }); + + const coder_app = state.resources.find( + (res) => res.type === "coder_app" && res.name === appName, + ); + + expect(coder_app).not.toBeNull(); + expect(coder_app?.instances.length).toBe(1); + expect(coder_app?.instances[0].attributes.order).toBe(22); + }); +}); diff --git a/registry/coder/modules/vscode-desktop-core/main.tf b/registry/coder/modules/vscode-desktop-core/main.tf new file mode 100644 index 00000000..77b4d8f3 --- /dev/null +++ b/registry/coder/modules/vscode-desktop-core/main.tf @@ -0,0 +1,105 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.5" + } + } +} + +variable "agent_id" { + type = string + description = "The ID of a Coder agent." +} + +variable "folder" { + type = string + description = "The folder to open in the IDE." + default = "" +} + +variable "open_recent" { + type = bool + description = "Open the most recent workspace or folder. Falls back to the folder if there is no recent workspace or folder to open." + default = false +} + +variable "protocol" { + type = string + description = "The URI protocol the IDE." +} + +variable "web_app_icon" { + type = string + description = "The icon of the coder_app." +} + +variable "web_app_slug" { + type = string + description = "The slug of the coder_app." +} + +variable "web_app_display_name" { + type = string + description = "The display name of the coder_app." +} + +variable "web_app_order" { + type = number + description = "The order of the coder_app." + default = null +} + +variable "web_app_group" { + type = string + description = "The group of the coder_app." + default = null +} + +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +resource "coder_app" "vscode-desktop" { + agent_id = var.agent_id + external = true + + icon = var.web_app_icon + slug = var.web_app_slug + display_name = var.web_app_display_name + + order = var.web_app_order + group = var.web_app_group + + url = join("", [ + var.protocol, + "://coder.coder-remote/open", + "?owner=", + data.coder_workspace_owner.me.name, + "&workspace=", + data.coder_workspace.me.name, + var.folder != "" ? join("", ["&folder=", var.folder]) : "", + var.open_recent ? "&openRecent" : "", + "&url=", + data.coder_workspace.me.access_url, + "&token=$SESSION_TOKEN", + ]) + + /* + url = join("", [ + "vscode://coder.coder-remote/open", + "?owner=${data.coder_workspace_owner.me.name}", + "&workspace=${data.coder_workspace.me.name}", + var.folder != "" ? join("", ["&folder=", var.folder]) : "", + var.open_recent ? "&openRecent" : "", + "&url=${data.coder_workspace.me.access_url}", + "&token=$SESSION_TOKEN", + ]) + */ +} + +output "ide_uri" { + value = coder_app.vscode-desktop.url + description = "IDE URI." +} \ No newline at end of file From 521a8d290f48be61f1893e98c7c9f966fe3d68c9 Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Thu, 31 Jul 2025 22:40:36 +0000 Subject: [PATCH 02/10] chore: format --- registry/coder/modules/vscode-desktop-core/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/vscode-desktop-core/main.tf b/registry/coder/modules/vscode-desktop-core/main.tf index 77b4d8f3..7e675712 100644 --- a/registry/coder/modules/vscode-desktop-core/main.tf +++ b/registry/coder/modules/vscode-desktop-core/main.tf @@ -64,7 +64,7 @@ data "coder_workspace_owner" "me" {} resource "coder_app" "vscode-desktop" { agent_id = var.agent_id external = true - + icon = var.web_app_icon slug = var.web_app_slug display_name = var.web_app_display_name From 5b6db3d5af79d80bbf5df96ac826cd5d5b2d0ce4 Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Thu, 31 Jul 2025 23:15:42 +0000 Subject: [PATCH 03/10] chore: make `vscode-desktop-core` more readable --- .../coder/modules/vscode-desktop-core/main.tf | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/registry/coder/modules/vscode-desktop-core/main.tf b/registry/coder/modules/vscode-desktop-core/main.tf index 7e675712..cb988163 100644 --- a/registry/coder/modules/vscode-desktop-core/main.tf +++ b/registry/coder/modules/vscode-desktop-core/main.tf @@ -72,22 +72,8 @@ resource "coder_app" "vscode-desktop" { order = var.web_app_order group = var.web_app_group + # While the call to "join" is not strictly necessary, it makes the URL more readable. url = join("", [ - var.protocol, - "://coder.coder-remote/open", - "?owner=", - data.coder_workspace_owner.me.name, - "&workspace=", - data.coder_workspace.me.name, - var.folder != "" ? join("", ["&folder=", var.folder]) : "", - var.open_recent ? "&openRecent" : "", - "&url=", - data.coder_workspace.me.access_url, - "&token=$SESSION_TOKEN", - ]) - - /* - url = join("", [ "vscode://coder.coder-remote/open", "?owner=${data.coder_workspace_owner.me.name}", "&workspace=${data.coder_workspace.me.name}", @@ -96,7 +82,6 @@ resource "coder_app" "vscode-desktop" { "&url=${data.coder_workspace.me.access_url}", "&token=$SESSION_TOKEN", ]) - */ } output "ide_uri" { From ac47d05526c54a49ac04cd7e3858818da55044c3 Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:11:19 +0000 Subject: [PATCH 04/10] fix: use protocol variable --- registry/coder/modules/vscode-desktop-core/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/vscode-desktop-core/main.tf b/registry/coder/modules/vscode-desktop-core/main.tf index cb988163..d5987fbb 100644 --- a/registry/coder/modules/vscode-desktop-core/main.tf +++ b/registry/coder/modules/vscode-desktop-core/main.tf @@ -74,7 +74,7 @@ resource "coder_app" "vscode-desktop" { # While the call to "join" is not strictly necessary, it makes the URL more readable. url = join("", [ - "vscode://coder.coder-remote/open", + "${var.protocol}://coder.coder-remote/open", "?owner=${data.coder_workspace_owner.me.name}", "&workspace=${data.coder_workspace.me.name}", var.folder != "" ? join("", ["&folder=", var.folder]) : "", From 544571bc54244d6b52171ad8de47ac8f5599f54b Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:27:16 +0000 Subject: [PATCH 05/10] chore: update readme --- .../modules/vscode-desktop-core/README.md | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/registry/coder/modules/vscode-desktop-core/README.md b/registry/coder/modules/vscode-desktop-core/README.md index ced483dd..fd847a64 100644 --- a/registry/coder/modules/vscode-desktop-core/README.md +++ b/registry/coder/modules/vscode-desktop-core/README.md @@ -9,6 +9,25 @@ tags: [internal, library] # VS Code Desktop Core > [!CAUTION] -> We do not recommend using this module directly. Instead, please consider using one of our [Tasks-compatible AI agent modules](https://registry.coder.com/modules?search=tag%3Atasks). +> We do not recommend using this module directly. Instead, please consider using one of our [Desktop IDE modules](https://registry.coder.com/modules?search=tag%3Aide). The VSCode Desktop Core module is a building block for modules that need to expose access to VSCode-based IDEs. It is intended primarily for internal use by Coder to create modules for VSCode-based IDEs. + +```tf +module "vscode-desktop-core" { + source = "registry.coder.com/coder/vscode-desktop-core/coder" + version = "1.0.1" + + agent_id = var.agent_id + + web_app_icon = "/icon/code.svg" + web_app_slug = "vscode" + web_app_display_name = "VS Code Desktop" + web_app_order = var.order + web_app_group = var.group + + folder = var.folder + open_recent = var.open_recent + protocol = "vscode" +} +``` From 14bb16adb83537ac590c0e8b98d8687dae006582 Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:28:14 +0000 Subject: [PATCH 06/10] chore: fmt --- registry/coder/modules/vscode-desktop-core/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/coder/modules/vscode-desktop-core/README.md b/registry/coder/modules/vscode-desktop-core/README.md index fd847a64..d95e2da2 100644 --- a/registry/coder/modules/vscode-desktop-core/README.md +++ b/registry/coder/modules/vscode-desktop-core/README.md @@ -15,8 +15,8 @@ The VSCode Desktop Core module is a building block for modules that need to expo ```tf module "vscode-desktop-core" { - source = "registry.coder.com/coder/vscode-desktop-core/coder" - version = "1.0.1" + source = "registry.coder.com/coder/vscode-desktop-core/coder" + version = "1.0.1" agent_id = var.agent_id From 4fd0c76897051a164afd46e96b29fcd1482f5eaa Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Sat, 2 Aug 2025 15:37:13 +0000 Subject: [PATCH 07/10] chore: revert version to 1.0.0 --- registry/coder/modules/vscode-desktop-core/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/vscode-desktop-core/README.md b/registry/coder/modules/vscode-desktop-core/README.md index d95e2da2..0e98dafb 100644 --- a/registry/coder/modules/vscode-desktop-core/README.md +++ b/registry/coder/modules/vscode-desktop-core/README.md @@ -16,7 +16,7 @@ The VSCode Desktop Core module is a building block for modules that need to expo ```tf module "vscode-desktop-core" { source = "registry.coder.com/coder/vscode-desktop-core/coder" - version = "1.0.1" + version = "1.0.0" agent_id = var.agent_id From 1a62c6077bb1dd5e3876dfd7f68fc8c30fd942fc Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Sat, 2 Aug 2025 15:38:59 +0000 Subject: [PATCH 08/10] chore: rename `web_app_*` params to `coder_app_*` --- .../modules/vscode-desktop-core/README.md | 10 +++++----- .../modules/vscode-desktop-core/main.test.ts | 8 ++++---- .../coder/modules/vscode-desktop-core/main.tf | 20 +++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/registry/coder/modules/vscode-desktop-core/README.md b/registry/coder/modules/vscode-desktop-core/README.md index 0e98dafb..ae641f0d 100644 --- a/registry/coder/modules/vscode-desktop-core/README.md +++ b/registry/coder/modules/vscode-desktop-core/README.md @@ -20,11 +20,11 @@ module "vscode-desktop-core" { agent_id = var.agent_id - web_app_icon = "/icon/code.svg" - web_app_slug = "vscode" - web_app_display_name = "VS Code Desktop" - web_app_order = var.order - web_app_group = var.group + coder_app_icon = "/icon/code.svg" + coder_app_slug = "vscode" + coder_app_display_name = "VS Code Desktop" + coder_app_order = var.order + coder_app_group = var.group folder = var.folder open_recent = var.open_recent diff --git a/registry/coder/modules/vscode-desktop-core/main.test.ts b/registry/coder/modules/vscode-desktop-core/main.test.ts index e7b01966..1135c9e0 100644 --- a/registry/coder/modules/vscode-desktop-core/main.test.ts +++ b/registry/coder/modules/vscode-desktop-core/main.test.ts @@ -10,9 +10,9 @@ const appName = "vscode-desktop"; const defaultVariables = { agent_id: "foo", - web_app_icon: "/icon/code.svg", - web_app_slug: "vscode", - web_app_display_name: "VS Code Desktop", + coder_app_icon: "/icon/code.svg", + coder_app_slug: "vscode", + coder_app_display_name: "VS Code Desktop", protocol: "vscode", } @@ -85,7 +85,7 @@ describe("vscode-desktop-core", async () => { it("expect order to be set", async () => { const state = await runTerraformApply(import.meta.dir, { - web_app_order: "22", + coder_app_order: "22", ...defaultVariables }); diff --git a/registry/coder/modules/vscode-desktop-core/main.tf b/registry/coder/modules/vscode-desktop-core/main.tf index d5987fbb..035f325e 100644 --- a/registry/coder/modules/vscode-desktop-core/main.tf +++ b/registry/coder/modules/vscode-desktop-core/main.tf @@ -31,28 +31,28 @@ variable "protocol" { description = "The URI protocol the IDE." } -variable "web_app_icon" { +variable "coder_app_icon" { type = string description = "The icon of the coder_app." } -variable "web_app_slug" { +variable "coder_app_slug" { type = string description = "The slug of the coder_app." } -variable "web_app_display_name" { +variable "coder_app_display_name" { type = string description = "The display name of the coder_app." } -variable "web_app_order" { +variable "coder_app_order" { type = number description = "The order of the coder_app." default = null } -variable "web_app_group" { +variable "coder_app_group" { type = string description = "The group of the coder_app." default = null @@ -65,12 +65,12 @@ resource "coder_app" "vscode-desktop" { agent_id = var.agent_id external = true - icon = var.web_app_icon - slug = var.web_app_slug - display_name = var.web_app_display_name + icon = var.coder_app_icon + slug = var.coder_app_slug + display_name = var.coder_app_display_name - order = var.web_app_order - group = var.web_app_group + order = var.coder_app_order + group = var.coder_app_group # While the call to "join" is not strictly necessary, it makes the URL more readable. url = join("", [ From 03aa37b378f5af96edde74c18f8ad708e4a8daa7 Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Sat, 2 Aug 2025 15:49:33 +0000 Subject: [PATCH 09/10] chore: add `SESSION_TOKEN` disclaimer --- registry/coder/modules/vscode-desktop-core/main.tf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/registry/coder/modules/vscode-desktop-core/main.tf b/registry/coder/modules/vscode-desktop-core/main.tf index 035f325e..2c9c4646 100644 --- a/registry/coder/modules/vscode-desktop-core/main.tf +++ b/registry/coder/modules/vscode-desktop-core/main.tf @@ -80,6 +80,8 @@ resource "coder_app" "vscode-desktop" { var.folder != "" ? join("", ["&folder=", var.folder]) : "", var.open_recent ? "&openRecent" : "", "&url=${data.coder_workspace.me.access_url}", + # NOTE: There is a protocol whitelist for the token replacement, so this will only work with the protocols hardcoded in the front-end. + # (https://github.com/coder/coder/blob/6ba4b5bbc95e2e528d7f5b1e31fffa200ae1a6db/site/src/modules/apps/apps.ts#L18) "&token=$SESSION_TOKEN", ]) } From 255b1ed969a8413d15ecbdb9f13db6bab4be0376 Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:24:03 +0200 Subject: [PATCH 10/10] chore: make library aspect clearer Co-authored-by: Atif Ali --- registry/coder/modules/vscode-desktop-core/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/vscode-desktop-core/README.md b/registry/coder/modules/vscode-desktop-core/README.md index ae641f0d..f914f7d9 100644 --- a/registry/coder/modules/vscode-desktop-core/README.md +++ b/registry/coder/modules/vscode-desktop-core/README.md @@ -11,7 +11,7 @@ tags: [internal, library] > [!CAUTION] > We do not recommend using this module directly. Instead, please consider using one of our [Desktop IDE modules](https://registry.coder.com/modules?search=tag%3Aide). -The VSCode Desktop Core module is a building block for modules that need to expose access to VSCode-based IDEs. It is intended primarily for internal use by Coder to create modules for VSCode-based IDEs. +The VSCode Desktop Core module is a building block for modules that need to expose access to VSCode-based IDEs. It is intended primarily to be used as a library to create modules for VSCode-based IDEs. ```tf module "vscode-desktop-core" {