feat: add vscode-desktop-core module (#278)
Co-authored-by: Atif Ali <atif@coder.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
507b73a07e
commit
63d56eadc9
33
registry/coder/modules/vscode-desktop-core/README.md
Normal file
33
registry/coder/modules/vscode-desktop-core/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
display_name: 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 [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.
|
||||||
|
|
||||||
|
```tf
|
||||||
|
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/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"
|
||||||
|
}
|
||||||
|
```
|
||||||
100
registry/coder/modules/vscode-desktop-core/main.test.ts
Normal file
100
registry/coder/modules/vscode-desktop-core/main.test.ts
Normal file
@ -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",
|
||||||
|
coder_app_icon: "/icon/code.svg",
|
||||||
|
coder_app_slug: "vscode",
|
||||||
|
coder_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, {
|
||||||
|
coder_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);
|
||||||
|
});
|
||||||
|
});
|
||||||
92
registry/coder/modules/vscode-desktop-core/main.tf
Normal file
92
registry/coder/modules/vscode-desktop-core/main.tf
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
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 for the IDE."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "coder_app_icon" {
|
||||||
|
type = string
|
||||||
|
description = "The icon of the coder_app."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "coder_app_slug" {
|
||||||
|
type = string
|
||||||
|
description = "The slug of the coder_app."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "coder_app_display_name" {
|
||||||
|
type = string
|
||||||
|
description = "The display name of the coder_app."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "coder_app_order" {
|
||||||
|
type = number
|
||||||
|
description = "The order of the coder_app."
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "coder_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.coder_app_icon
|
||||||
|
slug = var.coder_app_slug
|
||||||
|
display_name = var.coder_app_display_name
|
||||||
|
|
||||||
|
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("", [
|
||||||
|
"${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}",
|
||||||
|
# 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" {
|
||||||
|
value = coder_app.vscode-desktop.url
|
||||||
|
description = "IDE URI."
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user