From 57f52388ef7df7b9246a8704ed882bbf8c88a448 Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Mon, 13 Apr 2026 16:02:24 +0000 Subject: [PATCH 01/12] feat(registry/coder/modules/coder-utils): make install_script and start_script optional Both variables now default to null. Their coder_script resources are conditionally created with count, matching the existing pattern for pre_install_script and post_install_script. Sync dependency resolution is computed in locals so each stage waits for its closest existing predecessor in the chain: pre_install -> install -> post_install -> start. Outputs return null when the corresponding variable is not provided. --- .../coder/modules/coder-utils/main.test.ts | 1 - registry/coder/modules/coder-utils/main.tf | 42 ++- .../coder/modules/coder-utils/main.tftest.hcl | 250 ++++++++++++++++-- 3 files changed, 256 insertions(+), 37 deletions(-) diff --git a/registry/coder/modules/coder-utils/main.test.ts b/registry/coder/modules/coder-utils/main.test.ts index 5987c3288..bb64b5c59 100644 --- a/registry/coder/modules/coder-utils/main.test.ts +++ b/registry/coder/modules/coder-utils/main.test.ts @@ -8,6 +8,5 @@ describe("coder-utils", async () => { agent_id: "test-agent-id", agent_name: "test-agent", module_dir_name: ".test-module", - start_script: "echo 'start'", }); }); diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index cfb8b778a..8d9b868db 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -41,6 +41,7 @@ variable "post_install_script" { variable "start_script" { type = string description = "Script that starts AgentAPI." + default = null } variable "agent_name" { @@ -58,7 +59,7 @@ locals { encoded_pre_install_script = var.pre_install_script != null ? base64encode(var.pre_install_script) : "" encoded_install_script = var.install_script != null ? base64encode(var.install_script) : "" encoded_post_install_script = var.post_install_script != null ? base64encode(var.post_install_script) : "" - encoded_start_script = base64encode(var.start_script) + encoded_start_script = var.start_script != null ? base64encode(var.start_script) : "" pre_install_script_name = "${var.agent_name}-pre_install_script" install_script_name = "${var.agent_name}-install_script" @@ -76,6 +77,25 @@ locals { install_log_path = "${local.module_dir_path}/install.log" post_install_log_path = "${local.module_dir_path}/post_install.log" start_log_path = "${local.module_dir_path}/start.log" + + # Sync dependency resolution: each stage waits for its closest predecessor. + # Chain order: pre_install -> install -> post_install -> start + post_install_sync_deps = ( + var.install_script != null ? local.install_script_name : ( + var.pre_install_script != null ? local.pre_install_script_name : null + ) + ) + + start_sync_deps = ( + var.post_install_script != null && var.install_script != null + ? "${local.install_script_name} ${local.post_install_script_name}" : ( + var.post_install_script != null ? local.post_install_script_name : ( + var.install_script != null ? local.install_script_name : ( + var.pre_install_script != null ? local.pre_install_script_name : null + ) + ) + ) + ) } resource "coder_script" "pre_install_script" { @@ -101,6 +121,7 @@ resource "coder_script" "pre_install_script" { } resource "coder_script" "install_script" { + count = var.install_script != null ? 1 : 0 agent_id = var.agent_id display_name = "Install Script" run_on_start = true @@ -134,7 +155,9 @@ resource "coder_script" "post_install_script" { set -o pipefail trap 'coder exp sync complete ${local.post_install_script_name}' EXIT - coder exp sync want ${local.post_install_script_name} ${local.install_script_name} + %{if local.post_install_sync_deps != null~} + coder exp sync want ${local.post_install_script_name} ${local.post_install_sync_deps} + %{endif~} coder exp sync start ${local.post_install_script_name} echo -n '${local.encoded_post_install_script}' | base64 -d > ${local.post_install_path} @@ -145,6 +168,7 @@ resource "coder_script" "post_install_script" { } resource "coder_script" "start_script" { + count = var.start_script != null ? 1 : 0 agent_id = var.agent_id display_name = "Start Script" run_on_start = true @@ -155,10 +179,8 @@ resource "coder_script" "start_script" { trap 'coder exp sync complete ${local.start_script_name}' EXIT - %{if var.post_install_script != null~} - coder exp sync want ${local.start_script_name} ${local.install_script_name} ${local.post_install_script_name} - %{else~} - coder exp sync want ${local.start_script_name} ${local.install_script_name} + %{if local.start_sync_deps != null~} + coder exp sync want ${local.start_script_name} ${local.start_sync_deps} %{endif~} coder exp sync start ${local.start_script_name} @@ -171,20 +193,20 @@ resource "coder_script" "start_script" { output "pre_install_script_name" { description = "The name of the pre-install script for sync." - value = local.pre_install_script_name + value = var.pre_install_script != null ? local.pre_install_script_name : null } output "install_script_name" { description = "The name of the install script for sync." - value = local.install_script_name + value = var.install_script != null ? local.install_script_name : null } output "post_install_script_name" { description = "The name of the post-install script for sync." - value = local.post_install_script_name + value = var.post_install_script != null ? local.post_install_script_name : null } output "start_script_name" { description = "The name of the start script for sync." - value = local.start_script_name + value = var.start_script != null ? local.start_script_name : null } \ No newline at end of file diff --git a/registry/coder/modules/coder-utils/main.tftest.hcl b/registry/coder/modules/coder-utils/main.tftest.hcl index d1228a6d4..4432e4be3 100644 --- a/registry/coder/modules/coder-utils/main.tftest.hcl +++ b/registry/coder/modules/coder-utils/main.tftest.hcl @@ -35,19 +35,24 @@ run "test_with_all_scripts" { error_message = "Pre-install script should run on start" } - # Verify install_script is created + # Verify install_script is created when provided assert { - condition = coder_script.install_script.agent_id == "test-agent-id" + condition = length(coder_script.install_script) == 1 + error_message = "Install script should be created when install_script is provided" + } + + assert { + condition = coder_script.install_script[0].agent_id == "test-agent-id" error_message = "Install script agent ID should match input" } assert { - condition = coder_script.install_script.display_name == "Install Script" + condition = coder_script.install_script[0].display_name == "Install Script" error_message = "Install script should have correct display name" } assert { - condition = coder_script.install_script.run_on_start == true + condition = coder_script.install_script[0].run_on_start == true error_message = "Install script should run on start" } @@ -72,19 +77,24 @@ run "test_with_all_scripts" { error_message = "Post-install script should run on start" } - # Verify start_script is created + # Verify start_script is created when provided assert { - condition = coder_script.start_script.agent_id == "test-agent-id" + condition = length(coder_script.start_script) == 1 + error_message = "Start script should be created when start_script is provided" + } + + assert { + condition = coder_script.start_script[0].agent_id == "test-agent-id" error_message = "Start script agent ID should match input" } assert { - condition = coder_script.start_script.display_name == "Start Script" + condition = coder_script.start_script[0].display_name == "Start Script" error_message = "Start script should have correct display name" } assert { - condition = coder_script.start_script.run_on_start == true + condition = coder_script.start_script[0].run_on_start == true error_message = "Start script should run on start" } @@ -110,8 +120,8 @@ run "test_with_all_scripts" { } } -# Test with only required scripts (no pre/post install) -run "test_without_optional_scripts" { +# Test with only install and start scripts (no pre/post install) +run "test_without_optional_pre_post_scripts" { command = plan variables { @@ -134,21 +144,31 @@ run "test_without_optional_scripts" { error_message = "Post-install script should not be created when post_install_script is null" } - # Verify required scripts are still created + # Verify install and start scripts are still created assert { - condition = coder_script.install_script.agent_id == "test-agent-id" + condition = length(coder_script.install_script) == 1 error_message = "Install script should be created" } assert { - condition = coder_script.start_script.agent_id == "test-agent-id" + condition = coder_script.install_script[0].agent_id == "test-agent-id" + error_message = "Install script agent ID should match input" + } + + assert { + condition = length(coder_script.start_script) == 1 error_message = "Start script should be created" } - # Verify outputs assert { - condition = output.pre_install_script_name == "test-agent-pre_install_script" - error_message = "Pre-install script name output should be generated even when script is not created" + condition = coder_script.start_script[0].agent_id == "test-agent-id" + error_message = "Start script agent ID should match input" + } + + # Verify outputs are null for unprovided scripts + assert { + condition = output.pre_install_script_name == null + error_message = "Pre-install script name output should be null when script is not provided" } assert { @@ -157,8 +177,8 @@ run "test_without_optional_scripts" { } assert { - condition = output.post_install_script_name == "test-agent-post_install_script" - error_message = "Post-install script name output should be generated even when script is not created" + condition = output.post_install_script_name == null + error_message = "Post-install script name output should be null when script is not provided" } assert { @@ -167,6 +187,128 @@ run "test_without_optional_scripts" { } } +# Test with no scripts provided (all optional) +run "test_no_scripts" { + command = plan + + variables { + agent_id = "test-agent-id" + agent_name = "test-agent" + module_dir_name = ".test-module" + } + + # Verify no scripts are created + assert { + condition = length(coder_script.pre_install_script) == 0 + error_message = "Pre-install script should not be created when not provided" + } + + assert { + condition = length(coder_script.install_script) == 0 + error_message = "Install script should not be created when not provided" + } + + assert { + condition = length(coder_script.post_install_script) == 0 + error_message = "Post-install script should not be created when not provided" + } + + assert { + condition = length(coder_script.start_script) == 0 + error_message = "Start script should not be created when not provided" + } + + # Verify all outputs are null + assert { + condition = output.pre_install_script_name == null + error_message = "Pre-install script name output should be null" + } + + assert { + condition = output.install_script_name == null + error_message = "Install script name output should be null" + } + + assert { + condition = output.post_install_script_name == null + error_message = "Post-install script name output should be null" + } + + assert { + condition = output.start_script_name == null + error_message = "Start script name output should be null" + } +} + +# Test with only start_script (no install) +run "test_start_only" { + command = plan + + variables { + agent_id = "test-agent-id" + agent_name = "test-agent" + module_dir_name = ".test-module" + start_script = "echo 'start'" + } + + assert { + condition = length(coder_script.install_script) == 0 + error_message = "Install script should not be created when not provided" + } + + assert { + condition = length(coder_script.start_script) == 1 + error_message = "Start script should be created when provided" + } + + assert { + condition = coder_script.start_script[0].agent_id == "test-agent-id" + error_message = "Start script agent ID should match input" + } + + assert { + condition = output.install_script_name == null + error_message = "Install script name output should be null" + } + + assert { + condition = output.start_script_name == "test-agent-start_script" + error_message = "Start script name output should be correctly formatted" + } +} + +# Test with only install_script (no start) +run "test_install_only" { + command = plan + + variables { + agent_id = "test-agent-id" + agent_name = "test-agent" + module_dir_name = ".test-module" + install_script = "echo 'install'" + } + + assert { + condition = length(coder_script.install_script) == 1 + error_message = "Install script should be created when provided" + } + + assert { + condition = length(coder_script.start_script) == 0 + error_message = "Start script should not be created when not provided" + } + + assert { + condition = output.install_script_name == "test-agent-install_script" + error_message = "Install script name output should be correctly formatted" + } + + assert { + condition = output.start_script_name == null + error_message = "Start script name output should be null" + } +} + # Test with mock data sources run "test_with_mock_data" { command = plan @@ -214,12 +356,12 @@ run "test_with_mock_data" { # Verify scripts are created with mocked data assert { - condition = coder_script.install_script.agent_id == "mock-agent" + condition = coder_script.install_script[0].agent_id == "mock-agent" error_message = "Install script should use the mocked agent ID" } assert { - condition = coder_script.start_script.agent_id == "mock-agent" + condition = coder_script.start_script[0].agent_id == "mock-agent" error_message = "Start script should use the mocked agent ID" } } @@ -239,19 +381,19 @@ run "test_script_naming" { # Verify script names are constructed correctly # The script should contain references to custom-name-* in the sync commands assert { - condition = can(regex("custom-name-install_script", coder_script.install_script.script)) + condition = can(regex("custom-name-install_script", coder_script.install_script[0].script)) error_message = "Install script should use custom agent_name in sync commands" } assert { - condition = can(regex("custom-name-start_script", coder_script.start_script.script)) + condition = can(regex("custom-name-start_script", coder_script.start_script[0].script)) error_message = "Start script should use custom agent_name in sync commands" } # Verify outputs use custom agent_name assert { - condition = output.pre_install_script_name == "custom-name-pre_install_script" - error_message = "Pre-install script name output should use custom agent_name" + condition = output.pre_install_script_name == null + error_message = "Pre-install script name output should be null when not provided" } assert { @@ -260,8 +402,8 @@ run "test_script_naming" { } assert { - condition = output.post_install_script_name == "custom-name-post_install_script" - error_message = "Post-install script name output should use custom agent_name" + condition = output.post_install_script_name == null + error_message = "Post-install script name output should be null when not provided" } assert { @@ -269,3 +411,59 @@ run "test_script_naming" { error_message = "Start script name output should use custom agent_name" } } + +# Test with post_install but no install (sync deps should fall back to pre_install) +run "test_post_install_without_install" { + command = plan + + variables { + agent_id = "test-agent-id" + agent_name = "test-agent" + module_dir_name = ".test-module" + pre_install_script = "echo 'pre-install'" + post_install_script = "echo 'post-install'" + start_script = "echo 'start'" + } + + assert { + condition = length(coder_script.pre_install_script) == 1 + error_message = "Pre-install script should be created" + } + + assert { + condition = length(coder_script.install_script) == 0 + error_message = "Install script should not be created" + } + + assert { + condition = length(coder_script.post_install_script) == 1 + error_message = "Post-install script should be created" + } + + assert { + condition = length(coder_script.start_script) == 1 + error_message = "Start script should be created" + } + + # post_install should sync-want pre_install (since install is absent) + assert { + condition = can(regex("sync want test-agent-post_install_script test-agent-pre_install_script", coder_script.post_install_script[0].script)) + error_message = "Post-install script should sync-want pre_install_script when install_script is absent" + } + + # start should sync-want post_install (since install is absent) + assert { + condition = can(regex("sync want test-agent-start_script test-agent-post_install_script", coder_script.start_script[0].script)) + error_message = "Start script should sync-want post_install_script when install_script is absent" + } + + assert { + condition = output.pre_install_script_name == "test-agent-pre_install_script" + error_message = "Pre-install script name output should be set" + } + + assert { + condition = output.install_script_name == null + error_message = "Install script name output should be null" + } +} From fadaee88985223dc6f279a41e226fe8b35545e22 Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Mon, 13 Apr 2026 17:19:00 +0000 Subject: [PATCH 02/12] fix(registry/coder/modules/coder-utils): add mkdir -p to all script blocks and update module_dir_path Every script block now ensures the module directory exists, since any script can be the first (and only) one to run. Updated module_dir_path to use the namespaced path $HOME/.coder-modules/coder/coder-utils/. --- registry/coder/modules/coder-utils/main.tf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index 8d9b868db..cb621262a 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -66,7 +66,7 @@ locals { post_install_script_name = "${var.agent_name}-post_install_script" start_script_name = "${var.agent_name}-start_script" - module_dir_path = "$HOME/${var.module_dir_name}" + module_dir_path = "$HOME/.coder-modules/coder/coder-utils/${var.module_dir_name}" pre_install_path = "${local.module_dir_path}/pre_install.sh" install_path = "${local.module_dir_path}/install.sh" @@ -154,6 +154,8 @@ resource "coder_script" "post_install_script" { set -o errexit set -o pipefail + mkdir -p ${local.module_dir_path} + trap 'coder exp sync complete ${local.post_install_script_name}' EXIT %{if local.post_install_sync_deps != null~} coder exp sync want ${local.post_install_script_name} ${local.post_install_sync_deps} @@ -177,6 +179,8 @@ resource "coder_script" "start_script" { set -o errexit set -o pipefail + mkdir -p ${local.module_dir_path} + trap 'coder exp sync complete ${local.start_script_name}' EXIT %{if local.start_sync_deps != null~} From 87291223e3f552e9d8c15212a8cd7ccbf0465001 Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Mon, 13 Apr 2026 17:23:46 +0000 Subject: [PATCH 03/12] fix(registry/coder/modules/coder-utils): return empty string instead of null for unused outputs --- registry/coder/modules/coder-utils/main.tf | 8 ++-- .../coder/modules/coder-utils/main.tftest.hcl | 46 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index cb621262a..5d4173907 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -197,20 +197,20 @@ resource "coder_script" "start_script" { output "pre_install_script_name" { description = "The name of the pre-install script for sync." - value = var.pre_install_script != null ? local.pre_install_script_name : null + value = var.pre_install_script != null ? local.pre_install_script_name : "" } output "install_script_name" { description = "The name of the install script for sync." - value = var.install_script != null ? local.install_script_name : null + value = var.install_script != null ? local.install_script_name : "" } output "post_install_script_name" { description = "The name of the post-install script for sync." - value = var.post_install_script != null ? local.post_install_script_name : null + value = var.post_install_script != null ? local.post_install_script_name : "" } output "start_script_name" { description = "The name of the start script for sync." - value = var.start_script != null ? local.start_script_name : null + value = var.start_script != null ? local.start_script_name : "" } \ No newline at end of file diff --git a/registry/coder/modules/coder-utils/main.tftest.hcl b/registry/coder/modules/coder-utils/main.tftest.hcl index 4432e4be3..f25ec4243 100644 --- a/registry/coder/modules/coder-utils/main.tftest.hcl +++ b/registry/coder/modules/coder-utils/main.tftest.hcl @@ -167,8 +167,8 @@ run "test_without_optional_pre_post_scripts" { # Verify outputs are null for unprovided scripts assert { - condition = output.pre_install_script_name == null - error_message = "Pre-install script name output should be null when script is not provided" + condition = output.pre_install_script_name == "" + error_message = "Pre-install script name output should be empty when script is not provided" } assert { @@ -177,8 +177,8 @@ run "test_without_optional_pre_post_scripts" { } assert { - condition = output.post_install_script_name == null - error_message = "Post-install script name output should be null when script is not provided" + condition = output.post_install_script_name == "" + error_message = "Post-install script name output should be empty when script is not provided" } assert { @@ -218,25 +218,25 @@ run "test_no_scripts" { error_message = "Start script should not be created when not provided" } - # Verify all outputs are null + # Verify all outputs are empty strings assert { - condition = output.pre_install_script_name == null - error_message = "Pre-install script name output should be null" + condition = output.pre_install_script_name == "" + error_message = "Pre-install script name output should be empty" } assert { - condition = output.install_script_name == null - error_message = "Install script name output should be null" + condition = output.install_script_name == "" + error_message = "Install script name output should be empty" } assert { - condition = output.post_install_script_name == null - error_message = "Post-install script name output should be null" + condition = output.post_install_script_name == "" + error_message = "Post-install script name output should be empty" } assert { - condition = output.start_script_name == null - error_message = "Start script name output should be null" + condition = output.start_script_name == "" + error_message = "Start script name output should be empty" } } @@ -267,8 +267,8 @@ run "test_start_only" { } assert { - condition = output.install_script_name == null - error_message = "Install script name output should be null" + condition = output.install_script_name == "" + error_message = "Install script name output should be empty" } assert { @@ -304,8 +304,8 @@ run "test_install_only" { } assert { - condition = output.start_script_name == null - error_message = "Start script name output should be null" + condition = output.start_script_name == "" + error_message = "Start script name output should be empty" } } @@ -392,8 +392,8 @@ run "test_script_naming" { # Verify outputs use custom agent_name assert { - condition = output.pre_install_script_name == null - error_message = "Pre-install script name output should be null when not provided" + condition = output.pre_install_script_name == "" + error_message = "Pre-install script name output should be empty when not provided" } assert { @@ -402,8 +402,8 @@ run "test_script_naming" { } assert { - condition = output.post_install_script_name == null - error_message = "Post-install script name output should be null when not provided" + condition = output.post_install_script_name == "" + error_message = "Post-install script name output should be empty when not provided" } assert { @@ -463,7 +463,7 @@ run "test_post_install_without_install" { } assert { - condition = output.install_script_name == null - error_message = "Install script name output should be null" + condition = output.install_script_name == "" + error_message = "Install script name output should be empty" } } From 9127a111e3c019f14a9760f631037077eeec0990 Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Mon, 13 Apr 2026 17:29:38 +0000 Subject: [PATCH 04/12] docs(registry/coder/modules/coder-utils): bump version to 1.1.0 --- registry/coder/modules/coder-utils/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/coder-utils/README.md b/registry/coder/modules/coder-utils/README.md index 25ae28544..976e00463 100644 --- a/registry/coder/modules/coder-utils/README.md +++ b/registry/coder/modules/coder-utils/README.md @@ -20,7 +20,7 @@ The Coder Utils module is a building block for modules that need to run multiple ```tf module "coder_utils" { source = "registry.coder.com/coder/coder-utils/coder" - version = "1.0.1" + version = "1.1.0" agent_id = coder_agent.main.id agent_name = "myagent" @@ -58,8 +58,8 @@ The module orchestrates scripts in the following order: 1. **Log File Creation** - Creates module directory and log files 2. **Pre-Install Script** (optional) - Runs before installation -3. **Install Script** - Main installation +3. **Install Script** (optional) - Main installation 4. **Post-Install Script** (optional) - Runs after installation -5. **Start Script** - Starts the application +5. **Start Script** (optional) - Starts the application Each script waits for its prerequisites to complete before running using `coder exp sync` dependency management. From f203a780e8f18f07f56d8d1ea365b8ae26e86a40 Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Mon, 13 Apr 2026 17:49:21 +0000 Subject: [PATCH 05/12] refactor(registry/coder/modules/coder-utils): make install_script required, keep others optional install_script is now mandatory (no default). pre_install_script, post_install_script, and start_script remain optional with default null. Since install is always present, sync deps simplify: post_install always waits for install, start always waits for install (plus post_install when present). Removed validation blocks and fallback chains that are no longer needed. Bumped required Terraform version to >= 1.9. --- .../coder/modules/coder-utils/main.test.ts | 1 + registry/coder/modules/coder-utils/main.tf | 34 +-- .../coder/modules/coder-utils/main.tftest.hcl | 206 ++++-------------- 3 files changed, 58 insertions(+), 183 deletions(-) diff --git a/registry/coder/modules/coder-utils/main.test.ts b/registry/coder/modules/coder-utils/main.test.ts index bb64b5c59..42456fa7d 100644 --- a/registry/coder/modules/coder-utils/main.test.ts +++ b/registry/coder/modules/coder-utils/main.test.ts @@ -8,5 +8,6 @@ describe("coder-utils", async () => { agent_id: "test-agent-id", agent_name: "test-agent", module_dir_name: ".test-module", + install_script: "echo 'install'", }); }); diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index 5d4173907..7d7d5c7bf 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.9" required_providers { coder = { @@ -29,7 +29,6 @@ variable "pre_install_script" { variable "install_script" { type = string description = "Script to install the agent used by AgentAPI." - default = null } variable "post_install_script" { @@ -57,7 +56,7 @@ variable "module_dir_name" { locals { encoded_pre_install_script = var.pre_install_script != null ? base64encode(var.pre_install_script) : "" - encoded_install_script = var.install_script != null ? base64encode(var.install_script) : "" + encoded_install_script = base64encode(var.install_script) encoded_post_install_script = var.post_install_script != null ? base64encode(var.post_install_script) : "" encoded_start_script = var.start_script != null ? base64encode(var.start_script) : "" @@ -78,23 +77,13 @@ locals { post_install_log_path = "${local.module_dir_path}/post_install.log" start_log_path = "${local.module_dir_path}/start.log" - # Sync dependency resolution: each stage waits for its closest predecessor. + # Sync dependency resolution: each stage waits for its predecessors. # Chain order: pre_install -> install -> post_install -> start - post_install_sync_deps = ( - var.install_script != null ? local.install_script_name : ( - var.pre_install_script != null ? local.pre_install_script_name : null - ) - ) - + # install_script is always present (required), so it anchors the chain. start_sync_deps = ( - var.post_install_script != null && var.install_script != null - ? "${local.install_script_name} ${local.post_install_script_name}" : ( - var.post_install_script != null ? local.post_install_script_name : ( - var.install_script != null ? local.install_script_name : ( - var.pre_install_script != null ? local.pre_install_script_name : null - ) - ) - ) + var.post_install_script != null + ? "${local.install_script_name} ${local.post_install_script_name}" + : local.install_script_name ) } @@ -121,7 +110,6 @@ resource "coder_script" "pre_install_script" { } resource "coder_script" "install_script" { - count = var.install_script != null ? 1 : 0 agent_id = var.agent_id display_name = "Install Script" run_on_start = true @@ -157,9 +145,7 @@ resource "coder_script" "post_install_script" { mkdir -p ${local.module_dir_path} trap 'coder exp sync complete ${local.post_install_script_name}' EXIT - %{if local.post_install_sync_deps != null~} - coder exp sync want ${local.post_install_script_name} ${local.post_install_sync_deps} - %{endif~} + coder exp sync want ${local.post_install_script_name} ${local.install_script_name} coder exp sync start ${local.post_install_script_name} echo -n '${local.encoded_post_install_script}' | base64 -d > ${local.post_install_path} @@ -183,9 +169,7 @@ resource "coder_script" "start_script" { trap 'coder exp sync complete ${local.start_script_name}' EXIT - %{if local.start_sync_deps != null~} coder exp sync want ${local.start_script_name} ${local.start_sync_deps} - %{endif~} coder exp sync start ${local.start_script_name} echo -n '${local.encoded_start_script}' | base64 -d > ${local.start_path} @@ -202,7 +186,7 @@ output "pre_install_script_name" { output "install_script_name" { description = "The name of the install script for sync." - value = var.install_script != null ? local.install_script_name : "" + value = local.install_script_name } output "post_install_script_name" { diff --git a/registry/coder/modules/coder-utils/main.tftest.hcl b/registry/coder/modules/coder-utils/main.tftest.hcl index f25ec4243..9968a3f1c 100644 --- a/registry/coder/modules/coder-utils/main.tftest.hcl +++ b/registry/coder/modules/coder-utils/main.tftest.hcl @@ -35,24 +35,19 @@ run "test_with_all_scripts" { error_message = "Pre-install script should run on start" } - # Verify install_script is created when provided + # Verify install_script is always created assert { - condition = length(coder_script.install_script) == 1 - error_message = "Install script should be created when install_script is provided" - } - - assert { - condition = coder_script.install_script[0].agent_id == "test-agent-id" + condition = coder_script.install_script.agent_id == "test-agent-id" error_message = "Install script agent ID should match input" } assert { - condition = coder_script.install_script[0].display_name == "Install Script" + condition = coder_script.install_script.display_name == "Install Script" error_message = "Install script should have correct display name" } assert { - condition = coder_script.install_script[0].run_on_start == true + condition = coder_script.install_script.run_on_start == true error_message = "Install script should run on start" } @@ -120,8 +115,8 @@ run "test_with_all_scripts" { } } -# Test with only install and start scripts (no pre/post install) -run "test_without_optional_pre_post_scripts" { +# Test with only install_script (minimum required input) +run "test_install_only" { command = plan variables { @@ -129,46 +124,34 @@ run "test_without_optional_pre_post_scripts" { agent_name = "test-agent" module_dir_name = ".test-module" install_script = "echo 'install'" - start_script = "echo 'start'" } - # Verify pre_install_script is NOT created when not provided + # Verify optional scripts are NOT created assert { condition = length(coder_script.pre_install_script) == 0 - error_message = "Pre-install script should not be created when pre_install_script is null" + error_message = "Pre-install script should not be created when not provided" } - # Verify post_install_script is NOT created when not provided assert { condition = length(coder_script.post_install_script) == 0 - error_message = "Post-install script should not be created when post_install_script is null" - } - - # Verify install and start scripts are still created - assert { - condition = length(coder_script.install_script) == 1 - error_message = "Install script should be created" - } - - assert { - condition = coder_script.install_script[0].agent_id == "test-agent-id" - error_message = "Install script agent ID should match input" + error_message = "Post-install script should not be created when not provided" } assert { - condition = length(coder_script.start_script) == 1 - error_message = "Start script should be created" + condition = length(coder_script.start_script) == 0 + error_message = "Start script should not be created when not provided" } + # Verify install_script is created assert { - condition = coder_script.start_script[0].agent_id == "test-agent-id" - error_message = "Start script agent ID should match input" + condition = coder_script.install_script.agent_id == "test-agent-id" + error_message = "Install script should be created" } - # Verify outputs are null for unprovided scripts + # Verify outputs assert { condition = output.pre_install_script_name == "" - error_message = "Pre-install script name output should be empty when script is not provided" + error_message = "Pre-install script name output should be empty" } assert { @@ -178,87 +161,45 @@ run "test_without_optional_pre_post_scripts" { assert { condition = output.post_install_script_name == "" - error_message = "Post-install script name output should be empty when script is not provided" + error_message = "Post-install script name output should be empty" } assert { - condition = output.start_script_name == "test-agent-start_script" - error_message = "Start script name output should be correctly formatted" + condition = output.start_script_name == "" + error_message = "Start script name output should be empty" } } -# Test with no scripts provided (all optional) -run "test_no_scripts" { +# Test with install and start scripts (no pre/post install) +run "test_install_and_start" { command = plan variables { agent_id = "test-agent-id" agent_name = "test-agent" module_dir_name = ".test-module" + install_script = "echo 'install'" + start_script = "echo 'start'" } - # Verify no scripts are created assert { condition = length(coder_script.pre_install_script) == 0 error_message = "Pre-install script should not be created when not provided" } - assert { - condition = length(coder_script.install_script) == 0 - error_message = "Install script should not be created when not provided" - } - assert { condition = length(coder_script.post_install_script) == 0 error_message = "Post-install script should not be created when not provided" } assert { - condition = length(coder_script.start_script) == 0 - error_message = "Start script should not be created when not provided" - } - - # Verify all outputs are empty strings - assert { - condition = output.pre_install_script_name == "" - error_message = "Pre-install script name output should be empty" - } - - assert { - condition = output.install_script_name == "" - error_message = "Install script name output should be empty" - } - - assert { - condition = output.post_install_script_name == "" - error_message = "Post-install script name output should be empty" - } - - assert { - condition = output.start_script_name == "" - error_message = "Start script name output should be empty" - } -} - -# Test with only start_script (no install) -run "test_start_only" { - command = plan - - variables { - agent_id = "test-agent-id" - agent_name = "test-agent" - module_dir_name = ".test-module" - start_script = "echo 'start'" - } - - assert { - condition = length(coder_script.install_script) == 0 - error_message = "Install script should not be created when not provided" + condition = coder_script.install_script.agent_id == "test-agent-id" + error_message = "Install script should be created" } assert { condition = length(coder_script.start_script) == 1 - error_message = "Start script should be created when provided" + error_message = "Start script should be created" } assert { @@ -266,46 +207,30 @@ run "test_start_only" { error_message = "Start script agent ID should match input" } + # start should sync-want install (no post_install) assert { - condition = output.install_script_name == "" - error_message = "Install script name output should be empty" + condition = can(regex("sync want test-agent-start_script test-agent-install_script", coder_script.start_script[0].script)) + error_message = "Start script should sync-want install_script" } assert { - condition = output.start_script_name == "test-agent-start_script" - error_message = "Start script name output should be correctly formatted" - } -} - -# Test with only install_script (no start) -run "test_install_only" { - command = plan - - variables { - agent_id = "test-agent-id" - agent_name = "test-agent" - module_dir_name = ".test-module" - install_script = "echo 'install'" - } - - assert { - condition = length(coder_script.install_script) == 1 - error_message = "Install script should be created when provided" + condition = output.pre_install_script_name == "" + error_message = "Pre-install script name output should be empty" } assert { - condition = length(coder_script.start_script) == 0 - error_message = "Start script should not be created when not provided" + condition = output.install_script_name == "test-agent-install_script" + error_message = "Install script name output should be correctly formatted" } assert { - condition = output.install_script_name == "test-agent-install_script" - error_message = "Install script name output should be correctly formatted" + condition = output.post_install_script_name == "" + error_message = "Post-install script name output should be empty" } assert { - condition = output.start_script_name == "" - error_message = "Start script name output should be empty" + condition = output.start_script_name == "test-agent-start_script" + error_message = "Start script name output should be correctly formatted" } } @@ -321,7 +246,6 @@ run "test_with_mock_data" { start_script = "echo 'start'" } - # Mock the data sources for testing override_data { target = data.coder_workspace.me values = { @@ -354,9 +278,8 @@ run "test_with_mock_data" { } } - # Verify scripts are created with mocked data assert { - condition = coder_script.install_script[0].agent_id == "mock-agent" + condition = coder_script.install_script.agent_id == "mock-agent" error_message = "Install script should use the mocked agent ID" } @@ -378,10 +301,8 @@ run "test_script_naming" { start_script = "echo 'start'" } - # Verify script names are constructed correctly - # The script should contain references to custom-name-* in the sync commands assert { - condition = can(regex("custom-name-install_script", coder_script.install_script[0].script)) + condition = can(regex("custom-name-install_script", coder_script.install_script.script)) error_message = "Install script should use custom agent_name in sync commands" } @@ -390,7 +311,6 @@ run "test_script_naming" { error_message = "Start script should use custom agent_name in sync commands" } - # Verify outputs use custom agent_name assert { condition = output.pre_install_script_name == "" error_message = "Pre-install script name output should be empty when not provided" @@ -412,58 +332,28 @@ run "test_script_naming" { } } -# Test with post_install but no install (sync deps should fall back to pre_install) -run "test_post_install_without_install" { +# Test start script sync deps with post_install present +run "test_start_syncs_with_post_install" { command = plan variables { agent_id = "test-agent-id" agent_name = "test-agent" module_dir_name = ".test-module" - pre_install_script = "echo 'pre-install'" + install_script = "echo 'install'" post_install_script = "echo 'post-install'" start_script = "echo 'start'" } + # start should sync-want both install and post_install assert { - condition = length(coder_script.pre_install_script) == 1 - error_message = "Pre-install script should be created" - } - - assert { - condition = length(coder_script.install_script) == 0 - error_message = "Install script should not be created" - } - - assert { - condition = length(coder_script.post_install_script) == 1 - error_message = "Post-install script should be created" - } - - assert { - condition = length(coder_script.start_script) == 1 - error_message = "Start script should be created" - } - - # post_install should sync-want pre_install (since install is absent) - assert { - condition = can(regex("sync want test-agent-post_install_script test-agent-pre_install_script", coder_script.post_install_script[0].script)) - error_message = "Post-install script should sync-want pre_install_script when install_script is absent" - } - - # start should sync-want post_install (since install is absent) - assert { - condition = can(regex("sync want test-agent-start_script test-agent-post_install_script", coder_script.start_script[0].script)) - error_message = "Start script should sync-want post_install_script when install_script is absent" - } - - assert { - condition = output.pre_install_script_name == "test-agent-pre_install_script" - error_message = "Pre-install script name output should be set" + condition = can(regex("sync want test-agent-start_script test-agent-install_script test-agent-post_install_script", coder_script.start_script[0].script)) + error_message = "Start script should sync-want both install_script and post_install_script" } + # post_install should sync-want install assert { - condition = output.install_script_name == "" - error_message = "Install script name output should be empty" + condition = can(regex("sync want test-agent-post_install_script test-agent-install_script", coder_script.post_install_script[0].script)) + error_message = "Post-install script should sync-want install_script" } } From 8a9ab447d12e108d27840027cc89ef14bfbfa39e Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Mon, 13 Apr 2026 17:55:58 +0000 Subject: [PATCH 06/12] refactor(registry/coder/modules/coder-utils): move install sync deps to locals --- registry/coder/modules/coder-utils/main.tf | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index 7d7d5c7bf..d89bd99cb 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -77,9 +77,8 @@ locals { post_install_log_path = "${local.module_dir_path}/post_install.log" start_log_path = "${local.module_dir_path}/start.log" - # Sync dependency resolution: each stage waits for its predecessors. - # Chain order: pre_install -> install -> post_install -> start - # install_script is always present (required), so it anchors the chain. + install_sync_deps = var.pre_install_script != null ? local.pre_install_script_name : null + start_sync_deps = ( var.post_install_script != null ? "${local.install_script_name} ${local.post_install_script_name}" @@ -121,8 +120,8 @@ resource "coder_script" "install_script" { mkdir -p ${local.module_dir_path} trap 'coder exp sync complete ${local.install_script_name}' EXIT - %{if var.pre_install_script != null~} - coder exp sync want ${local.install_script_name} ${local.pre_install_script_name} + %{if local.install_sync_deps != null~} + coder exp sync want ${local.install_script_name} ${local.install_sync_deps} %{endif~} coder exp sync start ${local.install_script_name} echo -n '${local.encoded_install_script}' | base64 -d > ${local.install_path} From 0d51427c131738544abe16c8075454c18a24d246 Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Mon, 13 Apr 2026 17:59:39 +0000 Subject: [PATCH 07/12] test(registry/coder/modules/coder-utils): add install sync deps test and update README Add test_install_syncs_with_pre_install to verify install waits for pre_install via install_sync_deps local. Add sync assertion to test_with_all_scripts. Update README execution order to reflect install_script is required. --- registry/coder/modules/coder-utils/README.md | 9 +++-- .../coder/modules/coder-utils/main.tftest.hcl | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/registry/coder/modules/coder-utils/README.md b/registry/coder/modules/coder-utils/README.md index 976e00463..073d00c13 100644 --- a/registry/coder/modules/coder-utils/README.md +++ b/registry/coder/modules/coder-utils/README.md @@ -56,10 +56,9 @@ module "coder_utils" { The module orchestrates scripts in the following order: -1. **Log File Creation** - Creates module directory and log files -2. **Pre-Install Script** (optional) - Runs before installation -3. **Install Script** (optional) - Main installation -4. **Post-Install Script** (optional) - Runs after installation -5. **Start Script** (optional) - Starts the application +1. **Pre-Install Script** (optional) - Runs before installation +2. **Install Script** (required) - Main installation +3. **Post-Install Script** (optional) - Runs after installation +4. **Start Script** (optional) - Starts the application Each script waits for its prerequisites to complete before running using `coder exp sync` dependency management. diff --git a/registry/coder/modules/coder-utils/main.tftest.hcl b/registry/coder/modules/coder-utils/main.tftest.hcl index 9968a3f1c..6c8ab70bd 100644 --- a/registry/coder/modules/coder-utils/main.tftest.hcl +++ b/registry/coder/modules/coder-utils/main.tftest.hcl @@ -51,6 +51,12 @@ run "test_with_all_scripts" { error_message = "Install script should run on start" } + # install should sync-want pre_install + assert { + condition = can(regex("sync want test-agent-install_script test-agent-pre_install_script", coder_script.install_script.script)) + error_message = "Install script should sync-want pre_install_script when pre_install is provided" + } + # Verify post_install_script is created when provided assert { condition = length(coder_script.post_install_script) == 1 @@ -332,6 +338,34 @@ run "test_script_naming" { } } +# Test install syncs with pre_install when provided +run "test_install_syncs_with_pre_install" { + command = plan + + variables { + agent_id = "test-agent-id" + agent_name = "test-agent" + module_dir_name = ".test-module" + pre_install_script = "echo 'pre-install'" + install_script = "echo 'install'" + } + + assert { + condition = length(coder_script.pre_install_script) == 1 + error_message = "Pre-install script should be created" + } + + assert { + condition = can(regex("sync want test-agent-install_script test-agent-pre_install_script", coder_script.install_script.script)) + error_message = "Install script should sync-want pre_install_script" + } + + assert { + condition = output.pre_install_script_name == "test-agent-pre_install_script" + error_message = "Pre-install script name output should be set" + } +} + # Test start script sync deps with post_install present run "test_start_syncs_with_post_install" { command = plan From e942c7cfb3b55c161d8974da144dc9c250d0849c Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Mon, 13 Apr 2026 18:01:17 +0000 Subject: [PATCH 08/12] fix(registry/coder/modules/coder-utils): remove redundant mkdir from post_install and start Both scripts sync-wait on install, which always creates the directory. --- registry/coder/modules/coder-utils/main.tf | 4 ---- 1 file changed, 4 deletions(-) diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index d89bd99cb..2072ae703 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -141,8 +141,6 @@ resource "coder_script" "post_install_script" { set -o errexit set -o pipefail - mkdir -p ${local.module_dir_path} - trap 'coder exp sync complete ${local.post_install_script_name}' EXIT coder exp sync want ${local.post_install_script_name} ${local.install_script_name} coder exp sync start ${local.post_install_script_name} @@ -164,8 +162,6 @@ resource "coder_script" "start_script" { set -o errexit set -o pipefail - mkdir -p ${local.module_dir_path} - trap 'coder exp sync complete ${local.start_script_name}' EXIT coder exp sync want ${local.start_script_name} ${local.start_sync_deps} From e0a467066a694c4bd03c63579b9043236be6955f Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Tue, 14 Apr 2026 15:07:48 +0530 Subject: [PATCH 09/12] refactor(coder/modules/coder-utils): rename module_dir_name to module_directory for clarity --- registry/coder/modules/coder-utils/main.tf | 26 +++++------ .../coder/modules/coder-utils/main.tftest.hcl | 44 +++++++++---------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index 2072ae703..6dba2b3a6 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -49,9 +49,9 @@ variable "agent_name" { } -variable "module_dir_name" { +variable "module_directory" { type = string - description = "The name of the module directory." + description = "The module's working directory for scripts and logs." } locals { @@ -65,17 +65,15 @@ locals { post_install_script_name = "${var.agent_name}-post_install_script" start_script_name = "${var.agent_name}-start_script" - module_dir_path = "$HOME/.coder-modules/coder/coder-utils/${var.module_dir_name}" + pre_install_path = "${var.module_directory}/pre_install.sh" + install_path = "${var.module_directory}/install.sh" + post_install_path = "${var.module_directory}/post_install.sh" + start_path = "${var.module_directory}/start.sh" - pre_install_path = "${local.module_dir_path}/pre_install.sh" - install_path = "${local.module_dir_path}/install.sh" - post_install_path = "${local.module_dir_path}/post_install.sh" - start_path = "${local.module_dir_path}/start.sh" - - pre_install_log_path = "${local.module_dir_path}/pre_install.log" - install_log_path = "${local.module_dir_path}/install.log" - post_install_log_path = "${local.module_dir_path}/post_install.log" - start_log_path = "${local.module_dir_path}/start.log" + pre_install_log_path = "${var.module_directory}/pre_install.log" + install_log_path = "${var.module_directory}/install.log" + post_install_log_path = "${var.module_directory}/post_install.log" + start_log_path = "${var.module_directory}/start.log" install_sync_deps = var.pre_install_script != null ? local.pre_install_script_name : null @@ -96,7 +94,7 @@ resource "coder_script" "pre_install_script" { set -o errexit set -o pipefail - mkdir -p ${local.module_dir_path} + mkdir -p ${var.module_directory} trap 'coder exp sync complete ${local.pre_install_script_name}' EXIT coder exp sync start ${local.pre_install_script_name} @@ -117,7 +115,7 @@ resource "coder_script" "install_script" { set -o errexit set -o pipefail - mkdir -p ${local.module_dir_path} + mkdir -p ${var.module_directory} trap 'coder exp sync complete ${local.install_script_name}' EXIT %{if local.install_sync_deps != null~} diff --git a/registry/coder/modules/coder-utils/main.tftest.hcl b/registry/coder/modules/coder-utils/main.tftest.hcl index 6c8ab70bd..cb5ad9d04 100644 --- a/registry/coder/modules/coder-utils/main.tftest.hcl +++ b/registry/coder/modules/coder-utils/main.tftest.hcl @@ -7,7 +7,7 @@ run "test_with_all_scripts" { variables { agent_id = "test-agent-id" agent_name = "test-agent" - module_dir_name = ".test-module" + module_directory = ".test-module" pre_install_script = "echo 'pre-install'" install_script = "echo 'install'" post_install_script = "echo 'post-install'" @@ -126,10 +126,10 @@ run "test_install_only" { command = plan variables { - agent_id = "test-agent-id" - agent_name = "test-agent" - module_dir_name = ".test-module" - install_script = "echo 'install'" + agent_id = "test-agent-id" + agent_name = "test-agent" + module_directory = ".test-module" + install_script = "echo 'install'" } # Verify optional scripts are NOT created @@ -181,11 +181,11 @@ run "test_install_and_start" { command = plan variables { - agent_id = "test-agent-id" - agent_name = "test-agent" - module_dir_name = ".test-module" - install_script = "echo 'install'" - start_script = "echo 'start'" + agent_id = "test-agent-id" + agent_name = "test-agent" + module_directory = ".test-module" + install_script = "echo 'install'" + start_script = "echo 'start'" } assert { @@ -245,11 +245,11 @@ run "test_with_mock_data" { command = plan variables { - agent_id = "mock-agent" - agent_name = "mock-agent" - module_dir_name = ".mock-module" - install_script = "echo 'install'" - start_script = "echo 'start'" + agent_id = "mock-agent" + agent_name = "mock-agent" + module_directory = ".mock-module" + install_script = "echo 'install'" + start_script = "echo 'start'" } override_data { @@ -300,11 +300,11 @@ run "test_script_naming" { command = plan variables { - agent_id = "test-agent" - agent_name = "custom-name" - module_dir_name = ".test-module" - install_script = "echo 'install'" - start_script = "echo 'start'" + agent_id = "test-agent" + agent_name = "custom-name" + module_directory = ".test-module" + install_script = "echo 'install'" + start_script = "echo 'start'" } assert { @@ -345,7 +345,7 @@ run "test_install_syncs_with_pre_install" { variables { agent_id = "test-agent-id" agent_name = "test-agent" - module_dir_name = ".test-module" + module_directory = ".test-module" pre_install_script = "echo 'pre-install'" install_script = "echo 'install'" } @@ -373,7 +373,7 @@ run "test_start_syncs_with_post_install" { variables { agent_id = "test-agent-id" agent_name = "test-agent" - module_dir_name = ".test-module" + module_directory = ".test-module" install_script = "echo 'install'" post_install_script = "echo 'post-install'" start_script = "echo 'start'" From 22966c56db1f7aec700547a7d938ca35638ac76b Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Tue, 14 Apr 2026 15:08:16 +0530 Subject: [PATCH 10/12] fix(terraform): update required_version to support Terraform 1.0 and above --- registry/coder/modules/coder-utils/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index 6dba2b3a6..447f35efb 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.9" + required_version = ">= 1.0" required_providers { coder = { From 8216a7177bcbc06bb0ef4818ec0077aecb771c8c Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Tue, 14 Apr 2026 15:18:44 +0530 Subject: [PATCH 11/12] chore: update test --- registry/coder/modules/coder-utils/main.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/coder-utils/main.test.ts b/registry/coder/modules/coder-utils/main.test.ts index 42456fa7d..a7e8e2e9f 100644 --- a/registry/coder/modules/coder-utils/main.test.ts +++ b/registry/coder/modules/coder-utils/main.test.ts @@ -7,7 +7,7 @@ describe("coder-utils", async () => { testRequiredVariables(import.meta.dir, { agent_id: "test-agent-id", agent_name: "test-agent", - module_dir_name: ".test-module", + module_directory: ".test-module", install_script: "echo 'install'", }); }); From 94f1d3ad66f3abf7426fc52e23f011cb0d71b376 Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Tue, 14 Apr 2026 10:43:59 +0000 Subject: [PATCH 12/12] refactor(registry/coder/modules/coder-utils): consolidate outputs into single script_names object Replace four individual outputs with a single script_names output containing pre_install, install, post_install, and start fields. --- registry/coder/modules/coder-utils/main.tf | 26 +++++--------- .../coder/modules/coder-utils/main.tftest.hcl | 34 +++++++++---------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index 447f35efb..20b383d14 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -172,22 +172,12 @@ resource "coder_script" "start_script" { EOT } -output "pre_install_script_name" { - description = "The name of the pre-install script for sync." - value = var.pre_install_script != null ? local.pre_install_script_name : "" -} - -output "install_script_name" { - description = "The name of the install script for sync." - value = local.install_script_name -} - -output "post_install_script_name" { - description = "The name of the post-install script for sync." - value = var.post_install_script != null ? local.post_install_script_name : "" -} - -output "start_script_name" { - description = "The name of the start script for sync." - value = var.start_script != null ? local.start_script_name : "" +output "script_names" { + description = "The names of the scripts for sync." + value = { + pre_install = var.pre_install_script != null ? local.pre_install_script_name : "" + install = local.install_script_name + post_install = var.post_install_script != null ? local.post_install_script_name : "" + start = var.start_script != null ? local.start_script_name : "" + } } \ No newline at end of file diff --git a/registry/coder/modules/coder-utils/main.tftest.hcl b/registry/coder/modules/coder-utils/main.tftest.hcl index cb5ad9d04..0e3aa9ebb 100644 --- a/registry/coder/modules/coder-utils/main.tftest.hcl +++ b/registry/coder/modules/coder-utils/main.tftest.hcl @@ -101,22 +101,22 @@ run "test_with_all_scripts" { # Verify outputs for script names assert { - condition = output.pre_install_script_name == "test-agent-pre_install_script" + condition = output.script_names.pre_install == "test-agent-pre_install_script" error_message = "Pre-install script name output should be correctly formatted" } assert { - condition = output.install_script_name == "test-agent-install_script" + condition = output.script_names.install == "test-agent-install_script" error_message = "Install script name output should be correctly formatted" } assert { - condition = output.post_install_script_name == "test-agent-post_install_script" + condition = output.script_names.post_install == "test-agent-post_install_script" error_message = "Post-install script name output should be correctly formatted" } assert { - condition = output.start_script_name == "test-agent-start_script" + condition = output.script_names.start == "test-agent-start_script" error_message = "Start script name output should be correctly formatted" } } @@ -156,22 +156,22 @@ run "test_install_only" { # Verify outputs assert { - condition = output.pre_install_script_name == "" + condition = output.script_names.pre_install == "" error_message = "Pre-install script name output should be empty" } assert { - condition = output.install_script_name == "test-agent-install_script" + condition = output.script_names.install == "test-agent-install_script" error_message = "Install script name output should be correctly formatted" } assert { - condition = output.post_install_script_name == "" + condition = output.script_names.post_install == "" error_message = "Post-install script name output should be empty" } assert { - condition = output.start_script_name == "" + condition = output.script_names.start == "" error_message = "Start script name output should be empty" } } @@ -220,22 +220,22 @@ run "test_install_and_start" { } assert { - condition = output.pre_install_script_name == "" + condition = output.script_names.pre_install == "" error_message = "Pre-install script name output should be empty" } assert { - condition = output.install_script_name == "test-agent-install_script" + condition = output.script_names.install == "test-agent-install_script" error_message = "Install script name output should be correctly formatted" } assert { - condition = output.post_install_script_name == "" + condition = output.script_names.post_install == "" error_message = "Post-install script name output should be empty" } assert { - condition = output.start_script_name == "test-agent-start_script" + condition = output.script_names.start == "test-agent-start_script" error_message = "Start script name output should be correctly formatted" } } @@ -318,22 +318,22 @@ run "test_script_naming" { } assert { - condition = output.pre_install_script_name == "" + condition = output.script_names.pre_install == "" error_message = "Pre-install script name output should be empty when not provided" } assert { - condition = output.install_script_name == "custom-name-install_script" + condition = output.script_names.install == "custom-name-install_script" error_message = "Install script name output should use custom agent_name" } assert { - condition = output.post_install_script_name == "" + condition = output.script_names.post_install == "" error_message = "Post-install script name output should be empty when not provided" } assert { - condition = output.start_script_name == "custom-name-start_script" + condition = output.script_names.start == "custom-name-start_script" error_message = "Start script name output should use custom agent_name" } } @@ -361,7 +361,7 @@ run "test_install_syncs_with_pre_install" { } assert { - condition = output.pre_install_script_name == "test-agent-pre_install_script" + condition = output.script_names.pre_install == "test-agent-pre_install_script" error_message = "Pre-install script name output should be set" } }