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
module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24"
version = "1.0.25"
agent_id = coder_agent.example.id
agent_name = "example"
folder = "/home/coder/example"
jetbrains_ides = ["CL", "GO", "IU", "PY", "WS"]
default = ["GO"]
default = "GO"
}
```
@@ -32,27 +32,52 @@ module "jetbrains_gateway" {
```tf
module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24"
version = "1.0.25"
agent_id = coder_agent.example.id
agent_name = "example"
folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"]
default = ["GO"]
default = "GO"
}
```
### Use the fixed version
### Use the latest version of each IDE
```tf
module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24"
version = "1.0.25"
agent_id = coder_agent.example.id
agent_name = "example"
folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"]
default = ["GO"]
latest = false # current version is 2024.3
jetbrains_ides = ["IU", "PY"]
default = "IU"
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
module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24"
version = "1.0.25"
agent_id = coder_agent.example.id
agent_name = "example"
folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"]
default = ["GO"]
default = "GO"
latest = true
channel = "eap"
}
@@ -79,29 +104,14 @@ Due to the highest priority of the `ide_download_link` parameter in the `(jetbra
```tf
module "jetbrains_gateway" {
source = "registry.coder.com/modules/jetbrains-gateway/coder"
version = "1.0.24"
version = "1.0.25"
agent_id = coder_agent.example.id
agent_name = "example"
folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"]
releases_base_link = "https://releases.internal.site/"
download_base_link = "https://download.internal.site/"
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"]
default = "GO"
}
```

View File

@@ -16,13 +16,14 @@ describe("jetbrains-gateway", async () => {
it("should create a link with the default values", async () => {
const state = await runTerraformApply(import.meta.dir, {
// These are all required.
agent_id: "foo",
agent_name: "foo",
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",
]);
);
const coder_app = state.resources.find(
(res) => res.type === "coder_app" && res.name === "gateway",
@@ -33,31 +34,13 @@ describe("jetbrains-gateway", async () => {
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, {
agent_id: "foo",
agent_name: "foo",
folder: "/home/foo",
jetbrains_ides: ["IU", "PY"],
jetbrains_ides: '["IU", "GO", "PY"]',
});
expect(state.outputs.identifier.value).toEqual(["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",
]);
expect(state.outputs.identifier.value).toBe("IU");
});
});

View File

@@ -39,23 +39,9 @@ variable "folder" {
}
variable "default" {
default = []
type = list(string)
description = "List of default IDEs to be added to the Workspace page."
# 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"])}."
}
default = ""
type = string
description = "Default IDE"
}
variable "order" {
@@ -73,7 +59,7 @@ variable "coder_parameter_order" {
variable "latest" {
type = bool
description = "Whether to fetch the latest version of the IDE."
default = true
default = false
}
variable "channel" {
@@ -138,7 +124,7 @@ variable "jetbrains_ide_versions" {
variable "jetbrains_ides" {
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"]
validation {
condition = (
@@ -253,42 +239,23 @@ locals {
}
}
identifier = try([data.coder_parameter.jetbrains_ide[0].value], var.default)
list_json_data = var.latest ? [
for ide in local.identifier : jsondecode(data.http.jetbrains_ide_versions[ide].response_body)
] : []
list_key = var.latest ? [
for j in local.list_json_data : keys(j)[0]
] : []
download_links = length(local.list_key) > 0 ? [
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]
icon = local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].icon
json_data = var.latest ? jsondecode(data.http.jetbrains_ide_versions[data.coder_parameter.jetbrains_ide.value].response_body) : {}
key = var.latest ? keys(local.json_data)[0] : ""
display_name = local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].name
identifier = data.coder_parameter.jetbrains_ide.value
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
version = var.latest ? local.json_data[local.key][0].version : var.jetbrains_ide_versions[data.coder_parameter.jetbrains_ide.value].version
}
data "coder_parameter" "jetbrains_ide" {
# remove the coder_parameter if there are multiple default
count = length(var.default) > 1 ? 0 : 1
type = "string"
name = "jetbrains_ide"
display_name = "JetBrains IDE"
icon = "/icon/gateway.svg"
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
dynamic "option" {
@@ -305,11 +272,10 @@ data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}
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
slug = "${var.slug}-${lower(each.value)}"
display_name = local.jetbrains_ides[each.value].name
icon = local.jetbrains_ides[each.value].icon
slug = var.slug
display_name = local.display_name
icon = local.icon
external = true
order = var.order
url = join("", [
@@ -326,45 +292,38 @@ resource "coder_app" "gateway" {
"&token=",
"$SESSION_TOKEN",
"&ide_product_code=",
each.value,
data.coder_parameter.jetbrains_ide.value,
"&ide_build_number=",
local.jetbrains_ides[each.value].build_number,
local.build_number,
"&ide_download_link=",
local.jetbrains_ides[each.value].download_link,
local.download_link,
])
}
output "identifier" {
value = local.identifier
description = "The product code of the JetBrains IDE."
value = local.identifier
}
output "display_name" {
value = [for key in keys(coder_app.gateway) : coder_app.gateway[key].display_name]
description = "The display name of the JetBrains IDE."
value = local.display_name
}
output "icon" {
value = [for key in keys(coder_app.gateway) : coder_app.gateway[key].icon]
description = "The icon of the JetBrains IDE."
value = local.icon
}
output "download_link" {
value = local.download_links
description = "The download link of the JetBrains IDE."
value = local.download_link
}
output "build_number" {
value = local.build_numbers
description = "The build number of the JetBrains IDE."
value = local.build_number
}
output "version" {
value = local.versions
description = "The version of the JetBrains IDE."
value = local.version
}
output "url" {
value = [for key in keys(coder_app.gateway) : coder_app.gateway[key].url]
description = "The URL to connect to the JetBrains IDE."
}
value = coder_app.gateway.url
}

View File

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

View File

@@ -21,14 +21,39 @@ for dir in "${changed_dirs[@]}"; do
if [[ -f "$dir/README.md" ]]; then
file="$dir/README.md"
tmpfile=$(mktemp /tmp/tempfile.XXXXXX)
awk -v tag="$LATEST_TAG" '{
if ($1 == "version" && $2 == "=") {
sub(/"[^"]*"/, "\"" tag "\"")
print
} else {
awk -v tag="$LATEST_TAG" '
BEGIN { in_code_block = 0; in_nested_block = 0 }
{
# Detect the start and end of Markdown code blocks.
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
}
}' "$file" > "$tmpfile" && mv "$tmpfile" "$file"
' "$file" > "$tmpfile" && mv "$tmpfile" "$file"
# Check if the README.md file has changed
if ! git diff --quiet -- "$dir/README.md"; then