From b108185c14ae74cbff9dab8db1722e6b0f5dc10e Mon Sep 17 00:00:00 2001 From: Harsh Singh Panwar Date: Wed, 22 Apr 2026 09:17:53 +0530 Subject: [PATCH] feature (jetbrains-plugins): add module for installing jetbrains plugin (#772) Co-authored-by: DevCats Co-authored-by: DevCats --- registry/harsh9485/.images/avatar.png | Bin 0 -> 19310 bytes registry/harsh9485/README.md | 11 + .../modules/jetbrains-plugins/README.md | 80 +++++++ .../jetbrains-plugins.tftest.hcl | 44 ++++ .../modules/jetbrains-plugins/main.tf | 59 +++++ .../scripts/install_plugins.sh | 223 ++++++++++++++++++ 6 files changed, 417 insertions(+) create mode 100644 registry/harsh9485/.images/avatar.png create mode 100644 registry/harsh9485/README.md create mode 100644 registry/harsh9485/modules/jetbrains-plugins/README.md create mode 100644 registry/harsh9485/modules/jetbrains-plugins/jetbrains-plugins.tftest.hcl create mode 100644 registry/harsh9485/modules/jetbrains-plugins/main.tf create mode 100644 registry/harsh9485/modules/jetbrains-plugins/scripts/install_plugins.sh diff --git a/registry/harsh9485/.images/avatar.png b/registry/harsh9485/.images/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..938202b960c558dd13f9b15d55b0f0cfddbdc67c GIT binary patch literal 19310 zcmbTe2RK~a_clCQln^N+x=9c-_S$=`d);g8yx%>{gMS#_f)s2Hi55m5Mg>wt*vIQ$01j53@`uzj?^9KtX z2N&-eJ^>-o^_w7UEF2tcTpT<+TwI`}AMhOr_ZHsm``nV(?x?-Qr*{JL1Vn!!V2~

2!ylCx8Gf75$~OnUH~3eV5F{xu57RBj4PEy(^J^ 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 [!IMPORTANT] +> After installing the IDE, restart the workspace. On the next start the +> module detects installed IDEs and automatically installs the configured +> plugins. + +Some plugins may be disabled by default due to JetBrains security +defaults — you might need to enable them manually in the IDE. diff --git a/registry/harsh9485/modules/jetbrains-plugins/jetbrains-plugins.tftest.hcl b/registry/harsh9485/modules/jetbrains-plugins/jetbrains-plugins.tftest.hcl new file mode 100644 index 00000000..9f432932 --- /dev/null +++ b/registry/harsh9485/modules/jetbrains-plugins/jetbrains-plugins.tftest.hcl @@ -0,0 +1,44 @@ +run "no_script_when_plugins_empty" { + command = plan + + variables { + agent_id = "foo" + jetbrains_plugins = {} + } + + assert { + condition = length(resource.coder_script.install_jetbrains_plugins) == 0 + error_message = "Expected no plugin install script when plugins map is empty" + } +} + +run "script_created_when_plugins_provided" { + command = plan + + variables { + agent_id = "foo" + 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" + } +} + +run "rejects_invalid_product_code" { + command = plan + + variables { + agent_id = "foo" + jetbrains_plugins = { + "INVALID" = ["com.example.plugin"] + } + } + + expect_failures = [ + var.jetbrains_plugins, + ] +} diff --git a/registry/harsh9485/modules/jetbrains-plugins/main.tf b/registry/harsh9485/modules/jetbrains-plugins/main.tf new file mode 100644 index 00000000..149979a2 --- /dev/null +++ b/registry/harsh9485/modules/jetbrains-plugins/main.tf @@ -0,0 +1,59 @@ +terraform { + required_version = ">= 1.9" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.5" + } + } +} + +variable "agent_id" { + type = string + description = "The resource ID of a Coder agent." +} + +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 = {} + + validation { + condition = alltrue([ + for code in keys(var.jetbrains_plugins) : contains( + ["CL", "GO", "IU", "PS", "PY", "RD", "RM", "RR", "WS"], code + ) + ]) + error_message = "Keys must be valid JetBrains product codes: CL, GO, IU, PS, PY, RD, RM, RR, WS." + } +} + +locals { + plugin_map_b64 = base64encode(jsonencode(var.jetbrains_plugins)) + plugin_install_script = file("${path.module}/scripts/install_plugins.sh") +} + +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 + EOT +} diff --git a/registry/harsh9485/modules/jetbrains-plugins/scripts/install_plugins.sh b/registry/harsh9485/modules/jetbrains-plugins/scripts/install_plugins.sh new file mode 100644 index 00000000..95feb21d --- /dev/null +++ b/registry/harsh9485/modules/jetbrains-plugins/scripts/install_plugins.sh @@ -0,0 +1,223 @@ +#!/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" +PLUGIN_ALREADY_INSTALLED_MAP="$HOME/.config/JetBrains" + +# 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")" + +exec > >(tee -a "$LOGFILE") 2>&1 + +log() { + printf '%s %s\n' "$(date --iso-8601=seconds)" "$*" +} + +# -------- 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 +} + +# 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 + *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 +} + +# 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 + 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[*]}" + +# Loop until all plugins installed +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 + + # 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" "${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") + done + pending_codes=("${tmp[@]}") + continue + fi + + 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 + + # 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 "These IDEs not found: ${pending_codes[*]}" +fi + +log "Exiting."