From 0021a9fe7d5d426721fc11e7901d1b76737588be Mon Sep 17 00:00:00 2001 From: Phorcys <57866459+phorcys420@users.noreply.github.com> Date: Thu, 27 Nov 2025 13:35:40 +0100 Subject: [PATCH] feat: update vscode-based desktop IDE modules to use `vscode-desktop-core` (#279) --- registry/coder/modules/cursor/README.md | 7 +- registry/coder/modules/cursor/main.test.ts | 20 +- registry/coder/modules/cursor/main.tf | 39 ++-- registry/coder/modules/kiro/README.md | 7 +- registry/coder/modules/kiro/kiro.tftest.hcl | 53 ------ registry/coder/modules/kiro/main.test.ts | 46 +---- registry/coder/modules/kiro/main.tf | 51 ++---- .../modules/vscode-desktop-core/README.md | 16 +- .../modules/vscode-desktop-core/main.test.ts | 171 +++++++++++------- .../coder/modules/vscode-desktop-core/main.tf | 43 +++-- .../coder/modules/vscode-desktop/README.md | 4 +- .../coder/modules/vscode-desktop/main.test.ts | 20 +- registry/coder/modules/vscode-desktop/main.tf | 39 ++-- registry/coder/modules/windsurf/README.md | 7 +- registry/coder/modules/windsurf/main.test.ts | 20 +- registry/coder/modules/windsurf/main.tf | 41 ++--- .../cytoshahar/modules/positron/main.test.ts | 20 +- registry/cytoshahar/modules/positron/main.tf | 52 +++--- test/test.ts | 2 + 19 files changed, 270 insertions(+), 388 deletions(-) diff --git a/registry/coder/modules/cursor/README.md b/registry/coder/modules/cursor/README.md index 4bb2f719..7a870ac0 100644 --- a/registry/coder/modules/cursor/README.md +++ b/registry/coder/modules/cursor/README.md @@ -16,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "cursor" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/cursor/coder" - version = "1.3.3" + version = "1.4.0" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ module "cursor" { module "cursor" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/cursor/coder" - version = "1.3.3" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -45,7 +45,7 @@ The following example configures Cursor to use the GitHub MCP server with authen module "cursor" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/cursor/coder" - version = "1.3.3" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/home/coder/project" mcp = jsonencode({ @@ -58,6 +58,7 @@ module "cursor" { "type" : "http" } + } }) } diff --git a/registry/coder/modules/cursor/main.test.ts b/registry/coder/modules/cursor/main.test.ts index 618f987e..fdba8501 100644 --- a/registry/coder/modules/cursor/main.test.ts +++ b/registry/coder/modules/cursor/main.test.ts @@ -26,7 +26,10 @@ describe("cursor", async () => { ); const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "cursor", + (res) => + res.type === "coder_app" && + res.module === "module.vscode-desktop-core" && + res.name === "vscode-desktop", ); expect(coder_app).not.toBeNull(); @@ -76,21 +79,6 @@ describe("cursor", async () => { ); }); - it("expect order to be set", async () => { - const state = await runTerraformApply(import.meta.dir, { - agent_id: "foo", - order: "22", - }); - - const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "cursor", - ); - - expect(coder_app).not.toBeNull(); - expect(coder_app?.instances.length).toBe(1); - expect(coder_app?.instances[0].attributes.order).toBe(22); - }); - it("writes ~/.cursor/mcp.json when mcp provided", async () => { const id = await runContainer("alpine"); try { diff --git a/registry/coder/modules/cursor/main.tf b/registry/coder/modules/cursor/main.tf index d26000a8..0c0f8aa2 100644 --- a/registry/coder/modules/cursor/main.tf +++ b/registry/coder/modules/cursor/main.tf @@ -64,26 +64,21 @@ locals { mcp_b64 = var.mcp != "" ? base64encode(var.mcp) : "" } -resource "coder_app" "cursor" { - agent_id = var.agent_id - external = true - icon = "/icon/cursor.svg" - slug = var.slug - display_name = var.display_name - order = var.order - group = var.group - url = join("", [ - "cursor://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", - ]) +module "vscode-desktop-core" { + source = "registry.coder.com/coder/vscode-desktop-core/coder" + version = "1.0.0" + + agent_id = var.agent_id + + coder_app_icon = "/icon/cursor.svg" + coder_app_slug = var.slug + coder_app_display_name = var.display_name + coder_app_order = var.order + coder_app_group = var.group + + folder = var.folder + open_recent = var.open_recent + protocol = "cursor" } resource "coder_script" "cursor_mcp" { @@ -103,6 +98,6 @@ resource "coder_script" "cursor_mcp" { } output "cursor_url" { - value = coder_app.cursor.url + value = module.vscode-desktop-core.ide_uri description = "Cursor IDE Desktop URL." -} +} \ No newline at end of file diff --git a/registry/coder/modules/kiro/README.md b/registry/coder/modules/kiro/README.md index e7ecd1d7..23c17885 100644 --- a/registry/coder/modules/kiro/README.md +++ b/registry/coder/modules/kiro/README.md @@ -18,7 +18,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "kiro" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/kiro/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.main.id } ``` @@ -31,7 +31,7 @@ module "kiro" { module "kiro" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/kiro/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -47,7 +47,7 @@ The following example configures Kiro to use the GitHub MCP server with authenti module "kiro" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/kiro/coder" - version = "1.1.1" + version = "1.2.0" agent_id = coder_agent.main.id folder = "/home/coder/project" mcp = jsonencode({ @@ -60,6 +60,7 @@ module "kiro" { "type" : "http" } + } }) } diff --git a/registry/coder/modules/kiro/kiro.tftest.hcl b/registry/coder/modules/kiro/kiro.tftest.hcl index b132551a..5fb51311 100644 --- a/registry/coder/modules/kiro/kiro.tftest.hcl +++ b/registry/coder/modules/kiro/kiro.tftest.hcl @@ -17,11 +17,6 @@ run "default_output" { condition = output.kiro_url == "kiro://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN" error_message = "Default kiro_url must match expected value" } - - assert { - condition = coder_app.kiro.order == null - error_message = "coder_app order must be null by default" - } } run "adds_folder" { @@ -53,54 +48,6 @@ run "folder_and_open_recent" { } } -run "custom_slug_display_name" { - command = plan - - variables { - agent_id = "foo" - slug = "kiro-ai" - display_name = "Kiro AI IDE" - } - - assert { - condition = coder_app.kiro.slug == "kiro-ai" - error_message = "coder_app slug must be set to kiro-ai" - } - - assert { - condition = coder_app.kiro.display_name == "Kiro AI IDE" - error_message = "coder_app display_name must be set to Kiro AI IDE" - } -} - -run "sets_order" { - command = plan - - variables { - agent_id = "foo" - order = 5 - } - - assert { - condition = coder_app.kiro.order == 5 - error_message = "coder_app order must be set to 5" - } -} - -run "sets_group" { - command = plan - - variables { - agent_id = "foo" - group = "AI IDEs" - } - - assert { - condition = coder_app.kiro.group == "AI IDEs" - error_message = "coder_app group must be set to AI IDEs" - } -} - run "writes_mcp_json" { command = plan diff --git a/registry/coder/modules/kiro/main.test.ts b/registry/coder/modules/kiro/main.test.ts index 2d268a84..608abf89 100644 --- a/registry/coder/modules/kiro/main.test.ts +++ b/registry/coder/modules/kiro/main.test.ts @@ -26,7 +26,10 @@ describe("kiro", async () => { ); const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "kiro", + (res) => + res.type === "coder_app" && + res.module === "module.vscode-desktop-core" && + res.name === "vscode-desktop", ); expect(coder_app).not.toBeNull(); @@ -55,47 +58,6 @@ describe("kiro", async () => { ); }); - it("custom slug and display_name", async () => { - const state = await runTerraformApply(import.meta.dir, { - agent_id: "foo", - slug: "kiro-ai", - display_name: "Kiro AI IDE", - }); - - const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "kiro", - ); - - expect(coder_app?.instances[0].attributes.slug).toBe("kiro-ai"); - expect(coder_app?.instances[0].attributes.display_name).toBe("Kiro AI IDE"); - }); - - it("sets order", async () => { - const state = await runTerraformApply(import.meta.dir, { - agent_id: "foo", - order: "5", - }); - - const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "kiro", - ); - - expect(coder_app?.instances[0].attributes.order).toBe(5); - }); - - it("sets group", async () => { - const state = await runTerraformApply(import.meta.dir, { - agent_id: "foo", - group: "AI IDEs", - }); - - const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "kiro", - ); - - expect(coder_app?.instances[0].attributes.group).toBe("AI IDEs"); - }); - it("writes ~/.kiro/settings/mcp.json when mcp provided", async () => { const id = await runContainer("alpine"); try { diff --git a/registry/coder/modules/kiro/main.tf b/registry/coder/modules/kiro/main.tf index fed8407b..c48364bc 100644 --- a/registry/coder/modules/kiro/main.tf +++ b/registry/coder/modules/kiro/main.tf @@ -38,18 +38,6 @@ variable "group" { default = null } -variable "slug" { - type = string - description = "The slug of the app." - default = "kiro" -} - -variable "display_name" { - type = string - description = "The display name of the app." - default = "Kiro IDE" -} - variable "mcp" { type = string description = "JSON-encoded string to configure MCP servers for Kiro. When set, writes ~/.kiro/settings/mcp.json." @@ -63,26 +51,21 @@ locals { mcp_b64 = var.mcp != "" ? base64encode(var.mcp) : "" } -resource "coder_app" "kiro" { - agent_id = var.agent_id - external = true - icon = "/icon/kiro.svg" - slug = var.slug - display_name = var.display_name - order = var.order - group = var.group - url = join("", [ - "kiro://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", - ]) +module "vscode-desktop-core" { + source = "registry.coder.com/coder/vscode-desktop-core/coder" + version = "1.0.0" + + agent_id = var.agent_id + + coder_app_icon = "/icon/kiro.svg" + coder_app_slug = "kiro-ai" + coder_app_display_name = "Kiro AI IDE" + coder_app_order = var.order + coder_app_group = var.group + + folder = var.folder + open_recent = var.open_recent + protocol = "kiro" } resource "coder_script" "kiro_mcp" { @@ -102,6 +85,6 @@ resource "coder_script" "kiro_mcp" { } output "kiro_url" { - value = coder_app.kiro.url + value = module.vscode-desktop-core.ide_uri description = "Kiro IDE URL." -} +} \ No newline at end of file diff --git a/registry/coder/modules/vscode-desktop-core/README.md b/registry/coder/modules/vscode-desktop-core/README.md index 7ae070dd..d95e2da2 100644 --- a/registry/coder/modules/vscode-desktop-core/README.md +++ b/registry/coder/modules/vscode-desktop-core/README.md @@ -1,5 +1,5 @@ --- -display_name: VSCode Desktop Core +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 @@ -11,20 +11,20 @@ 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 to be used as a library 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 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.0" + version = "1.0.1" agent_id = var.agent_id - 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 + 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 diff --git a/registry/coder/modules/vscode-desktop-core/main.test.ts b/registry/coder/modules/vscode-desktop-core/main.test.ts index 6777b1d5..46c51227 100644 --- a/registry/coder/modules/vscode-desktop-core/main.test.ts +++ b/registry/coder/modules/vscode-desktop-core/main.test.ts @@ -10,9 +10,11 @@ const appName = "vscode-desktop"; const defaultVariables = { agent_id: "foo", - coder_app_icon: "/icon/code.svg", - coder_app_slug: "vscode", - coder_app_display_name: "VS Code Desktop", + + web_app_icon: "/icon/code.svg", + web_app_slug: "vscode", + web_app_display_name: "VS Code Desktop", + protocol: "vscode", }; @@ -21,80 +23,115 @@ describe("vscode-desktop-core", async () => { 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`, - ); + describe("coder_app", () => { + describe("IDE URI attributes", () => { + 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, - ); + 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(); - }); + 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", + it("adds folder", async () => { + const state = await runTerraformApply(import.meta.dir, { + folder: "/foo/bar", - ...defaultVariables, + ...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`, + ); + }); }); - 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("sets custom slug and display_name", async () => { + const state = await runTerraformApply(import.meta.dir, defaultVariables); - it("adds folder and open_recent", async () => { - const state = await runTerraformApply(import.meta.dir, { - folder: "/foo/bar", - open_recent: "true", + const coder_app = state.resources.find( + (res) => res.type === "coder_app" && res.name === appName, + ); - ...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, { - coder_app_order: "22", - ...defaultVariables, + expect(coder_app?.instances[0].attributes.slug).toBe( + defaultVariables.web_app_slug, + ); + expect(coder_app?.instances[0].attributes.display_name).toBe( + defaultVariables.web_app_display_name, + ); }); - const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === appName, - ); + it("sets order", async () => { + const state = await runTerraformApply(import.meta.dir, { + web_app_order: "5", - expect(coder_app).not.toBeNull(); - expect(coder_app?.instances.length).toBe(1); - expect(coder_app?.instances[0].attributes.order).toBe(22); + ...defaultVariables, + }); + + const coder_app = state.resources.find( + (res) => res.type === "coder_app" && res.name === appName, + ); + + expect(coder_app?.instances[0].attributes.order).toBe(5); + }); + + it("sets group", async () => { + const state = await runTerraformApply(import.meta.dir, { + web_app_group: "web-app-group", + + ...defaultVariables, + }); + + const coder_app = state.resources.find( + (res) => res.type === "coder_app" && res.name === appName, + ); + + expect(coder_app?.instances[0].attributes.group).toBe("web-app-group"); + }); }); }); diff --git a/registry/coder/modules/vscode-desktop-core/main.tf b/registry/coder/modules/vscode-desktop-core/main.tf index 3bed8e79..7e675712 100644 --- a/registry/coder/modules/vscode-desktop-core/main.tf +++ b/registry/coder/modules/vscode-desktop-core/main.tf @@ -28,31 +28,31 @@ variable "open_recent" { variable "protocol" { type = string - description = "The URI protocol for the IDE." + description = "The URI protocol the IDE." } -variable "coder_app_icon" { +variable "web_app_icon" { type = string description = "The icon of the coder_app." } -variable "coder_app_slug" { +variable "web_app_slug" { type = string description = "The slug of the coder_app." } -variable "coder_app_display_name" { +variable "web_app_display_name" { type = string description = "The display name of the coder_app." } -variable "coder_app_order" { +variable "web_app_order" { type = number description = "The order of the coder_app." default = null } -variable "coder_app_group" { +variable "web_app_group" { type = string description = "The group of the coder_app." default = null @@ -65,25 +65,38 @@ resource "coder_app" "vscode-desktop" { agent_id = var.agent_id external = true - icon = var.coder_app_icon - slug = var.coder_app_slug - display_name = var.coder_app_display_name + icon = var.web_app_icon + slug = var.web_app_slug + display_name = var.web_app_display_name - order = var.coder_app_order - group = var.coder_app_group + 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", + 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}", - # 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", ]) + */ } output "ide_uri" { diff --git a/registry/coder/modules/vscode-desktop/README.md b/registry/coder/modules/vscode-desktop/README.md index cb4585be..56f39bf7 100644 --- a/registry/coder/modules/vscode-desktop/README.md +++ b/registry/coder/modules/vscode-desktop/README.md @@ -16,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "vscode" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/vscode-desktop/coder" - version = "1.1.2" + version = "1.2.0" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ module "vscode" { module "vscode" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/vscode-desktop/coder" - version = "1.1.2" + version = "1.2.0" agent_id = coder_agent.main.id folder = "/home/coder/project" } diff --git a/registry/coder/modules/vscode-desktop/main.test.ts b/registry/coder/modules/vscode-desktop/main.test.ts index b59ef5dc..3c1321b9 100644 --- a/registry/coder/modules/vscode-desktop/main.test.ts +++ b/registry/coder/modules/vscode-desktop/main.test.ts @@ -22,7 +22,10 @@ describe("vscode-desktop", async () => { ); const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "vscode", + (res) => + res.type === "coder_app" && + res.module === "module.vscode-desktop-core" && + res.name === "vscode-desktop", ); expect(coder_app).not.toBeNull(); @@ -71,19 +74,4 @@ describe("vscode-desktop", async () => { "vscode://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, { - agent_id: "foo", - order: "22", - }); - - const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "vscode", - ); - - 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/main.tf b/registry/coder/modules/vscode-desktop/main.tf index f93d14e3..c9e6dd35 100644 --- a/registry/coder/modules/vscode-desktop/main.tf +++ b/registry/coder/modules/vscode-desktop/main.tf @@ -38,33 +38,24 @@ variable "group" { default = null } -data "coder_workspace" "me" {} -data "coder_workspace_owner" "me" {} +module "vscode-desktop-core" { + source = "registry.coder.com/coder/vscode-desktop-core/coder" + version = "1.0.0" -resource "coder_app" "vscode" { - agent_id = var.agent_id - external = true - icon = "/icon/code.svg" - slug = "vscode" - display_name = "VS Code Desktop" - order = var.order - group = var.group + agent_id = var.agent_id - 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", - ]) + 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 + protocol = "vscode" } output "vscode_url" { - value = coder_app.vscode.url + value = module.vscode-desktop-core.ide_uri description = "VS Code Desktop URL." -} +} \ No newline at end of file diff --git a/registry/coder/modules/windsurf/README.md b/registry/coder/modules/windsurf/README.md index 926dae5a..77c57d40 100644 --- a/registry/coder/modules/windsurf/README.md +++ b/registry/coder/modules/windsurf/README.md @@ -16,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "windsurf" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/windsurf/coder" - version = "1.2.1" + version = "1.3.0" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ module "windsurf" { module "windsurf" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/windsurf/coder" - version = "1.2.1" + version = "1.3.0" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -45,7 +45,7 @@ The following example configures Windsurf to use the GitHub MCP server with auth module "windsurf" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/windsurf/coder" - version = "1.2.1" + version = "1.3.0" agent_id = coder_agent.main.id folder = "/home/coder/project" mcp = jsonencode({ @@ -58,6 +58,7 @@ module "windsurf" { "type" : "http" } + } }) } diff --git a/registry/coder/modules/windsurf/main.test.ts b/registry/coder/modules/windsurf/main.test.ts index f5aa5e1f..27e61039 100644 --- a/registry/coder/modules/windsurf/main.test.ts +++ b/registry/coder/modules/windsurf/main.test.ts @@ -26,7 +26,10 @@ describe("windsurf", async () => { ); const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "windsurf", + (res) => + res.type === "coder_app" && + res.module === "module.vscode-desktop-core" && + res.name === "vscode-desktop", ); expect(coder_app).not.toBeNull(); @@ -76,21 +79,6 @@ describe("windsurf", async () => { ); }); - it("expect order to be set", async () => { - const state = await runTerraformApply(import.meta.dir, { - agent_id: "foo", - order: 22, - }); - - const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "windsurf", - ); - - expect(coder_app).not.toBeNull(); - expect(coder_app?.instances.length).toBe(1); - expect(coder_app?.instances[0].attributes.order).toBe(22); - }); - it("writes ~/.codeium/windsurf/mcp_config.json when mcp provided", async () => { const id = await runContainer("alpine"); try { diff --git a/registry/coder/modules/windsurf/main.tf b/registry/coder/modules/windsurf/main.tf index b75f8638..3ec29d5b 100644 --- a/registry/coder/modules/windsurf/main.tf +++ b/registry/coder/modules/windsurf/main.tf @@ -16,7 +16,7 @@ variable "agent_id" { variable "folder" { type = string - description = "The folder to open in Cursor IDE." + description = "The folder to open in Windsurf Editor." default = "" } @@ -63,26 +63,21 @@ locals { mcp_b64 = var.mcp != "" ? base64encode(var.mcp) : "" } -resource "coder_app" "windsurf" { - agent_id = var.agent_id - external = true - icon = "/icon/windsurf.svg" - slug = var.slug - display_name = var.display_name - order = var.order - group = var.group - url = join("", [ - "windsurf://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", - ]) +module "vscode-desktop-core" { + source = "registry.coder.com/coder/vscode-desktop-core/coder" + version = "1.0.0" + + agent_id = var.agent_id + + coder_app_icon = "/icon/windsurf.svg" + coder_app_slug = "windsurf" + coder_app_display_name = "Windsurf Editor" + coder_app_order = var.order + coder_app_group = var.group + + folder = var.folder + open_recent = var.open_recent + protocol = "windsurf" } resource "coder_script" "windsurf_mcp" { @@ -102,6 +97,6 @@ resource "coder_script" "windsurf_mcp" { } output "windsurf_url" { - value = coder_app.windsurf.url + value = module.vscode-desktop-core.ide_uri description = "Windsurf Editor URL." -} +} \ No newline at end of file diff --git a/registry/cytoshahar/modules/positron/main.test.ts b/registry/cytoshahar/modules/positron/main.test.ts index 8017b595..fd1c5815 100644 --- a/registry/cytoshahar/modules/positron/main.test.ts +++ b/registry/cytoshahar/modules/positron/main.test.ts @@ -21,7 +21,10 @@ describe("positron-desktop", async () => { ); const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "positron", + (res) => + res.type === "coder_app" && + res.module === "module.vscode-desktop-core" && + res.name === "vscode-desktop", ); expect(coder_app).not.toBeNull(); @@ -70,19 +73,4 @@ describe("positron-desktop", async () => { "positron://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, { - agent_id: "foo", - order: "22", - }); - - const coder_app = state.resources.find( - (res) => res.type === "coder_app" && res.name === "positron", - ); - - 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/cytoshahar/modules/positron/main.tf b/registry/cytoshahar/modules/positron/main.tf index c7826550..9365b444 100644 --- a/registry/cytoshahar/modules/positron/main.tf +++ b/registry/cytoshahar/modules/positron/main.tf @@ -9,10 +9,6 @@ terraform { } } -locals { - icon_url = "/icon/positron.svg" -} - variable "agent_id" { type = string description = "The ID of a Coder agent." @@ -42,33 +38,39 @@ variable "group" { default = null } +variable "slug" { + type = string + description = "The slug of the app." + default = "cursor" +} + +variable "display_name" { + type = string + description = "The display name of the app." + default = "Cursor Desktop" +} + data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} -resource "coder_app" "positron" { - agent_id = var.agent_id - external = true - icon = local.icon_url - slug = "positron" - display_name = "Positron Desktop" - order = var.order - group = var.group +module "vscode-desktop-core" { + source = "registry.coder.com/coder/vscode-desktop-core/coder" + version = "1.0.0" - url = join("", [ - "positron://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", - ]) + agent_id = var.agent_id + + coder_app_icon = "/icon/positron.svg" + coder_app_slug = var.slug + coder_app_display_name = var.display_name + coder_app_order = var.order + coder_app_group = var.group + + folder = var.folder + open_recent = var.open_recent + protocol = "positron" } output "positron_url" { - value = coder_app.positron.url + value = module.vscode-desktop-core.ide_uri description = "Positron Desktop URL." } diff --git a/test/test.ts b/test/test.ts index 6851f8de..7a956205 100644 --- a/test/test.ts +++ b/test/test.ts @@ -112,6 +112,8 @@ type JsonValue = | { [key: string]: JsonValue }; type TerraformStateResource = { + module: string; + mode: string; type: string; name: string; provider: string;