Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
313ec59d46 | ||
|
|
4b04d18f39 | ||
|
|
ee53ca0281 | ||
|
|
8e254a3bb9 | ||
|
|
1ab53139b3 | ||
|
|
147bea9782 | ||
|
|
8d8910c52a | ||
|
|
c00b7536cb | ||
|
|
d66d7e994e |
3
.github/workflows/update-readme.yaml
vendored
3
.github/workflows/update-readme.yaml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
jobs:
|
||||
update-readme:
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -33,6 +33,7 @@ jobs:
|
||||
title: 'chore: bump version to ${{ env.TAG }} in README.md files'
|
||||
body: 'This is an auto-generated PR to update README.md files of all modules with the new tag ${{ env.TAG }}'
|
||||
branch: 'update-readme-branch'
|
||||
base: 'main'
|
||||
env:
|
||||
TAG: ${{ steps.get-latest-tag.outputs.TAG }}
|
||||
|
||||
|
||||
BIN
.images/hcp-vault-secrets-credentials.png
Normal file
BIN
.images/hcp-vault-secrets-credentials.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 174 KiB |
@@ -69,7 +69,7 @@ resource "coder_app" "MODULE_NAME" {
|
||||
slug = "MODULE_NAME"
|
||||
display_name = "MODULE_NAME"
|
||||
url = "http://localhost:${var.port}"
|
||||
icon = loocal.icon_url
|
||||
icon = local.icon_url
|
||||
subdomain = false
|
||||
share = "owner"
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Automatically install [code-server](https://github.com/coder/code-server) in a w
|
||||
```tf
|
||||
module "code-server" {
|
||||
source = "registry.coder.com/modules/code-server/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
}
|
||||
```
|
||||
@@ -28,7 +28,7 @@ module "code-server" {
|
||||
```tf
|
||||
module "code-server" {
|
||||
source = "registry.coder.com/modules/code-server/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
install_version = "4.8.3"
|
||||
}
|
||||
@@ -41,7 +41,7 @@ Install the Dracula theme from [OpenVSX](https://open-vsx.org/):
|
||||
```tf
|
||||
module "code-server" {
|
||||
source = "registry.coder.com/modules/code-server/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
extensions = [
|
||||
"dracula-theme.theme-dracula"
|
||||
@@ -58,7 +58,7 @@ Configure VS Code's [settings.json](https://code.visualstudio.com/docs/getstarte
|
||||
```tf
|
||||
module "code-server" {
|
||||
source = "registry.coder.com/modules/code-server/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
extensions = ["dracula-theme.theme-dracula"]
|
||||
settings = {
|
||||
@@ -74,7 +74,7 @@ Just run code-server in the background, don't fetch it from GitHub:
|
||||
```tf
|
||||
module "code-server" {
|
||||
source = "registry.coder.com/modules/code-server/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
|
||||
}
|
||||
@@ -87,7 +87,7 @@ Just run code-server in the background, don't fetch it from GitHub:
|
||||
```tf
|
||||
module "code-server" {
|
||||
source = "registry.coder.com/modules/code-server/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
offline = true
|
||||
}
|
||||
|
||||
@@ -32,6 +32,12 @@ variable "display_name" {
|
||||
default = "code-server"
|
||||
}
|
||||
|
||||
variable "slug" {
|
||||
type = string
|
||||
description = "The slug for the code-server application."
|
||||
default = "code-server"
|
||||
}
|
||||
|
||||
variable "settings" {
|
||||
type = map(string)
|
||||
description = "A map of settings to apply to code-server."
|
||||
@@ -89,7 +95,7 @@ resource "coder_script" "code-server" {
|
||||
|
||||
resource "coder_app" "code-server" {
|
||||
agent_id = var.agent_id
|
||||
slug = "code-server"
|
||||
slug = var.slug
|
||||
display_name = var.display_name
|
||||
url = "http://localhost:${var.port}/${var.folder != "" ? "?folder=${urlencode(var.folder)}" : ""}"
|
||||
icon = "/icon/code.svg"
|
||||
|
||||
@@ -23,7 +23,14 @@ module "vault" {
|
||||
|
||||
## Configuration
|
||||
|
||||
To configure the HCP Vault Secrets module, you must create an HCP Service Principal from the HCP Vault Secrets app in the HCP console. This will give you the `HCP_CLIENT_ID` and `HCP_CLIENT_SECRET` that you need to authenticate with HCP Vault Secrets. See the [HCP Vault Secrets documentation](https://developer.hashicorp.com/hcp/docs/vault-secrets) for more information.
|
||||
To configure the HCP Vault Secrets module, follow these steps,
|
||||
|
||||
1. [Create secrets in HCP Vault Secrets](https://developer.hashicorp.com/vault/tutorials/hcp-vault-secrets-get-started/hcp-vault-secrets-create-secret)
|
||||
2. Create an HCP Service Principal from the HCP Vault Secrets app in the HCP console. This will give you the `HCP_CLIENT_ID` and `HCP_CLIENT_SECRET` that you need to authenticate with HCP Vault Secrets.
|
||||

|
||||
3. Set `HCP_CLIENT_ID` and `HCP_CLIENT_SECRET` variables on the coder provisioner (recommended) or supply them as input to the module.
|
||||
|
||||
> See the [HCP Vault Secrets documentation](https://developer.hashicorp.com/hcp/docs/vault-secrets) for more information.
|
||||
|
||||
## Fetch All Secrets
|
||||
|
||||
|
||||
@@ -11,18 +11,16 @@ describe("jetbrains-gateway", async () => {
|
||||
await testRequiredVariables(import.meta.dir, {
|
||||
agent_id: "foo",
|
||||
agent_name: "foo",
|
||||
folder: "/baz/",
|
||||
folder: "/home/foo",
|
||||
});
|
||||
|
||||
it("default to first ide", async () => {
|
||||
const state = await runTerraformApply(import.meta.dir, {
|
||||
agent_id: "foo",
|
||||
agent_name: "foo",
|
||||
folder: "/baz/",
|
||||
folder: "/home/foo",
|
||||
jetbrains_ides: '["IU", "GO", "PY"]',
|
||||
});
|
||||
expect(state.outputs.jetbrains_ides.value).toBe(
|
||||
'["IU","232.10203.10","https://download.jetbrains.com/idea/ideaIU-2023.2.4.tar.gz"]',
|
||||
);
|
||||
expect(state.outputs.identifier.value).toBe("IU");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,6 +22,10 @@ variable "agent_name" {
|
||||
variable "folder" {
|
||||
type = string
|
||||
description = "The directory to open in the IDE. e.g. /home/coder/project"
|
||||
validation {
|
||||
condition = can(regex("^(?:/[^/]+)+$", var.folder))
|
||||
error_message = "The folder must be a full path and must not start with a ~."
|
||||
}
|
||||
}
|
||||
|
||||
variable "default" {
|
||||
@@ -30,10 +34,6 @@ variable "default" {
|
||||
description = "Default IDE"
|
||||
}
|
||||
|
||||
locals {
|
||||
supported_ides = ["IU", "PS", "WS", "PY", "CL", "GO", "RM"]
|
||||
}
|
||||
|
||||
variable "jetbrains_ide_versions" {
|
||||
type = map(object({
|
||||
build_number = string
|
||||
@@ -69,29 +69,28 @@ variable "jetbrains_ide_versions" {
|
||||
build_number = "232.10203.15"
|
||||
version = "2023.2.4"
|
||||
}
|
||||
|
||||
}
|
||||
validation {
|
||||
condition = (
|
||||
alltrue([
|
||||
for code in var.jetbrains_ide_versions : contains(local.supported_ides, code)
|
||||
for code in keys(var.jetbrains_ide_versions) : contains(["IU", "PS", "WS", "PY", "CL", "GO", "RM"], code)
|
||||
])
|
||||
)
|
||||
error_message = "The jetbrains_ide_versions must contain a map of valid product codes. Valid product codes are ${join(",", local.supported_ides)}."
|
||||
error_message = "The jetbrains_ide_versions must contain a map of valid product codes. Valid product codes are ${join(",", ["IU", "PS", "WS", "PY", "CL", "GO", "RM"])}."
|
||||
}
|
||||
}
|
||||
|
||||
variable "jetbrains_ides" {
|
||||
type = list(string)
|
||||
description = "The list of IDE product codes."
|
||||
default = local.supported_ides
|
||||
default = ["IU", "PS", "WS", "PY", "CL", "GO", "RM"]
|
||||
validation {
|
||||
condition = (
|
||||
alltrue([
|
||||
for code in var.jetbrains_ides : contains(local.supported_ides, code)
|
||||
for code in var.jetbrains_ides : contains(["IU", "PS", "WS", "PY", "CL", "GO", "RM"], code)
|
||||
])
|
||||
)
|
||||
error_message = "The jetbrains_ides must be a list of valid product codes. Valid product codes are ${join(",", local.supported_ides)}."
|
||||
error_message = "The jetbrains_ides must be a list of valid product codes. Valid product codes are ${join(",", ["IU", "PS", "WS", "PY", "CL", "GO", "RM"])}."
|
||||
}
|
||||
# check if the list is empty
|
||||
validation {
|
||||
@@ -108,58 +107,71 @@ variable "jetbrains_ides" {
|
||||
locals {
|
||||
jetbrains_ides = {
|
||||
"GO" = {
|
||||
icon = "/icon/goland.svg",
|
||||
name = "GoLand",
|
||||
value = jsonencode(["GO", var.jetbrains_ide_versions["GO"].build_number, "https://download.jetbrains.com/go/goland-${var.jetbrains_ide_versions["GO"].version}.tar.gz"])
|
||||
icon = "/icon/goland.svg",
|
||||
name = "GoLand",
|
||||
identifier = "GO",
|
||||
build_number = var.jetbrains_ide_versions["GO"].build_number,
|
||||
download_link = "https://download.jetbrains.com/go/goland-${var.jetbrains_ide_versions["GO"].version}.tar.gz"
|
||||
},
|
||||
"WS" = {
|
||||
icon = "/icon/webstorm.svg",
|
||||
name = "WebStorm",
|
||||
value = jsonencode(["WS", var.jetbrains_ide_versions["WS"].build_number, "https://download.jetbrains.com/webstorm/WebStorm-${var.jetbrains_ide_versions["WS"].version}.tar.gz"])
|
||||
icon = "/icon/webstorm.svg",
|
||||
name = "WebStorm",
|
||||
identifier = "WS",
|
||||
build_number = var.jetbrains_ide_versions["WS"].build_number,
|
||||
download_link = "https://download.jetbrains.com/webstorm/WebStorm-${var.jetbrains_ide_versions["WS"].version}.tar.gz"
|
||||
},
|
||||
"IU" = {
|
||||
icon = "/icon/intellij.svg",
|
||||
name = "IntelliJ IDEA Ultimate",
|
||||
value = jsonencode(["IU", var.jetbrains_ide_versions["IU"].build_number, "https://download.jetbrains.com/idea/ideaIU-${var.jetbrains_ide_versions["IU"].version}.tar.gz"])
|
||||
icon = "/icon/intellij.svg",
|
||||
name = "IntelliJ IDEA Ultimate",
|
||||
identifier = "IU",
|
||||
build_number = var.jetbrains_ide_versions["IU"].build_number,
|
||||
download_link = "https://download.jetbrains.com/idea/ideaIU-${var.jetbrains_ide_versions["IU"].version}.tar.gz"
|
||||
},
|
||||
"PY" = {
|
||||
icon = "/icon/pycharm.svg",
|
||||
name = "PyCharm Professional",
|
||||
value = jsonencode(["PY", var.jetbrains_ide_versions["PY"].build_number, "https://download.jetbrains.com/python/pycharm-professional-${var.jetbrains_ide_versions["PY"].version}.tar.gz"])
|
||||
icon = "/icon/pycharm.svg",
|
||||
name = "PyCharm Professional",
|
||||
identifier = "PY",
|
||||
build_number = var.jetbrains_ide_versions["PY"].build_number,
|
||||
download_link = "https://download.jetbrains.com/python/pycharm-professional-${var.jetbrains_ide_versions["PY"].version}.tar.gz"
|
||||
},
|
||||
"CL" = {
|
||||
icon = "/icon/clion.svg",
|
||||
name = "CLion",
|
||||
value = jsonencode(["CL", var.jetbrains_ide_versions["CL"].build_number, "https://download.jetbrains.com/cpp/CLion-${var.jetbrains_ide_versions["CL"].version}.tar.gz"])
|
||||
icon = "/icon/clion.svg",
|
||||
name = "CLion",
|
||||
identifier = "CL",
|
||||
build_number = var.jetbrains_ide_versions["CL"].build_number,
|
||||
download_link = "https://download.jetbrains.com/cpp/CLion-${var.jetbrains_ide_versions["CL"].version}.tar.gz"
|
||||
},
|
||||
"PS" = {
|
||||
icon = "/icon/phpstorm.svg",
|
||||
name = "PhpStorm",
|
||||
value = jsonencode(["PS", var.jetbrains_ide_versions["PS"].build_number, "https://download.jetbrains.com/webide/PhpStorm-${var.jetbrains_ide_versions["PS"].version}.tar.gz"])
|
||||
icon = "/icon/phpstorm.svg",
|
||||
name = "PhpStorm",
|
||||
identifier = "PS",
|
||||
build_number = var.jetbrains_ide_versions["PS"].build_number,
|
||||
download_link = "https://download.jetbrains.com/webide/PhpStorm-${var.jetbrains_ide_versions["PS"].version}.tar.gz"
|
||||
},
|
||||
"RM" = {
|
||||
icon = "/icon/rubymine.svg",
|
||||
name = "RubyMine",
|
||||
value = jsonencode(["RM", var.jetbrains_ide_versions["RM"].build_number, "https://download.jetbrains.com/ruby/RubyMine-${var.jetbrains_ide_versions["RM"].version}.tar.gz"])
|
||||
icon = "/icon/rubymine.svg",
|
||||
name = "RubyMine",
|
||||
identifier = "RM",
|
||||
build_number = var.jetbrains_ide_versions["RM"].build_number,
|
||||
download_link = "https://download.jetbrains.com/ruby/RubyMine-${var.jetbrains_ide_versions["RM"].version}.tar.gz"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "coder_parameter" "jetbrains_ide" {
|
||||
type = "list(string)"
|
||||
type = "string"
|
||||
name = "jetbrains_ide"
|
||||
display_name = "JetBrains IDE"
|
||||
icon = "/icon/gateway.svg"
|
||||
mutable = true
|
||||
# check if default is in the jet_brains_ides list and if it is not empty or null otherwise set it to null
|
||||
default = var.default != null && var.default != "" && contains(var.jetbrains_ides, var.default) ? local.jetbrains_ides[var.default].value : local.jetbrains_ides[var.jetbrains_ides[0]].value
|
||||
default = var.default == "" ? var.jetbrains_ides[0] : var.default
|
||||
|
||||
dynamic "option" {
|
||||
for_each = { for key, value in local.jetbrains_ides : key => value if contains(var.jetbrains_ides, key) }
|
||||
for_each = var.jetbrains_ides
|
||||
content {
|
||||
icon = option.value.icon
|
||||
name = option.value.name
|
||||
value = option.value.value
|
||||
icon = lookup(local.jetbrains_ides, option.value).icon
|
||||
name = lookup(local.jetbrains_ides, option.value).name
|
||||
value = lookup(local.jetbrains_ides, option.value).identifier
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,9 +180,9 @@ data "coder_workspace" "me" {}
|
||||
|
||||
resource "coder_app" "gateway" {
|
||||
agent_id = var.agent_id
|
||||
display_name = data.coder_parameter.jetbrains_ide.option[index(data.coder_parameter.jetbrains_ide.option.*.value, data.coder_parameter.jetbrains_ide.value)].name
|
||||
slug = "gateway"
|
||||
icon = data.coder_parameter.jetbrains_ide.option[index(data.coder_parameter.jetbrains_ide.option.*.value, data.coder_parameter.jetbrains_ide.value)].icon
|
||||
display_name = try(lookup(local.jetbrains_ides, data.coder_parameter.jetbrains_ide.value).name, "JetBrains IDE")
|
||||
icon = try(lookup(local.jetbrains_ides, data.coder_parameter.jetbrains_ide.value).icon, "/icon/gateway.svg")
|
||||
external = true
|
||||
url = join("", [
|
||||
"jetbrains-gateway://connect#type=coder&workspace=",
|
||||
@@ -184,14 +196,38 @@ resource "coder_app" "gateway" {
|
||||
"&token=",
|
||||
"$SESSION_TOKEN",
|
||||
"&ide_product_code=",
|
||||
jsondecode(data.coder_parameter.jetbrains_ide.value)[0],
|
||||
local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].identifier,
|
||||
"&ide_build_number=",
|
||||
jsondecode(data.coder_parameter.jetbrains_ide.value)[1],
|
||||
local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].build_number,
|
||||
"&ide_download_link=",
|
||||
jsondecode(data.coder_parameter.jetbrains_ide.value)[2],
|
||||
local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].download_link
|
||||
])
|
||||
}
|
||||
|
||||
output "jetbrains_ides" {
|
||||
output "identifier" {
|
||||
value = data.coder_parameter.jetbrains_ide.value
|
||||
}
|
||||
|
||||
output "name" {
|
||||
value = coder_app.gateway.display_name
|
||||
}
|
||||
|
||||
output "icon" {
|
||||
value = coder_app.gateway.icon
|
||||
}
|
||||
|
||||
output "download_link" {
|
||||
value = lookup(local.jetbrains_ides, data.coder_parameter.jetbrains_ide.value).download_link
|
||||
}
|
||||
|
||||
output "build_number" {
|
||||
value = lookup(local.jetbrains_ides, data.coder_parameter.jetbrains_ide.value).build_number
|
||||
}
|
||||
|
||||
output "version" {
|
||||
value = var.jetbrains_ide_versions[data.coder_parameter.jetbrains_ide.value].version
|
||||
}
|
||||
|
||||
output "url" {
|
||||
value = coder_app.gateway.url
|
||||
}
|
||||
@@ -17,7 +17,7 @@ Install the JF CLI and authenticate package managers with Artifactory using OAut
|
||||
```tf
|
||||
module "jfrog" {
|
||||
source = "registry.coder.com/modules/jfrog-oauth/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
jfrog_url = "https://example.jfrog.io"
|
||||
username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"
|
||||
@@ -44,7 +44,7 @@ Configure the Python pip package manager to fetch packages from Artifactory whil
|
||||
```tf
|
||||
module "jfrog" {
|
||||
source = "registry.coder.com/modules/jfrog-oauth/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
jfrog_url = "https://example.jfrog.io"
|
||||
username_field = "email"
|
||||
@@ -72,7 +72,7 @@ The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extensio
|
||||
```tf
|
||||
module "jfrog" {
|
||||
source = "registry.coder.com/modules/jfrog-oauth/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
jfrog_url = "https://example.jfrog.io"
|
||||
username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"
|
||||
|
||||
@@ -19,6 +19,12 @@ variable "jfrog_url" {
|
||||
}
|
||||
}
|
||||
|
||||
variable "jfrog_server_id" {
|
||||
type = string
|
||||
description = "The server ID of the JFrog instance for JFrog CLI configuration"
|
||||
default = "0"
|
||||
}
|
||||
|
||||
variable "username_field" {
|
||||
type = string
|
||||
description = "The field to use for the artifactory username. i.e. Coder username or email."
|
||||
@@ -79,6 +85,7 @@ resource "coder_script" "jfrog" {
|
||||
script = templatefile("${path.module}/run.sh", {
|
||||
JFROG_URL : var.jfrog_url,
|
||||
JFROG_HOST : local.jfrog_host,
|
||||
JFROG_SERVER_ID : var.jfrog_server_id,
|
||||
ARTIFACTORY_USERNAME : local.username,
|
||||
ARTIFACTORY_EMAIL : data.coder_workspace.me.owner_email,
|
||||
ARTIFACTORY_ACCESS_TOKEN : data.coder_external_auth.jfrog.access_token,
|
||||
|
||||
@@ -15,9 +15,9 @@ fi
|
||||
# flows.
|
||||
export CI=true
|
||||
# Authenticate JFrog CLI with Artifactory.
|
||||
echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite 0
|
||||
echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite "${JFROG_SERVER_ID}"
|
||||
# Set the configured server as the default.
|
||||
jf c use 0
|
||||
jf c use "${JFROG_SERVER_ID}"
|
||||
|
||||
# Configure npm to use the Artifactory "npm" repository.
|
||||
if [ -z "${REPOSITORY_NPM}" ]; then
|
||||
|
||||
@@ -15,7 +15,7 @@ Install the JF CLI and authenticate package managers with Artifactory using Arti
|
||||
```tf
|
||||
module "jfrog" {
|
||||
source = "registry.coder.com/modules/jfrog-token/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
jfrog_url = "https://XXXX.jfrog.io"
|
||||
artifactory_access_token = var.artifactory_access_token
|
||||
@@ -41,7 +41,7 @@ For detailed instructions, please see this [guide](https://coder.com/docs/v2/lat
|
||||
```tf
|
||||
module "jfrog" {
|
||||
source = "registry.coder.com/modules/jfrog-token/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
jfrog_url = "https://YYYY.jfrog.io"
|
||||
artifactory_access_token = var.artifactory_access_token # An admin access token
|
||||
@@ -74,7 +74,7 @@ The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extensio
|
||||
```tf
|
||||
module "jfrog" {
|
||||
source = "registry.coder.com/modules/jfrog-token/coder"
|
||||
version = "1.0.2"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
jfrog_url = "https://XXXX.jfrog.io"
|
||||
artifactory_access_token = var.artifactory_access_token
|
||||
|
||||
@@ -23,6 +23,12 @@ variable "jfrog_url" {
|
||||
}
|
||||
}
|
||||
|
||||
variable "jfrog_server_id" {
|
||||
type = string
|
||||
description = "The server ID of the JFrog instance for JFrog CLI configuration"
|
||||
default = "0"
|
||||
}
|
||||
|
||||
variable "artifactory_access_token" {
|
||||
type = string
|
||||
description = "The admin-level access token to use for JFrog."
|
||||
@@ -112,6 +118,7 @@ resource "coder_script" "jfrog" {
|
||||
script = templatefile("${path.module}/run.sh", {
|
||||
JFROG_URL : var.jfrog_url,
|
||||
JFROG_HOST : local.jfrog_host,
|
||||
JFROG_SERVER_ID : var.jfrog_server_id,
|
||||
ARTIFACTORY_USERNAME : local.username,
|
||||
ARTIFACTORY_EMAIL : data.coder_workspace.me.owner_email,
|
||||
ARTIFACTORY_ACCESS_TOKEN : artifactory_scoped_token.me.access_token,
|
||||
|
||||
@@ -15,9 +15,9 @@ fi
|
||||
# flows.
|
||||
export CI=true
|
||||
# Authenticate JFrog CLI with Artifactory.
|
||||
echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite 0
|
||||
echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite "${JFROG_SERVER_ID}"
|
||||
# Set the configured server as the default.
|
||||
jf c use 0
|
||||
jf c use "${JFROG_SERVER_ID}"
|
||||
|
||||
# Configure npm to use the Artifactory "npm" repository.
|
||||
if [ -z "${REPOSITORY_NPM}" ]; then
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"test": "bun test",
|
||||
"fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf",
|
||||
"fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf",
|
||||
"lint": "bun run lint.ts",
|
||||
"lint": "bun run lint.ts && ./terraform_validate.sh",
|
||||
"update-version": "./update-version.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
29
terraform_validate.sh
Executable file
29
terraform_validate.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Function to run terraform init and validate in a directory
|
||||
run_terraform() {
|
||||
local dir="$1"
|
||||
echo "Running terraform init and validate in $dir"
|
||||
pushd "$dir"
|
||||
terraform init -upgrade
|
||||
terraform validate
|
||||
popd
|
||||
}
|
||||
|
||||
# Main script
|
||||
main() {
|
||||
# Get the directory of the script
|
||||
script_dir=$(dirname "$(readlink -f "$0")")
|
||||
|
||||
# Get all subdirectories in the repository
|
||||
subdirs=$(find "$script_dir" -mindepth 1 -maxdepth 1 -type d -not -name ".*" | sort)
|
||||
|
||||
for dir in $subdirs; do
|
||||
run_terraform "$dir"
|
||||
done
|
||||
}
|
||||
|
||||
# Run the main script
|
||||
main
|
||||
@@ -15,7 +15,7 @@ This module lets you authenticate with [Hashicorp Vault](https://www.vaultprojec
|
||||
```tf
|
||||
module "vault" {
|
||||
source = "registry.coder.com/modules/vault-github/coder"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
agent_id = coder_agent.example.id
|
||||
vault_addr = "https://vault.example.com"
|
||||
}
|
||||
@@ -46,7 +46,7 @@ To configure the Vault module, you must set up a Vault GitHub auth method. See t
|
||||
```tf
|
||||
module "vault" {
|
||||
source = "registry.coder.com/modules/vault-github/coder"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
agent_id = coder_agent.example.id
|
||||
vault_addr = "https://vault.example.com"
|
||||
coder_github_auth_id = "my-github-auth-id"
|
||||
@@ -58,7 +58,7 @@ module "vault" {
|
||||
```tf
|
||||
module "vault" {
|
||||
source = "registry.coder.com/modules/vault-github/coder"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
agent_id = coder_agent.example.id
|
||||
vault_addr = "https://vault.example.com"
|
||||
coder_github_auth_id = "my-github-auth-id"
|
||||
@@ -71,7 +71,7 @@ module "vault" {
|
||||
```tf
|
||||
module "vault" {
|
||||
source = "registry.coder.com/modules/vault-github/coder"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
agent_id = coder_agent.example.id
|
||||
vault_addr = "https://vault.example.com"
|
||||
vault_cli_version = "1.15.0"
|
||||
|
||||
@@ -21,7 +21,7 @@ variable "vault_token" {
|
||||
|
||||
module "vault" {
|
||||
source = "registry.coder.com/modules/vault-token/coder"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
agent_id = coder_agent.example.id
|
||||
vault_token = var.token
|
||||
vault_addr = "https://vault.example.com"
|
||||
@@ -74,7 +74,7 @@ variable "vault_token" {
|
||||
|
||||
module "vault" {
|
||||
source = "registry.coder.com/modules/vault-token/coder"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
agent_id = coder_agent.example.id
|
||||
vault_addr = "https://vault.example.com"
|
||||
vault_token = var.token
|
||||
|
||||
@@ -9,7 +9,7 @@ tags: [helper, ide, vscode, web]
|
||||
|
||||
# VS Code Web
|
||||
|
||||
Automatically install [Visual Studio Code Server](https://code.visualstudio.com/docs/remote/vscode-server) in a workspace using the [VS Code CLI](https://code.visualstudio.com/docs/editor/command-line) and create an app to access it via the dashboard.
|
||||
Automatically install [Visual Studio Code Server](https://code.visualstudio.com/docs/remote/vscode-server) in a workspace and create an app to access it via the dashboard.
|
||||
|
||||
```tf
|
||||
module "vscode-web" {
|
||||
@@ -31,8 +31,20 @@ module "vscode-web" {
|
||||
source = "registry.coder.com/modules/vscode-web/coder"
|
||||
version = "1.0.3"
|
||||
agent_id = coder_agent.example.id
|
||||
install_dir = "/home/coder/.vscode-web"
|
||||
install_prefix = "/home/coder/.vscode-web"
|
||||
folder = "/home/coder"
|
||||
accept_license = true
|
||||
}
|
||||
```
|
||||
|
||||
### Install Extensions
|
||||
|
||||
```tf
|
||||
module "vscode-web" {
|
||||
source = "registry.coder.com/modules/vscode-web/coder"
|
||||
version = "1.0.2"
|
||||
agent_id = coder_agent.example.id
|
||||
extensions = ["github.copilot", "ms-python.python", "ms-toolsai.jupyter"]
|
||||
accept_license = true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import {
|
||||
executeScriptInContainer,
|
||||
runTerraformApply,
|
||||
runTerraformInit,
|
||||
} from "../test";
|
||||
|
||||
describe("vscode-web", async () => {
|
||||
await runTerraformInit(import.meta.dir);
|
||||
|
||||
// replaces testRequiredVariables due to license variable
|
||||
// may add a testRequiredVariablesWithLicense function later
|
||||
it("missing agent_id", async () => {
|
||||
try {
|
||||
await runTerraformApply(import.meta.dir, {
|
||||
accept_license: "true",
|
||||
});
|
||||
} catch (ex) {
|
||||
expect(ex.message).toContain('input variable "agent_id" is not set');
|
||||
}
|
||||
});
|
||||
|
||||
it("invalid license_agreement", async () => {
|
||||
try {
|
||||
await runTerraformApply(import.meta.dir, {
|
||||
agent_id: "foo",
|
||||
});
|
||||
} catch (ex) {
|
||||
expect(ex.message).toContain(
|
||||
"You must accept the VS Code license agreement by setting accept_license=true",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("fails without curl", async () => {
|
||||
const state = await runTerraformApply(import.meta.dir, {
|
||||
agent_id: "foo",
|
||||
accept_license: "true",
|
||||
});
|
||||
const output = await executeScriptInContainer(state, "alpine");
|
||||
expect(output.exitCode).toBe(1);
|
||||
expect(output.stdout).toEqual([
|
||||
"\u001b[0;1mInstalling vscode-cli!",
|
||||
"Failed to install vscode-cli:", // TODO: manually test error log
|
||||
]);
|
||||
});
|
||||
|
||||
it("runs with curl", async () => {
|
||||
const state = await runTerraformApply(import.meta.dir, {
|
||||
agent_id: "foo",
|
||||
accept_license: "true",
|
||||
});
|
||||
const output = await executeScriptInContainer(state, "alpine/curl");
|
||||
expect(output.exitCode).toBe(0);
|
||||
expect(output.stdout).toEqual([
|
||||
"\u001b[0;1mInstalling vscode-cli!",
|
||||
"🥳 vscode-cli has been installed.",
|
||||
"",
|
||||
"👷 Running /tmp/vscode-cli/bin/code serve-web --port 13338 --without-connection-token --accept-server-license-terms in the background...",
|
||||
"Check logs at /tmp/vscode-web.log!",
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -53,15 +53,21 @@ variable "log_path" {
|
||||
default = "/tmp/vscode-web.log"
|
||||
}
|
||||
|
||||
variable "install_dir" {
|
||||
variable "install_prefix" {
|
||||
type = string
|
||||
description = "The directory to install VS Code CLI"
|
||||
default = "/tmp/vscode-cli"
|
||||
description = "The prefix to install vscode-web to."
|
||||
default = "/tmp/vscode-web"
|
||||
}
|
||||
|
||||
variable "extensions" {
|
||||
type = list(string)
|
||||
description = "A list of extensions to install."
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "accept_license" {
|
||||
type = bool
|
||||
description = "Accept the VS Code license. https://code.visualstudio.com/license"
|
||||
description = "Accept the VS Code Server license. https://code.visualstudio.com/license/server"
|
||||
default = false
|
||||
validation {
|
||||
condition = var.accept_license == true
|
||||
@@ -69,6 +75,16 @@ variable "accept_license" {
|
||||
}
|
||||
}
|
||||
|
||||
variable "telemetry_level" {
|
||||
type = string
|
||||
description = "Set the telemetry level for VS Code Web."
|
||||
default = "error"
|
||||
validation {
|
||||
condition = var.telemetry_level == "off" || var.telemetry_level == "crash" || var.telemetry_level == "error" || var.telemetry_level == "all"
|
||||
error_message = "Incorrect value. Please set either 'off', 'crash', 'error', or 'all'."
|
||||
}
|
||||
}
|
||||
|
||||
resource "coder_script" "vscode-web" {
|
||||
agent_id = var.agent_id
|
||||
display_name = "VS Code Web"
|
||||
@@ -76,7 +92,9 @@ resource "coder_script" "vscode-web" {
|
||||
script = templatefile("${path.module}/run.sh", {
|
||||
PORT : var.port,
|
||||
LOG_PATH : var.log_path,
|
||||
INSTALL_DIR : var.install_dir,
|
||||
INSTALL_PREFIX : var.install_prefix,
|
||||
EXTENSIONS : join(",", var.extensions),
|
||||
TELEMETRY_LEVEL : var.telemetry_level,
|
||||
})
|
||||
run_on_start = true
|
||||
}
|
||||
|
||||
48
vscode-web/run.sh
Normal file → Executable file
48
vscode-web/run.sh
Normal file → Executable file
@@ -1,21 +1,49 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BOLD='\033[0;1m'
|
||||
EXTENSIONS=("${EXTENSIONS}")
|
||||
|
||||
# Create install directory if it doesn't exist
|
||||
mkdir -p ${INSTALL_DIR}
|
||||
# Create install prefix
|
||||
mkdir -p ${INSTALL_PREFIX}
|
||||
|
||||
printf "$${BOLD}Installing vscode-cli!\n"
|
||||
printf "$${BOLD}Installing Microsoft Visual Studio Code Server!\n"
|
||||
|
||||
# Download and extract code-cli tarball
|
||||
output=$(curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz && tar -xf vscode_cli.tar.gz -C ${INSTALL_DIR} && rm vscode_cli.tar.gz)
|
||||
# Download and extract vscode-server
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64) ARCH="x64" ;;
|
||||
aarch64) ARCH="arm64" ;;
|
||||
*)
|
||||
echo "Unsupported architecture"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
HASH=$(curl https://update.code.visualstudio.com/api/commits/stable/server-linux-$ARCH-web | cut -d '"' -f 2)
|
||||
output=$(curl -sL https://vscode.download.prss.microsoft.com/dbazure/download/stable/$HASH/vscode-server-linux-$ARCH-web.tar.gz | tar -xz -C ${INSTALL_PREFIX} --strip-components 1)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to install vscode-cli: $output"
|
||||
echo "Failed to install Microsoft Visual Studio Code Server: $output"
|
||||
exit 1
|
||||
fi
|
||||
printf "🥳 vscode-cli has been installed.\n\n"
|
||||
printf "$${BOLD}Microsoft Visual Studio Code Server has been installed.\n"
|
||||
|
||||
echo "👷 Running ${INSTALL_DIR}/bin/code serve-web --port ${PORT} --without-connection-token --accept-server-license-terms in the background..."
|
||||
VSCODE_SERVER="${INSTALL_PREFIX}/bin/code-server"
|
||||
|
||||
# Install each extension...
|
||||
IFS=',' read -r -a EXTENSIONLIST <<< "$${EXTENSIONS}"
|
||||
for extension in "$${EXTENSIONLIST[@]}"; do
|
||||
if [ -z "$extension" ]; then
|
||||
continue
|
||||
fi
|
||||
printf "🧩 Installing extension $${CODE}$extension$${RESET}...\n"
|
||||
output=$($VSCODE_SERVER --install-extension "$extension" --force)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to install extension: $extension: $output"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "👷 Running ${INSTALL_PREFIX}/bin/code-server serve-local --port ${PORT} --accept-server-license-terms serve-local --without-connection-token --telemetry-level ${TELEMETRY_LEVEL} in the background..."
|
||||
echo "Check logs at ${LOG_PATH}!"
|
||||
${INSTALL_DIR}/code serve-web --port ${PORT} --without-connection-token --accept-server-license-terms > ${LOG_PATH} 2>&1 &
|
||||
"${INSTALL_PREFIX}/bin/code-server" serve-local --port "${PORT}" --accept-server-license-terms serve-local --without-connection-token --telemetry-level "${TELEMETRY_LEVEL}" > "${LOG_PATH}" 2>&1 &
|
||||
|
||||
Reference in New Issue
Block a user