From 50d2aff1daf3a48ee5fe58f21a918154acfb5d64 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Thu, 23 Apr 2026 06:56:53 +0000 Subject: [PATCH 1/3] feat(coder-utils): nest scripts under module_directory/scripts --- registry/coder/modules/coder-utils/README.md | 11 ++++ registry/coder/modules/coder-utils/main.tf | 15 +++--- .../coder/modules/coder-utils/main.tftest.hcl | 50 +++++++++++++++++++ 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/registry/coder/modules/coder-utils/README.md b/registry/coder/modules/coder-utils/README.md index 813d943b3..acf868e7b 100644 --- a/registry/coder/modules/coder-utils/README.md +++ b/registry/coder/modules/coder-utils/README.md @@ -94,3 +94,14 @@ The module writes each script's stdout+stderr to `${module_directory}/logs/`: - `start.log` Each `coder_script` `mkdir -p`s this subdirectory before its `tee` runs, so the first script to execute creates it. + +## Script file locations + +The module materializes each script to `${module_directory}/scripts/` before running it: + +- `pre_install.sh` +- `install.sh` +- `post_install.sh` +- `start.sh` + +The pre-install and install `coder_script`s `mkdir -p` this subdirectory; post-install and start sync-depend on install, so the directory already exists by the time they run. diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index e9abff572..332792909 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -51,7 +51,7 @@ variable "agent_name" { variable "module_directory" { type = string - description = "The module's working directory for the install/pre/post/start scripts this module writes. Logs land under a `logs/` subdirectory of this path." + description = "The module's working directory. Scripts this module writes land under `scripts/` and their logs under `logs/` in this path." } variable "display_name_prefix" { @@ -77,17 +77,18 @@ locals { post_install_script_name = "${var.agent_name}-post_install_script" start_script_name = "${var.agent_name}-start_script" - 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.scripts_directory}/pre_install.sh" + install_path = "${local.scripts_directory}/install.sh" + post_install_path = "${local.scripts_directory}/post_install.sh" + start_path = "${local.scripts_directory}/start.sh" pre_install_log_path = "${local.log_directory}/pre_install.log" install_log_path = "${local.log_directory}/install.log" post_install_log_path = "${local.log_directory}/post_install.log" start_log_path = "${local.log_directory}/start.log" - log_directory = "${var.module_directory}/logs" + scripts_directory = "${var.module_directory}/scripts" + log_directory = "${var.module_directory}/logs" install_sync_deps = var.pre_install_script != null ? local.pre_install_script_name : null @@ -112,6 +113,7 @@ resource "coder_script" "pre_install_script" { set -o pipefail mkdir -p ${var.module_directory} + mkdir -p ${local.scripts_directory} mkdir -p ${local.log_directory} trap 'coder exp sync complete ${local.pre_install_script_name}' EXIT @@ -135,6 +137,7 @@ resource "coder_script" "install_script" { set -o pipefail mkdir -p ${var.module_directory} + mkdir -p ${local.scripts_directory} mkdir -p ${local.log_directory} trap 'coder exp sync complete ${local.install_script_name}' EXIT diff --git a/registry/coder/modules/coder-utils/main.tftest.hcl b/registry/coder/modules/coder-utils/main.tftest.hcl index a89585de1..d46adb302 100644 --- a/registry/coder/modules/coder-utils/main.tftest.hcl +++ b/registry/coder/modules/coder-utils/main.tftest.hcl @@ -578,3 +578,53 @@ run "test_logs_nested_under_module_directory" { error_message = "install script must mkdir -p the logs/ sub-path" } } + +# Scripts unconditionally land under ${module_directory}/scripts/. Each +# script that materializes its own `.sh` file mkdirs that path first; the +# first script to execute creates it for the rest. +run "test_scripts_nested_under_module_directory" { + command = plan + + variables { + agent_id = "test-agent-id" + agent_name = "test-agent" + module_directory = ".test-module" + pre_install_script = "echo pre" + install_script = "echo install" + post_install_script = "echo post" + start_script = "echo start" + } + + assert { + condition = can(regex("> .test-module/scripts/pre_install.sh", coder_script.pre_install_script[0].script)) + error_message = "pre_install script must be written under module_directory/scripts" + } + + assert { + condition = can(regex("> .test-module/scripts/install.sh", coder_script.install_script.script)) + error_message = "install script must be written under module_directory/scripts" + } + + assert { + condition = can(regex("> .test-module/scripts/post_install.sh", coder_script.post_install_script[0].script)) + error_message = "post_install script must be written under module_directory/scripts" + } + + assert { + condition = can(regex("> .test-module/scripts/start.sh", coder_script.start_script[0].script)) + error_message = "start script must be written under module_directory/scripts" + } + + # Only pre_install and install mkdir the scripts/ sub-path. post_install + # and start sync-depend on install so the directory already exists by + # the time they run. + assert { + condition = can(regex("mkdir -p .test-module/scripts", coder_script.pre_install_script[0].script)) + error_message = "pre_install script must mkdir -p the scripts/ sub-path" + } + + assert { + condition = can(regex("mkdir -p .test-module/scripts", coder_script.install_script.script)) + error_message = "install script must mkdir -p the scripts/ sub-path" + } +} From 39961abd1c4545a52c9e9bccf418e49f1640470d Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Thu, 23 Apr 2026 06:57:19 +0000 Subject: [PATCH 2/3] chore(coder-utils): bump version to 1.3.0 --- registry/coder/modules/coder-utils/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/coder/modules/coder-utils/README.md b/registry/coder/modules/coder-utils/README.md index acf868e7b..34584c463 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.2.0" + version = "1.3.0" agent_id = coder_agent.main.id agent_name = "myagent" @@ -70,7 +70,7 @@ By default each `coder_script` renders in the Coder UI as plain "Install Script" ```tf module "coder_utils" { source = "registry.coder.com/coder/coder-utils/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id agent_name = "myagent" From 8d391c42e4ad7e3a24fe437c54870aaabe663162 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Thu, 23 Apr 2026 16:29:13 +0000 Subject: [PATCH 3/3] refactor(coder-utils): prefix script filenames with agent_name --- registry/coder/modules/coder-utils/README.md | 10 +++++----- registry/coder/modules/coder-utils/main.tf | 8 ++++---- registry/coder/modules/coder-utils/main.tftest.hcl | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/registry/coder/modules/coder-utils/README.md b/registry/coder/modules/coder-utils/README.md index 34584c463..86425e4d1 100644 --- a/registry/coder/modules/coder-utils/README.md +++ b/registry/coder/modules/coder-utils/README.md @@ -99,9 +99,9 @@ Each `coder_script` `mkdir -p`s this subdirectory before its `tee` runs, so the The module materializes each script to `${module_directory}/scripts/` before running it: -- `pre_install.sh` -- `install.sh` -- `post_install.sh` -- `start.sh` +- `${agent_name}-utils-pre_install.sh` +- `${agent_name}-utils-install.sh` +- `${agent_name}-utils-post_install.sh` +- `${agent_name}-utils-start.sh` -The pre-install and install `coder_script`s `mkdir -p` this subdirectory; post-install and start sync-depend on install, so the directory already exists by the time they run. +The `${agent_name}-utils-` prefix namespaces files per-agent so multiple `coder-utils` instances can safely share a `module_directory`. The pre-install and install `coder_script`s `mkdir -p` this subdirectory; post-install and start sync-depend on install, so the directory already exists by the time they run. diff --git a/registry/coder/modules/coder-utils/main.tf b/registry/coder/modules/coder-utils/main.tf index 332792909..df1e175cc 100644 --- a/registry/coder/modules/coder-utils/main.tf +++ b/registry/coder/modules/coder-utils/main.tf @@ -77,10 +77,10 @@ locals { post_install_script_name = "${var.agent_name}-post_install_script" start_script_name = "${var.agent_name}-start_script" - pre_install_path = "${local.scripts_directory}/pre_install.sh" - install_path = "${local.scripts_directory}/install.sh" - post_install_path = "${local.scripts_directory}/post_install.sh" - start_path = "${local.scripts_directory}/start.sh" + pre_install_path = "${local.scripts_directory}/${var.agent_name}-utils-pre_install.sh" + install_path = "${local.scripts_directory}/${var.agent_name}-utils-install.sh" + post_install_path = "${local.scripts_directory}/${var.agent_name}-utils-post_install.sh" + start_path = "${local.scripts_directory}/${var.agent_name}-utils-start.sh" pre_install_log_path = "${local.log_directory}/pre_install.log" install_log_path = "${local.log_directory}/install.log" diff --git a/registry/coder/modules/coder-utils/main.tftest.hcl b/registry/coder/modules/coder-utils/main.tftest.hcl index d46adb302..1ba9bc5dd 100644 --- a/registry/coder/modules/coder-utils/main.tftest.hcl +++ b/registry/coder/modules/coder-utils/main.tftest.hcl @@ -596,22 +596,22 @@ run "test_scripts_nested_under_module_directory" { } assert { - condition = can(regex("> .test-module/scripts/pre_install.sh", coder_script.pre_install_script[0].script)) + condition = can(regex("> .test-module/scripts/test-agent-utils-pre_install.sh", coder_script.pre_install_script[0].script)) error_message = "pre_install script must be written under module_directory/scripts" } assert { - condition = can(regex("> .test-module/scripts/install.sh", coder_script.install_script.script)) + condition = can(regex("> .test-module/scripts/test-agent-utils-install.sh", coder_script.install_script.script)) error_message = "install script must be written under module_directory/scripts" } assert { - condition = can(regex("> .test-module/scripts/post_install.sh", coder_script.post_install_script[0].script)) + condition = can(regex("> .test-module/scripts/test-agent-utils-post_install.sh", coder_script.post_install_script[0].script)) error_message = "post_install script must be written under module_directory/scripts" } assert { - condition = can(regex("> .test-module/scripts/start.sh", coder_script.start_script[0].script)) + condition = can(regex("> .test-module/scripts/test-agent-utils-start.sh", coder_script.start_script[0].script)) error_message = "start script must be written under module_directory/scripts" }