Skip to content

Commit bbae3d1

Browse files
committed
feat: add vscode-desktop-core module
1 parent 3fd7b47 commit bbae3d1

File tree

3 files changed

+219
-0
lines changed

3 files changed

+219
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
display_name: Coder VSCode Desktop Core
3+
description: Building block for modules that need to link to an external VSCode-based IDE
4+
icon: ../../../../.icons/coder.svg
5+
verified: true
6+
tags: [internal, library]
7+
---
8+
9+
# VS Code Desktop Core
10+
11+
> [!CAUTION]
12+
> 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).
13+
14+
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.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { describe, expect, it } from "bun:test";
2+
import {
3+
runTerraformApply,
4+
runTerraformInit,
5+
testRequiredVariables,
6+
} from "~test";
7+
8+
// hardcoded coder_app name in main.tf
9+
const appName = "vscode-desktop";
10+
11+
const defaultVariables = {
12+
agent_id: "foo",
13+
web_app_icon: "/icon/code.svg",
14+
web_app_slug: "vscode",
15+
web_app_display_name: "VS Code Desktop",
16+
protocol: "vscode",
17+
}
18+
19+
describe("vscode-desktop-core", async () => {
20+
await runTerraformInit(import.meta.dir);
21+
22+
testRequiredVariables(import.meta.dir, defaultVariables);
23+
24+
it("default output", async () => {
25+
const state = await runTerraformApply(import.meta.dir, defaultVariables);
26+
expect(state.outputs.ide_uri.value).toBe(
27+
`${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`,
28+
);
29+
30+
const coder_app = state.resources.find(
31+
(res) => res.type === "coder_app" && res.name === appName,
32+
);
33+
34+
expect(coder_app).not.toBeNull();
35+
expect(coder_app?.instances.length).toBe(1);
36+
expect(coder_app?.instances[0].attributes.order).toBeNull();
37+
});
38+
39+
it("adds folder", async () => {
40+
const state = await runTerraformApply(import.meta.dir, {
41+
folder: "/foo/bar",
42+
43+
...defaultVariables
44+
});
45+
46+
expect(state.outputs.ide_uri.value).toBe(
47+
`${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`,
48+
);
49+
});
50+
51+
it("adds folder and open_recent", async () => {
52+
const state = await runTerraformApply(import.meta.dir, {
53+
folder: "/foo/bar",
54+
open_recent: "true",
55+
56+
...defaultVariables,
57+
});
58+
expect(state.outputs.ide_uri.value).toBe(
59+
`${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`,
60+
);
61+
});
62+
63+
it("adds folder but not open_recent", async () => {
64+
const state = await runTerraformApply(import.meta.dir, {
65+
folder: "/foo/bar",
66+
openRecent: "false",
67+
68+
...defaultVariables,
69+
});
70+
expect(state.outputs.ide_uri.value).toBe(
71+
`${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`,
72+
);
73+
});
74+
75+
it("adds open_recent", async () => {
76+
const state = await runTerraformApply(import.meta.dir, {
77+
open_recent: "true",
78+
79+
...defaultVariables,
80+
});
81+
expect(state.outputs.ide_uri.value).toBe(
82+
`${defaultVariables.protocol}://coder.coder-remote/open?owner=default&workspace=default&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN`,
83+
);
84+
});
85+
86+
it("expect order to be set", async () => {
87+
const state = await runTerraformApply(import.meta.dir, {
88+
web_app_order: "22",
89+
...defaultVariables
90+
});
91+
92+
const coder_app = state.resources.find(
93+
(res) => res.type === "coder_app" && res.name === appName,
94+
);
95+
96+
expect(coder_app).not.toBeNull();
97+
expect(coder_app?.instances.length).toBe(1);
98+
expect(coder_app?.instances[0].attributes.order).toBe(22);
99+
});
100+
});
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
4+
required_providers {
5+
coder = {
6+
source = "coder/coder"
7+
version = ">= 2.5"
8+
}
9+
}
10+
}
11+
12+
variable "agent_id" {
13+
type = string
14+
description = "The ID of a Coder agent."
15+
}
16+
17+
variable "folder" {
18+
type = string
19+
description = "The folder to open in the IDE."
20+
default = ""
21+
}
22+
23+
variable "open_recent" {
24+
type = bool
25+
description = "Open the most recent workspace or folder. Falls back to the folder if there is no recent workspace or folder to open."
26+
default = false
27+
}
28+
29+
variable "protocol" {
30+
type = string
31+
description = "The URI protocol the IDE."
32+
}
33+
34+
variable "web_app_icon" {
35+
type = string
36+
description = "The icon of the coder_app."
37+
}
38+
39+
variable "web_app_slug" {
40+
type = string
41+
description = "The slug of the coder_app."
42+
}
43+
44+
variable "web_app_display_name" {
45+
type = string
46+
description = "The display name of the coder_app."
47+
}
48+
49+
variable "web_app_order" {
50+
type = number
51+
description = "The order of the coder_app."
52+
default = null
53+
}
54+
55+
variable "web_app_group" {
56+
type = string
57+
description = "The group of the coder_app."
58+
default = null
59+
}
60+
61+
data "coder_workspace" "me" {}
62+
data "coder_workspace_owner" "me" {}
63+
64+
resource "coder_app" "vscode-desktop" {
65+
agent_id = var.agent_id
66+
external = true
67+
68+
icon = var.web_app_icon
69+
slug = var.web_app_slug
70+
display_name = var.web_app_display_name
71+
72+
order = var.web_app_order
73+
group = var.web_app_group
74+
75+
url = join("", [
76+
var.protocol,
77+
"://coder.coder-remote/open",
78+
"?owner=",
79+
data.coder_workspace_owner.me.name,
80+
"&workspace=",
81+
data.coder_workspace.me.name,
82+
var.folder != "" ? join("", ["&folder=", var.folder]) : "",
83+
var.open_recent ? "&openRecent" : "",
84+
"&url=",
85+
data.coder_workspace.me.access_url,
86+
"&token=$SESSION_TOKEN",
87+
])
88+
89+
/*
90+
url = join("", [
91+
"vscode://coder.coder-remote/open",
92+
"?owner=${data.coder_workspace_owner.me.name}",
93+
"&workspace=${data.coder_workspace.me.name}",
94+
var.folder != "" ? join("", ["&folder=", var.folder]) : "",
95+
var.open_recent ? "&openRecent" : "",
96+
"&url=${data.coder_workspace.me.access_url}",
97+
"&token=$SESSION_TOKEN",
98+
])
99+
*/
100+
}
101+
102+
output "ide_uri" {
103+
value = coder_app.vscode-desktop.url
104+
description = "IDE URI."
105+
}

0 commit comments

Comments
 (0)