From 0afb18ea4bb904eea8811b4639bf9500f369c343 Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Sat, 28 Feb 2026 09:02:54 +0530 Subject: [PATCH 01/10] feat: add pre-install plugins support --- registry/coder/modules/jetbrains/README.md | 39 ++++ .../modules/jetbrains/jetbrains.tftest.hcl | 34 ++++ registry/coder/modules/jetbrains/main.tf | 34 ++++ .../jetbrains/scripts/install_plugins.sh | 167 ++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 registry/coder/modules/jetbrains/scripts/install_plugins.sh diff --git a/registry/coder/modules/jetbrains/README.md b/registry/coder/modules/jetbrains/README.md index 7fa8f6747..d28c5b9c2 100644 --- a/registry/coder/modules/jetbrains/README.md +++ b/registry/coder/modules/jetbrains/README.md @@ -136,6 +136,45 @@ module "jetbrains" { } ``` +### Plugin Auto‑Installer + +This module now supports automatic JetBrains plugin installation inside your workspace. + +To get a plugin ID, open the plugin’s page on the JetBrains Marketplace. Scroll down to Additional Information and look for Plugin ID. Use that value in the configuration below. + +```tf +module "jetbrains" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/jetbrains/coder" + version = "1.2.1" + agent_id = coder_agent.main.id + folder = "/home/coder/project" + default = ["IU", "PY"] + + jetbrains_plugins = { + "PY" = ["com.koxudaxi.pydantic", "com.intellij.kubernetes"] + "IU" = ["", ""] + "WS" = ["", ""] + "GO" = ["", ""] + "CL" = ["", ""] + "PS" = ["", ""] + "RD" = ["", ""] + "RM" = ["", ""] + "RR" = ["", ""] + } +} +``` + +> [!IMPORTANT] \ +> After installing the IDE, restart the workspace. +> When the workspace starts again, the scripts will detect the installed IDE and automatically install the configured plugins. +> +> This module prerequisites and limitations +> +> 1. Requires JetBrains Toolbox to be installed +> 2. Requires jq to be available +> 3. Only works on Debian/Ubuntu-based systems (due to apt-get usage) + ### Accessing the IDE Metadata You can now reference the output `ide_metadata` as a map. diff --git a/registry/coder/modules/jetbrains/jetbrains.tftest.hcl b/registry/coder/modules/jetbrains/jetbrains.tftest.hcl index dba9551da..973a74295 100644 --- a/registry/coder/modules/jetbrains/jetbrains.tftest.hcl +++ b/registry/coder/modules/jetbrains/jetbrains.tftest.hcl @@ -351,3 +351,37 @@ run "validate_output_schema" { error_message = "The ide_metadata output schema has changed. Please update the 'main.tf' and this test." } } + +run "no_plugin_script_when_plugins_empty" { + command = plan + + variables { + agent_id = "foo" + folder = "/home/coder" + default = ["PY"] + jetbrains_plugins = {} + } + + assert { + condition = length(resource.coder_script.install_jetbrains_plugins) == 0 + error_message = "Expected no plugin install script when plugins list is empty" + } +} + +run "plugin_script_created_when_plugins_provided" { + command = plan + + variables { + agent_id = "foo" + folder = "/home/coder" + default = ["PY"] + jetbrains_plugins = { + "PY" = ["com.koxudaxi.pydantic", "com.intellij.kubernetes"] + } + } + + assert { + condition = length(resource.coder_script.install_jetbrains_plugins) == 1 + error_message = "Expected script to be created when plugins are provided" + } +} \ No newline at end of file diff --git a/registry/coder/modules/jetbrains/main.tf b/registry/coder/modules/jetbrains/main.tf index 2fac060f1..e4290b181 100644 --- a/registry/coder/modules/jetbrains/main.tf +++ b/registry/coder/modules/jetbrains/main.tf @@ -173,6 +173,12 @@ variable "ide_config" { } } +variable "jetbrains_plugins" { + type = map(list(string)) + description = "Map of IDE product codes to plugin ID lists. Example: { IU = [\"com.foo\"], GO = [\"org.bar\"] }." + default = {} +} + locals { # Parse HTTP responses once with error handling for air-gapped environments parsed_responses = { @@ -214,6 +220,10 @@ locals { # Convert the parameter value to a set for for_each selected_ides = length(var.default) == 0 ? toset(jsondecode(coalesce(data.coder_parameter.jetbrains_ides[0].value, "[]"))) : toset(var.default) + + plugin_map_b64 = base64encode(jsonencode(var.jetbrains_plugins)) + + plugin_install_script = file("${path.module}/script/install_plugins.sh") } data "coder_parameter" "jetbrains_ides" { @@ -241,6 +251,30 @@ data "coder_parameter" "jetbrains_ides" { data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} +resource "coder_script" "install_jetbrains_plugins" { + count = length(var.jetbrains_plugins) > 0 ? 1 : 0 + agent_id = var.agent_id + display_name = "Install JetBrains Plugins" + run_on_start = true + + script = <<-EOT + #!/bin/bash + set -o errexit + set -o pipefail + + CONFIG_DIR="$HOME/.config/jetbrains" + + mkdir -p "$CONFIG_DIR" + echo -n "${local.plugin_map_b64}" | base64 -d > "$CONFIG_DIR/plugins.json" + chmod 600 "$CONFIG_DIR/plugins.json" + + echo -n '${base64encode(local.plugin_install_script)}' | base64 -d > /tmp/install_plugins.sh + chmod +x /tmp/install_plugins.sh + + /tmp/install_plugins.sh > /tmp/install_plugins.log 2>&1 & + EOT +} + resource "coder_app" "jetbrains" { for_each = local.selected_ides agent_id = var.agent_id diff --git a/registry/coder/modules/jetbrains/scripts/install_plugins.sh b/registry/coder/modules/jetbrains/scripts/install_plugins.sh new file mode 100644 index 000000000..868bbc74e --- /dev/null +++ b/registry/coder/modules/jetbrains/scripts/install_plugins.sh @@ -0,0 +1,167 @@ +#!/bin/bash +# set -euo pipefail + +LOGFILE="$HOME/.config/jetbrains/install_plugins.log" +TOOLBOX_BASE="$HOME/.local/share/JetBrains/Toolbox/apps" +PLUGIN_MAP_FILE="$HOME/.config/jetbrains/plugins.json" + +if command -v apt-get > /dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y libfreetype6 +else + echo "Warning: 'apt-get' not found. Please ensure 'libfreetype6' is installed manually for your distribution." >&2 +fi + +mkdir -p "$(dirname "$LOGFILE")" + +exec > >(tee -a "$LOGFILE") 2>&1 + +log() { + printf '%s %s\n' "$(date --iso-8601=seconds)" "$*" | tee -a "$LOGFILE" +} + +# -------- Read plugin JSON -------- +get_enabled_codes() { + jq -r 'keys[]' "$PLUGIN_MAP_FILE" +} + +get_plugins_for_code() { + jq -r --arg CODE "$1" '.[$CODE][]?' "$PLUGIN_MAP_FILE" 2> /dev/null || true +} + +# -------- Product code mapping -------- +map_folder_to_code() { + case "$1" in + *pycharm*) echo "PY" ;; + *idea*) echo "IU" ;; + *webstorm*) echo "WS" ;; + *goland*) echo "GO" ;; + *clion*) echo "CL" ;; + *phpstorm*) echo "PS" ;; + *rider*) echo "RD" ;; + *rubymine*) echo "RM" ;; + *rustrover*) echo "RR" ;; + *) echo "" ;; + esac +} + +# -------- CLI launcher names -------- +launcher_for_code() { + case "$1" in + PY) echo "pycharm" ;; + IU) echo "idea" ;; + WS) echo "webstorm" ;; + GO) echo "goland" ;; + CL) echo "clion" ;; + PS) echo "phpstorm" ;; + RD) echo "rider" ;; + RM) echo "rubymine" ;; + RR) echo "rustrover" ;; + *) return 1 ;; + esac +} + +find_cli_launcher() { + local exe + exe="$(launcher_for_code "$1")" || return 1 + + # Look for the newest version directory + local latest_version + latest_version=$(find "$2" -maxdepth 2 -type d -name "ch-*" 2> /dev/null | sort -V | tail -1) + + if [ -n "$latest_version" ] && [ -f "$latest_version/bin/$exe" ]; then + echo "$latest_version/bin/$exe" + elif [ -f "$2/bin/$exe" ]; then + echo "$2/bin/$exe" + else + return 1 + fi +} + +install_plugin() { + log "Installing plugin: $2" + if "$1" installPlugins "$2"; then + log "Successfully installed plugin: $2" + else + log "Failed to install plugin: $2" + return 1 + fi +} + +# -------- Main -------- +log "Plugin installer started" + +if [ ! -f "$PLUGIN_MAP_FILE" ]; then + log "No plugins.json found. Exiting." + exit 0 +fi + +if [ ! -d "$TOOLBOX_BASE" ]; then + log "Toolbox directory not found. Exiting." + exit 0 +fi + +# Load list of IDE codes user actually needs +mapfile -t pending_codes < <(get_enabled_codes) + +if [ ${#pending_codes[@]} -eq 0 ]; then + log "No plugin entries found. Exiting." + exit 0 +fi + +log "Waiting for IDE installation. Pending codes: ${pending_codes[*]}" + +MAX_ATTEMPTS=10 +attempt=0 + +# Loop until all plugins installed +while [ ${#pending_codes[@]} -gt 0 ] && [ $attempt -lt $MAX_ATTEMPTS ]; do + + for product_dir in "$TOOLBOX_BASE"/*; do + [ -d "$product_dir" ] || continue + + product_name="$(basename "$product_dir")" + code="$(map_folder_to_code "$product_name")" + + # Only process codes user requested + if [[ ! " ${pending_codes[*]} " =~ " $code " ]]; then + continue + fi + + cli_launcher_path="$(find_cli_launcher "$code" "$product_dir")" || continue + + log "Detected IDE $code at $product_dir" + + plugins="$(get_plugins_for_code "$code")" + if [ -z "$plugins" ]; then + log "No plugins for $code" + continue + fi + + while read -r plugin; do + install_plugin "$cli_launcher_path" "$plugin" + done <<< "$plugins" + + # remove code from pending list after success + tmp=() + for c in "${pending_codes[@]}"; do + [ "$c" != "$code" ] && tmp+=("$c") + done + pending_codes=("${tmp[@]}") + + log "Finished $code. Remaining: ${pending_codes[*]:-none}" + + done + # If still pending, wait and retry + if [ ${#pending_codes[@]} -gt 0 ]; then + sleep 5 + ((attempt++)) + fi +done + +if [ ${#pending_codes[@]} -gt 0 ]; then + log "Timeout: IDEs not found: ${pending_codes[*]}" + exit 1 +fi + +log "All plugins installed. Exiting." \ No newline at end of file From f0d55e1dffe9b4a14118efc84baa43688620e037 Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Sat, 28 Feb 2026 11:17:24 +0530 Subject: [PATCH 02/10] fix: typos --- registry/coder/modules/jetbrains/main.tf | 4 ++-- registry/coder/modules/jetbrains/scripts/install_plugins.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/jetbrains/main.tf b/registry/coder/modules/jetbrains/main.tf index e4290b181..0591fc65e 100644 --- a/registry/coder/modules/jetbrains/main.tf +++ b/registry/coder/modules/jetbrains/main.tf @@ -223,7 +223,7 @@ locals { plugin_map_b64 = base64encode(jsonencode(var.jetbrains_plugins)) - plugin_install_script = file("${path.module}/script/install_plugins.sh") + plugin_install_script = file("${path.module}/scripts/install_plugins.sh") } data "coder_parameter" "jetbrains_ides" { @@ -271,7 +271,7 @@ resource "coder_script" "install_jetbrains_plugins" { echo -n '${base64encode(local.plugin_install_script)}' | base64 -d > /tmp/install_plugins.sh chmod +x /tmp/install_plugins.sh - /tmp/install_plugins.sh > /tmp/install_plugins.log 2>&1 & + /tmp/install_plugins.sh > /tmp/install_plugins.log 2>&1 EOT } diff --git a/registry/coder/modules/jetbrains/scripts/install_plugins.sh b/registry/coder/modules/jetbrains/scripts/install_plugins.sh index 868bbc74e..4374d7ef0 100644 --- a/registry/coder/modules/jetbrains/scripts/install_plugins.sh +++ b/registry/coder/modules/jetbrains/scripts/install_plugins.sh @@ -164,4 +164,4 @@ if [ ${#pending_codes[@]} -gt 0 ]; then exit 1 fi -log "All plugins installed. Exiting." \ No newline at end of file +log "All plugins installed. Exiting." From d5852fdbc99aaf540b599185bec0aa4c51d974c2 Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Sat, 28 Feb 2026 11:44:00 +0530 Subject: [PATCH 03/10] fix: update version --- registry/coder/modules/jetbrains/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/registry/coder/modules/jetbrains/README.md b/registry/coder/modules/jetbrains/README.md index d28c5b9c2..73bacfbb2 100644 --- a/registry/coder/modules/jetbrains/README.md +++ b/registry/coder/modules/jetbrains/README.md @@ -14,7 +14,7 @@ This module adds JetBrains IDE buttons to launch IDEs directly from the dashboar module "jetbrains" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jetbrains/coder" - version = "1.3.0" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -39,7 +39,7 @@ When `default` contains IDE codes, those IDEs are created directly without user module "jetbrains" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jetbrains/coder" - version = "1.3.0" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/home/coder/project" default = ["PY", "IU"] # Pre-configure PyCharm and IntelliJ IDEA @@ -52,7 +52,7 @@ module "jetbrains" { module "jetbrains" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jetbrains/coder" - version = "1.3.0" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/home/coder/project" # Show parameter with limited options @@ -66,7 +66,7 @@ module "jetbrains" { module "jetbrains" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jetbrains/coder" - version = "1.3.0" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/home/coder/project" default = ["IU", "PY"] @@ -81,7 +81,7 @@ module "jetbrains" { module "jetbrains" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jetbrains/coder" - version = "1.3.0" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/workspace/project" @@ -108,7 +108,7 @@ module "jetbrains" { module "jetbrains_pycharm" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jetbrains/coder" - version = "1.3.0" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/workspace/project" @@ -128,7 +128,7 @@ Add helpful tooltip text that appears when users hover over the IDE app buttons: module "jetbrains" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jetbrains/coder" - version = "1.3.0" + version = "1.4.0" agent_id = coder_agent.main.id folder = "/home/coder/project" default = ["IU", "PY"] @@ -165,7 +165,7 @@ module "jetbrains" { } ``` -> [!IMPORTANT] \ +> [!IMPORTANT] > After installing the IDE, restart the workspace. > When the workspace starts again, the scripts will detect the installed IDE and automatically install the configured plugins. > From 79a852ff79e167b0ef2fa2da4b4fdafae3d7a6c5 Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Tue, 10 Mar 2026 11:05:02 +0530 Subject: [PATCH 04/10] feat|fix: add check_plugins_installed and mark_plugins_installed, and fix the continuous wait for an IDE that is not installed --- .../jetbrains/scripts/install_plugins.sh | 127 +++++++++++++----- 1 file changed, 92 insertions(+), 35 deletions(-) diff --git a/registry/coder/modules/jetbrains/scripts/install_plugins.sh b/registry/coder/modules/jetbrains/scripts/install_plugins.sh index 4374d7ef0..3b6de0cd5 100644 --- a/registry/coder/modules/jetbrains/scripts/install_plugins.sh +++ b/registry/coder/modules/jetbrains/scripts/install_plugins.sh @@ -4,6 +4,7 @@ LOGFILE="$HOME/.config/jetbrains/install_plugins.log" TOOLBOX_BASE="$HOME/.local/share/JetBrains/Toolbox/apps" PLUGIN_MAP_FILE="$HOME/.config/jetbrains/plugins.json" +PLUGIN_ALREADY_INSTALLED_MAP="$HOME/.config/jetbrains" if command -v apt-get > /dev/null 2>&1; then sudo apt-get update @@ -29,6 +30,30 @@ get_plugins_for_code() { jq -r --arg CODE "$1" '.[$CODE][]?' "$PLUGIN_MAP_FILE" 2> /dev/null || true } +# Returns only plugins that are NOT already installed +check_plugins_installed() { + local code="$1" + shift + local plugins=("$@") + + local installed_file="$PLUGIN_ALREADY_INSTALLED_MAP/${code}_installed.json" + + # If no installed file exists, all plugins need to be installed + if [ ! -f "$installed_file" ]; then + printf '%s\n' "${plugins[@]}" + return 0 + fi + + installed_plugins=$(jq -r '.[]?' "$installed_file" 2>/dev/null) + + for plugin in "${plugins[@]}"; do + if ! echo "$installed_plugins" | grep -Fxq "$plugin"; then + echo "$plugin" + fi + done + return 0 +} + # -------- Product code mapping -------- map_folder_to_code() { case "$1" in @@ -78,10 +103,38 @@ find_cli_launcher() { fi } +# Marks a plugin as installed by adding it to the installed plugins JSON file +mark_plugins_installed() { + local code="$1" + local plugin="$2" + + local installed_file="$PLUGIN_ALREADY_INSTALLED_MAP/${code}_installed.json" + + mkdir -p "$PLUGIN_ALREADY_INSTALLED_MAP" + + # Create file with empty array if it doesn't exist + if [ ! -f "$installed_file" ]; then + echo '[]' > "$installed_file" || { + log "Error: Failed to create $installed_file" + return 1 + } + fi + + jq --arg PLUGIN "$plugin" '. += [$PLUGIN]' "$installed_file" > "${installed_file}.tmp" 2>/dev/null && \ + mv "${installed_file}.tmp" "$installed_file" || { + log "Error: Failed to update $installed_file with plugin $plugin" + rm -f "${installed_file}.tmp" + return 1 + } + log "Marked plugin as installed: $plugin" + return 0 +} + install_plugin() { log "Installing plugin: $2" if "$1" installPlugins "$2"; then log "Successfully installed plugin: $2" + return 0 else log "Failed to install plugin: $2" return 1 @@ -111,56 +164,60 @@ fi log "Waiting for IDE installation. Pending codes: ${pending_codes[*]}" -MAX_ATTEMPTS=10 -attempt=0 - # Loop until all plugins installed -while [ ${#pending_codes[@]} -gt 0 ] && [ $attempt -lt $MAX_ATTEMPTS ]; do - - for product_dir in "$TOOLBOX_BASE"/*; do - [ -d "$product_dir" ] || continue - - product_name="$(basename "$product_dir")" - code="$(map_folder_to_code "$product_name")" +for product_dir in "$TOOLBOX_BASE"/*; do + [ -d "$product_dir" ] || continue - # Only process codes user requested - if [[ ! " ${pending_codes[*]} " =~ " $code " ]]; then - continue - fi - - cli_launcher_path="$(find_cli_launcher "$code" "$product_dir")" || continue + product_name="$(basename "$product_dir")" + code="$(map_folder_to_code "$product_name")" - log "Detected IDE $code at $product_dir" - - plugins="$(get_plugins_for_code "$code")" - if [ -z "$plugins" ]; then - log "No plugins for $code" - continue - fi + # Only process codes user requested + if [[ ! " ${pending_codes[*]} " =~ " $code " ]]; then + continue + fi - while read -r plugin; do - install_plugin "$cli_launcher_path" "$plugin" - done <<< "$plugins" + plugins="$(get_plugins_for_code "$code")" + if [ -z "$plugins" ]; then + log "No plugins for $code" + continue + fi - # remove code from pending list after success + # Get only plugins that are not already installed + mapfile -t new_plugins < <(check_plugins_installed "$code" $(echo "$plugins" | tr '\n' ' ')) + if [ ${#new_plugins[@]} -eq 0 ]; then + log "All plugins for $code are already installed" + # Remove code from pending list since all plugins are installed tmp=() for c in "${pending_codes[@]}"; do - [ "$c" != "$code" ] && tmp+=("$c") + [ "$c" != "$code" ] && tmp+=("$c") done pending_codes=("${tmp[@]}") + continue + fi - log "Finished $code. Remaining: ${pending_codes[*]:-none}" + cli_launcher_path="$(find_cli_launcher "$code" "$product_dir")" || continue + log "Detected IDE $code at $product_dir" + log "Plugins to install for $code: ${#new_plugins[@]} plugin(s)" + # Install only the plugins that are not yet installed + for plugin in "${new_plugins[@]}"; do + if install_plugin "$cli_launcher_path" "$plugin"; then + # Mark plugin as installed after successful installation + mark_plugins_installed "$code" "$plugin" + fi done - # If still pending, wait and retry - if [ ${#pending_codes[@]} -gt 0 ]; then - sleep 5 - ((attempt++)) - fi + + # remove code from pending list after success + tmp=() + for c in "${pending_codes[@]}"; do + [ "$c" != "$code" ] && tmp+=("$c") + done + pending_codes=("${tmp[@]}") + log "Finished $code. Remaining: ${pending_codes[*]:-none}" done if [ ${#pending_codes[@]} -gt 0 ]; then - log "Timeout: IDEs not found: ${pending_codes[*]}" + log "These IDEs not found: ${pending_codes[*]}" exit 1 fi From 85077e2b0b83f557e3956272201f4afc96a711c8 Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Tue, 10 Mar 2026 11:24:20 +0530 Subject: [PATCH 05/10] fix: the plugins variable and style --- .../modules/jetbrains/scripts/install_plugins.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/registry/coder/modules/jetbrains/scripts/install_plugins.sh b/registry/coder/modules/jetbrains/scripts/install_plugins.sh index 3b6de0cd5..43ebd0b4a 100644 --- a/registry/coder/modules/jetbrains/scripts/install_plugins.sh +++ b/registry/coder/modules/jetbrains/scripts/install_plugins.sh @@ -44,7 +44,7 @@ check_plugins_installed() { return 0 fi - installed_plugins=$(jq -r '.[]?' "$installed_file" 2>/dev/null) + installed_plugins=$(jq -r '.[]?' "$installed_file" 2> /dev/null) for plugin in "${plugins[@]}"; do if ! echo "$installed_plugins" | grep -Fxq "$plugin"; then @@ -120,8 +120,8 @@ mark_plugins_installed() { } fi - jq --arg PLUGIN "$plugin" '. += [$PLUGIN]' "$installed_file" > "${installed_file}.tmp" 2>/dev/null && \ - mv "${installed_file}.tmp" "$installed_file" || { + jq --arg PLUGIN "$plugin" '. += [$PLUGIN]' "$installed_file" > "${installed_file}.tmp" 2> /dev/null \ + && mv "${installed_file}.tmp" "$installed_file" || { log "Error: Failed to update $installed_file with plugin $plugin" rm -f "${installed_file}.tmp" return 1 @@ -176,20 +176,21 @@ for product_dir in "$TOOLBOX_BASE"/*; do continue fi - plugins="$(get_plugins_for_code "$code")" - if [ -z "$plugins" ]; then + # Store plugins as array for consistency + mapfile -t plugins_list < <(get_plugins_for_code "$code") + if [ ${#plugins_list[@]} -eq 0 ]; then log "No plugins for $code" continue fi # Get only plugins that are not already installed - mapfile -t new_plugins < <(check_plugins_installed "$code" $(echo "$plugins" | tr '\n' ' ')) + mapfile -t new_plugins < <(check_plugins_installed "$code" "${plugins_list[@]}") if [ ${#new_plugins[@]} -eq 0 ]; then log "All plugins for $code are already installed" # Remove code from pending list since all plugins are installed tmp=() for c in "${pending_codes[@]}"; do - [ "$c" != "$code" ] && tmp+=("$c") + [ "$c" != "$code" ] && tmp+=("$c") done pending_codes=("${tmp[@]}") continue From d4ebd2d7971984e9f5d2e66ca433be5a55fa4a0c Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Tue, 10 Mar 2026 19:37:06 +0530 Subject: [PATCH 06/10] fix: script throws an error if any IDE plugins remain uninstalled --- registry/coder/modules/jetbrains/scripts/install_plugins.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/registry/coder/modules/jetbrains/scripts/install_plugins.sh b/registry/coder/modules/jetbrains/scripts/install_plugins.sh index 43ebd0b4a..350757ae0 100644 --- a/registry/coder/modules/jetbrains/scripts/install_plugins.sh +++ b/registry/coder/modules/jetbrains/scripts/install_plugins.sh @@ -219,7 +219,6 @@ done if [ ${#pending_codes[@]} -gt 0 ]; then log "These IDEs not found: ${pending_codes[*]}" - exit 1 fi -log "All plugins installed. Exiting." +log "Exiting." From 998c6776ce2e2d51e7489aaeaf8ad9de49451b4e Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Wed, 11 Mar 2026 18:12:58 +0530 Subject: [PATCH 07/10] fix: log duplication and add warning that some plugins are disabled by default --- registry/coder/modules/jetbrains/README.md | 3 +++ registry/coder/modules/jetbrains/scripts/install_plugins.sh | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/registry/coder/modules/jetbrains/README.md b/registry/coder/modules/jetbrains/README.md index 73bacfbb2..c7d25e209 100644 --- a/registry/coder/modules/jetbrains/README.md +++ b/registry/coder/modules/jetbrains/README.md @@ -175,6 +175,9 @@ module "jetbrains" { > 2. Requires jq to be available > 3. Only works on Debian/Ubuntu-based systems (due to apt-get usage) +> [!WARNING] +> Some plugins are disabled by default due to JetBrains security defaults, so you need to enable them manually. + ### Accessing the IDE Metadata You can now reference the output `ide_metadata` as a map. diff --git a/registry/coder/modules/jetbrains/scripts/install_plugins.sh b/registry/coder/modules/jetbrains/scripts/install_plugins.sh index 350757ae0..baf2ba220 100644 --- a/registry/coder/modules/jetbrains/scripts/install_plugins.sh +++ b/registry/coder/modules/jetbrains/scripts/install_plugins.sh @@ -18,7 +18,7 @@ mkdir -p "$(dirname "$LOGFILE")" exec > >(tee -a "$LOGFILE") 2>&1 log() { - printf '%s %s\n' "$(date --iso-8601=seconds)" "$*" | tee -a "$LOGFILE" + printf '%s %s\n' "$(date --iso-8601=seconds)" "$*" } # -------- Read plugin JSON -------- From 6af22cc771c3c1e8ad5bff9b1c10604411359263 Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Thu, 12 Mar 2026 00:18:35 +0530 Subject: [PATCH 08/10] fix: change the location of CONFIG_DIR --- registry/coder/modules/jetbrains/README.md | 2 +- registry/coder/modules/jetbrains/main.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/coder/modules/jetbrains/README.md b/registry/coder/modules/jetbrains/README.md index c7d25e209..e74835f85 100644 --- a/registry/coder/modules/jetbrains/README.md +++ b/registry/coder/modules/jetbrains/README.md @@ -176,7 +176,7 @@ module "jetbrains" { > 3. Only works on Debian/Ubuntu-based systems (due to apt-get usage) > [!WARNING] -> Some plugins are disabled by default due to JetBrains security defaults, so you need to enable them manually. +> Some plugins are disabled by default due to JetBrains security defaults, so you might need to enable them manually. ### Accessing the IDE Metadata diff --git a/registry/coder/modules/jetbrains/main.tf b/registry/coder/modules/jetbrains/main.tf index 0591fc65e..dd9304946 100644 --- a/registry/coder/modules/jetbrains/main.tf +++ b/registry/coder/modules/jetbrains/main.tf @@ -262,7 +262,7 @@ resource "coder_script" "install_jetbrains_plugins" { set -o errexit set -o pipefail - CONFIG_DIR="$HOME/.config/jetbrains" + CONFIG_DIR="$HOME/.config/Jetbrains" mkdir -p "$CONFIG_DIR" echo -n "${local.plugin_map_b64}" | base64 -d > "$CONFIG_DIR/plugins.json" From a2aa95ad06fd5fbfbc2c892ad38a5ad4e4340e5a Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Thu, 12 Mar 2026 00:23:31 +0530 Subject: [PATCH 09/10] docs: improve wording in README --- registry/coder/modules/jetbrains/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/jetbrains/README.md b/registry/coder/modules/jetbrains/README.md index e74835f85..711e7ee66 100644 --- a/registry/coder/modules/jetbrains/README.md +++ b/registry/coder/modules/jetbrains/README.md @@ -173,7 +173,7 @@ module "jetbrains" { > > 1. Requires JetBrains Toolbox to be installed > 2. Requires jq to be available -> 3. Only works on Debian/Ubuntu-based systems (due to apt-get usage) +> 3. only works in a Linux environment. > [!WARNING] > Some plugins are disabled by default due to JetBrains security defaults, so you might need to enable them manually. From 25cf7eee6cdee65e4be5e13fc62d3286795223d9 Mon Sep 17 00:00:00 2001 From: Harsh panwar Date: Fri, 13 Mar 2026 21:49:35 +0530 Subject: [PATCH 10/10] fix: make script compatible with all distributions --- .../jetbrains/scripts/install_plugins.sh | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/registry/coder/modules/jetbrains/scripts/install_plugins.sh b/registry/coder/modules/jetbrains/scripts/install_plugins.sh index baf2ba220..026f3868f 100644 --- a/registry/coder/modules/jetbrains/scripts/install_plugins.sh +++ b/registry/coder/modules/jetbrains/scripts/install_plugins.sh @@ -6,11 +6,31 @@ TOOLBOX_BASE="$HOME/.local/share/JetBrains/Toolbox/apps" PLUGIN_MAP_FILE="$HOME/.config/jetbrains/plugins.json" PLUGIN_ALREADY_INSTALLED_MAP="$HOME/.config/jetbrains" -if command -v apt-get > /dev/null 2>&1; then - sudo apt-get update - sudo apt-get install -y libfreetype6 -else - echo "Warning: 'apt-get' not found. Please ensure 'libfreetype6' is installed manually for your distribution." >&2 +# -------- Install dependencies -------- +install_dependencies() { + if command -v apt-get > /dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y libfreetype6 jq + elif command -v dnf > /dev/null 2>&1; then + sudo dnf install -y freetype-devel jq + elif command -v yum > /dev/null 2>&1; then + sudo yum install -y freetype-devel jq + elif command -v pacman > /dev/null 2>&1; then + sudo pacman -Sy --noconfirm freetype2 jq + elif command -v apk > /dev/null 2>&1; then + sudo apk add --no-cache freetype-dev jq + else + echo "Warning: Package manager not found. Please ensure 'libfreetype6' and 'jq' are installed manually for your distribution." >&2 + return 1 + fi +} + +install_dependencies || true + +# Verify jq is available +if ! command -v jq > /dev/null 2>&1; then + echo "Error: 'jq' is required but not installed. Please install it manually." >&2 + exit 1 fi mkdir -p "$(dirname "$LOGFILE")"