Compare commits

..

2 Commits

Author SHA1 Message Date
Muhammad Atif Ali
675c82367a feat(jetbrains-gateway): bump to 2024.3 (#355) 2024-11-29 15:51:24 +00:00
Mathias Fredriksson
bf697e1fa4 fix(update-versions.sh): handle markdown/tf block nesting when updating version (#356) 2024-11-29 20:22:43 +05:00
5 changed files with 104 additions and 128 deletions

View File

@@ -14,12 +14,12 @@ This module adds a JetBrains Gateway Button to open any workspace with a single
```tf ```tf
module "jetbrains_gateway" { module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder" source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24" version = "1.0.25"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
agent_name = "example" agent_name = "example"
folder = "/home/coder/example" folder = "/home/coder/example"
jetbrains_ides = ["CL", "GO", "IU", "PY", "WS"] jetbrains_ides = ["CL", "GO", "IU", "PY", "WS"]
default = ["GO"] default = "GO"
} }
``` ```
@@ -32,27 +32,52 @@ module "jetbrains_gateway" {
```tf ```tf
module "jetbrains_gateway" { module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder" source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24" version = "1.0.25"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
agent_name = "example" agent_name = "example"
folder = "/home/coder/example" folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"] jetbrains_ides = ["GO", "WS"]
default = ["GO"] default = "GO"
} }
``` ```
### Use the fixed version ### Use the latest version of each IDE
```tf ```tf
module "jetbrains_gateway" { module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder" source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24" version = "1.0.25"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
agent_name = "example" agent_name = "example"
folder = "/home/coder/example" folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"] jetbrains_ides = ["IU", "PY"]
default = ["GO"] default = "IU"
latest = false # current version is 2024.3 latest = true
}
```
### Use fixed versions set by `jetbrains_ide_versions`
```tf
module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.25"
agent_id = coder_agent.example.id
agent_name = "example"
folder = "/home/coder/example"
jetbrains_ides = ["IU", "PY"]
default = "IU"
latest = false
jetbrains_ide_versions = {
"IU" = {
build_number = "243.21565.193"
version = "2024.3"
}
"PY" = {
build_number = "243.21565.199"
version = "2024.3"
}
}
} }
``` ```
@@ -61,12 +86,12 @@ module "jetbrains_gateway" {
```tf ```tf
module "jetbrains_gateway" { module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder" source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24" version = "1.0.25"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
agent_name = "example" agent_name = "example"
folder = "/home/coder/example" folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"] jetbrains_ides = ["GO", "WS"]
default = ["GO"] default = "GO"
latest = true latest = true
channel = "eap" channel = "eap"
} }
@@ -79,29 +104,14 @@ Due to the highest priority of the `ide_download_link` parameter in the `(jetbra
```tf ```tf
module "jetbrains_gateway" { module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder" source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24" version = "1.0.25"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
agent_name = "example" agent_name = "example"
folder = "/home/coder/example" folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"] jetbrains_ides = ["GO", "WS"]
releases_base_link = "https://releases.internal.site/" releases_base_link = "https://releases.internal.site/"
download_base_link = "https://download.internal.site/" download_base_link = "https://download.internal.site/"
default = ["GO"] default = "GO"
}
```
### Add multiple IDEs
**Note:** This removes the choice of IDE from the user.
```tf
module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24"
agent_id = coder_agent.example.id
agent_name = "example"
folder = "/home/coder/example"
default = ["GO", "WS"]
} }
``` ```

View File

@@ -16,13 +16,14 @@ describe("jetbrains-gateway", async () => {
it("should create a link with the default values", async () => { it("should create a link with the default values", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply(import.meta.dir, {
// These are all required.
agent_id: "foo", agent_id: "foo",
agent_name: "foo", agent_name: "foo",
folder: "/home/coder", folder: "/home/coder",
}); });
expect(state.outputs.url.value).toEqual([ expect(state.outputs.url.value).toBe(
"jetbrains-gateway://connect#type=coder&workspace=default&owner=default&agent=foo&folder=/home/coder&url=https://mydeployment.coder.com&token=$SESSION_TOKEN&ide_product_code=IU&ide_build_number=243.21565.193&ide_download_link=https://download.jetbrains.com/idea/ideaIU-2024.3.tar.gz", "jetbrains-gateway://connect#type=coder&workspace=default&owner=default&agent=foo&folder=/home/coder&url=https://mydeployment.coder.com&token=$SESSION_TOKEN&ide_product_code=IU&ide_build_number=243.21565.193&ide_download_link=https://download.jetbrains.com/idea/ideaIU-2024.3.tar.gz",
]); );
const coder_app = state.resources.find( const coder_app = state.resources.find(
(res) => res.type === "coder_app" && res.name === "gateway", (res) => res.type === "coder_app" && res.name === "gateway",
@@ -33,31 +34,13 @@ describe("jetbrains-gateway", async () => {
expect(coder_app?.instances[0].attributes.order).toBeNull(); expect(coder_app?.instances[0].attributes.order).toBeNull();
}); });
it("default to first IDE", async () => { it("default to first ide", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo", agent_id: "foo",
agent_name: "foo", agent_name: "foo",
folder: "/home/foo", folder: "/home/foo",
jetbrains_ides: ["IU", "PY"], jetbrains_ides: '["IU", "GO", "PY"]',
}); });
expect(state.outputs.identifier.value).toEqual(["IU"]); expect(state.outputs.identifier.value).toBe("IU");
expect(state.outputs.url.value).toEqual([
"jetbrains-gateway://connect#type=coder&workspace=default&owner=default&agent=foo&folder=/home/foo&url=https://mydeployment.coder.com&token=$SESSION_TOKEN&ide_product_code=IU&ide_build_number=243.21565.193&ide_download_link=https://download.jetbrains.com/idea/ideaIU-2024.3.tar.gz",
]);
});
it("should create multiple IDEs", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
agent_name: "foo",
folder: "/home/foo",
default: ["GO", "IU", "PY"],
});
expect(state.outputs.identifier.value).toEqual(["GO", "IU", "PY"]);
expect(state.outputs.url.value).toEqual([
"jetbrains-gateway://connect#type=coder&workspace=default&owner=default&agent=foo&folder=/home/foo&url=https://mydeployment.coder.com&token=$SESSION_TOKEN&ide_product_code=GO&ide_build_number=243.21565.208&ide_download_link=https://download.jetbrains.com/go/goland-2024.3.tar.gz",
"jetbrains-gateway://connect#type=coder&workspace=default&owner=default&agent=foo&folder=/home/foo&url=https://mydeployment.coder.com&token=$SESSION_TOKEN&ide_product_code=IU&ide_build_number=243.21565.193&ide_download_link=https://download.jetbrains.com/idea/ideaIU-2024.3.tar.gz",
"jetbrains-gateway://connect#type=coder&workspace=default&owner=default&agent=foo&folder=/home/foo&url=https://mydeployment.coder.com&token=$SESSION_TOKEN&ide_product_code=PY&ide_build_number=243.21565.199&ide_download_link=https://download.jetbrains.com/python/pycharm-professional-2024.3.tar.gz",
]);
}); });
}); });

View File

@@ -39,23 +39,9 @@ variable "folder" {
} }
variable "default" { variable "default" {
default = [] default = ""
type = list(string) type = string
description = "List of default IDEs to be added to the Workspace page." description = "Default IDE"
# check if the list is unique
validation {
condition = length(var.default) == length(toset(var.default))
error_message = "The default must not contain duplicates."
}
# check if default are valid jetbrains_ides
validation {
condition = (
alltrue([
for code in var.default : contains(["IU", "PS", "WS", "PY", "CL", "GO", "RM", "RD"], code)
])
)
error_message = "The default must be a list of valid product codes. Valid product codes are ${join(",", ["IU", "PS", "WS", "PY", "CL", "GO", "RM", "RD"])}."
}
} }
variable "order" { variable "order" {
@@ -73,7 +59,7 @@ variable "coder_parameter_order" {
variable "latest" { variable "latest" {
type = bool type = bool
description = "Whether to fetch the latest version of the IDE." description = "Whether to fetch the latest version of the IDE."
default = true default = false
} }
variable "channel" { variable "channel" {
@@ -138,7 +124,7 @@ variable "jetbrains_ide_versions" {
variable "jetbrains_ides" { variable "jetbrains_ides" {
type = list(string) type = list(string)
description = "The list of IDE product codes to be shown to the user. Does not apply when there are multiple defaults." description = "The list of IDE product codes."
default = ["IU", "PS", "WS", "PY", "CL", "GO", "RM", "RD"] default = ["IU", "PS", "WS", "PY", "CL", "GO", "RM", "RD"]
validation { validation {
condition = ( condition = (
@@ -253,42 +239,23 @@ locals {
} }
} }
identifier = try([data.coder_parameter.jetbrains_ide[0].value], var.default) icon = local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].icon
list_json_data = var.latest ? [ json_data = var.latest ? jsondecode(data.http.jetbrains_ide_versions[data.coder_parameter.jetbrains_ide.value].response_body) : {}
for ide in local.identifier : jsondecode(data.http.jetbrains_ide_versions[ide].response_body) key = var.latest ? keys(local.json_data)[0] : ""
] : [] display_name = local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].name
list_key = var.latest ? [ identifier = data.coder_parameter.jetbrains_ide.value
for j in local.list_json_data : keys(j)[0] download_link = var.latest ? local.json_data[local.key][0].downloads.linux.link : local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].download_link
] : [] build_number = var.latest ? local.json_data[local.key][0].build : local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].build_number
download_links = length(local.list_key) > 0 ? [ version = var.latest ? local.json_data[local.key][0].version : var.jetbrains_ide_versions[data.coder_parameter.jetbrains_ide.value].version
for i, j in local.list_json_data : j[local.list_key[i]][0].downloads.linux.link
] : [
for ide in local.identifier : local.jetbrains_ides[ide].download_link
]
build_numbers = length(local.list_key) > 0 ? [
for i, j in local.list_json_data : j[local.list_key[i]][0].build
] : [
for ide in local.identifier : local.jetbrains_ides[ide].build_number
]
versions = length(local.list_key) > 0 ? [
for i, j in local.list_json_data : j[local.list_key[i]][0].version
] : [
for ide in local.identifier : local.jetbrains_ides[ide].version
]
display_names = [for key in keys(coder_app.gateway) : coder_app.gateway[key].display_name]
icons = [for key in keys(coder_app.gateway) : coder_app.gateway[key].icon]
urls = [for key in keys(coder_app.gateway) : coder_app.gateway[key].url]
} }
data "coder_parameter" "jetbrains_ide" { data "coder_parameter" "jetbrains_ide" {
# remove the coder_parameter if there are multiple default
count = length(var.default) > 1 ? 0 : 1
type = "string" type = "string"
name = "jetbrains_ide" name = "jetbrains_ide"
display_name = "JetBrains IDE" display_name = "JetBrains IDE"
icon = "/icon/gateway.svg" icon = "/icon/gateway.svg"
mutable = true mutable = true
default = length(var.default) > 0 ? var.default[0] : var.jetbrains_ides[0] default = var.default == "" ? var.jetbrains_ides[0] : var.default
order = var.coder_parameter_order order = var.coder_parameter_order
dynamic "option" { dynamic "option" {
@@ -305,11 +272,10 @@ data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {} data "coder_workspace_owner" "me" {}
resource "coder_app" "gateway" { resource "coder_app" "gateway" {
for_each = length(var.default) > 1 ? toset(var.default) : toset([data.coder_parameter.jetbrains_ide[0].value])
agent_id = var.agent_id agent_id = var.agent_id
slug = "${var.slug}-${lower(each.value)}" slug = var.slug
display_name = local.jetbrains_ides[each.value].name display_name = local.display_name
icon = local.jetbrains_ides[each.value].icon icon = local.icon
external = true external = true
order = var.order order = var.order
url = join("", [ url = join("", [
@@ -326,45 +292,38 @@ resource "coder_app" "gateway" {
"&token=", "&token=",
"$SESSION_TOKEN", "$SESSION_TOKEN",
"&ide_product_code=", "&ide_product_code=",
each.value, data.coder_parameter.jetbrains_ide.value,
"&ide_build_number=", "&ide_build_number=",
local.jetbrains_ides[each.value].build_number, local.build_number,
"&ide_download_link=", "&ide_download_link=",
local.jetbrains_ides[each.value].download_link, local.download_link,
]) ])
} }
output "identifier" { output "identifier" {
value = local.identifier value = local.identifier
description = "The product code of the JetBrains IDE."
} }
output "display_name" { output "display_name" {
value = [for key in keys(coder_app.gateway) : coder_app.gateway[key].display_name] value = local.display_name
description = "The display name of the JetBrains IDE."
} }
output "icon" { output "icon" {
value = [for key in keys(coder_app.gateway) : coder_app.gateway[key].icon] value = local.icon
description = "The icon of the JetBrains IDE."
} }
output "download_link" { output "download_link" {
value = local.download_links value = local.download_link
description = "The download link of the JetBrains IDE."
} }
output "build_number" { output "build_number" {
value = local.build_numbers value = local.build_number
description = "The build number of the JetBrains IDE."
} }
output "version" { output "version" {
value = local.versions value = local.version
description = "The version of the JetBrains IDE."
} }
output "url" { output "url" {
value = [for key in keys(coder_app.gateway) : coder_app.gateway[key].url] value = coder_app.gateway.url
description = "The URL to connect to the JetBrains IDE." }
}

View File

@@ -200,8 +200,7 @@ export const runTerraformApply = async <TVars extends TerraformVariables>(
const combinedEnv = env === undefined ? {} : { ...env }; const combinedEnv = env === undefined ? {} : { ...env };
for (const [key, value] of Object.entries(vars)) { for (const [key, value] of Object.entries(vars)) {
// Convert arrays to JSON strings combinedEnv[`TF_VAR_${key}`] = String(value);
combinedEnv[`TF_VAR_${key}`] = Array.isArray(value) ? JSON.stringify(value) : String(value);
} }
const proc = spawn( const proc = spawn(

View File

@@ -21,14 +21,39 @@ for dir in "${changed_dirs[@]}"; do
if [[ -f "$dir/README.md" ]]; then if [[ -f "$dir/README.md" ]]; then
file="$dir/README.md" file="$dir/README.md"
tmpfile=$(mktemp /tmp/tempfile.XXXXXX) tmpfile=$(mktemp /tmp/tempfile.XXXXXX)
awk -v tag="$LATEST_TAG" '{ awk -v tag="$LATEST_TAG" '
if ($1 == "version" && $2 == "=") { BEGIN { in_code_block = 0; in_nested_block = 0 }
sub(/"[^"]*"/, "\"" tag "\"") {
print # Detect the start and end of Markdown code blocks.
} else { if ($0 ~ /^```/) {
in_code_block = !in_code_block
# Reset nested block tracking when exiting a code block.
if (!in_code_block) {
in_nested_block = 0
}
}
# Handle nested blocks within a code block.
if (in_code_block) {
# Detect the start of a nested block (skipping "module" blocks).
if ($0 ~ /{/ && !($1 == "module" || $1 ~ /^[a-zA-Z0-9_]+$/)) {
in_nested_block++
}
# Detect the end of a nested block.
if ($0 ~ /}/ && in_nested_block > 0) {
in_nested_block--
}
# Update "version" only if not in a nested block.
if (!in_nested_block && $1 == "version" && $2 == "=") {
sub(/"[^"]*"/, "\"" tag "\"")
}
}
print print
} }
}' "$file" > "$tmpfile" && mv "$tmpfile" "$file" ' "$file" > "$tmpfile" && mv "$tmpfile" "$file"
# Check if the README.md file has changed # Check if the README.md file has changed
if ! git diff --quiet -- "$dir/README.md"; then if ! git diff --quiet -- "$dir/README.md"; then