Compare commits

..

2 Commits

Author SHA1 Message Date
Atif Ali 3b64d99fb1 refactor(registry/coder/modules/coder-utils)!: derive names from module_directory (#874)
## Summary

Derives `coder-utils` script names from `module_directory` instead of a
separate `agent_name` input. The `module_directory` already encodes both
the namespace and the module name, so carrying both is redundant and
error-prone. Callers like `claude-code` no longer need to pass
`agent_name`.

Scripts this module materializes lose the `${agent_name}-utils-` prefix
because `module_directory` already namespaces them per-caller.

We will address multiple instances of coder-utils per caller in a future
iteration if needed.

## Versioning Note

Previous tags (`v1.0.0` through `v1.3.0`) have been deleted because no
published module ever consumed them — the module was effectively
unreleased. This PR ships the first real public version as **`v0.0.1`**,
treating it as a fresh start rather than a breaking bump from a version
that was never in production use.

## Changes

- Remove `agent_name` variable.
- Derive `caller_name = "${namespace}-${module_name}"` from
`module_directory`.
- Validate `module_directory` matches
`$HOME/.coder-modules/<namespace>/<module-name>`.
- Rename script files on disk from `${agent_name}-utils-<phase>.sh` to
plain `<phase>.sh`.
- Add a TS test for the `module_directory` validation.
- Ship as `v0.0.1` (first published version; all prior tags removed).

## Breaking Changes

| Before | After |
|---|---|
| `agent_name = "myagent"` | removed (derived from `module_directory`) |
| `module_directory = ".my-module"` | `module_directory =
"$HOME/.coder-modules/<ns>/<name>"` (validated) |
| Script files `${agent_name}-utils-install.sh` | `install.sh` |
| Script sync names `${agent_name}-install_script` |
`${namespace}-${module_name}-install_script` |

No callers were depending on the old format (prior tags were
unpublished).

## Validation

- `terraform fmt -recursive` clean
- `terraform validate` clean
- `terraform test` → 17/17 pass
- `bun test registry/coder/modules/coder-utils` → 5/5 pass
- `prettier --check` clean

## Consumer

coder/registry#861 (`claude-code`) consumes this and is currently pinned
to the commit SHA until this merges and ships as `v0.0.1`.

> 🤖 This PR was created with the help of Coder Agents, and needs a human
review. 🧑‍💻
2026-04-24 17:16:10 +05:00
Atif Ali 22e574926e feat(coder-utils): nest scripts under module_directory/scripts (#871)
## Summary

Move script files from the flat `${module_directory}` to a `scripts/`
subdirectory, and prefix each script's filename with
`${agent_name}-utils-` so multiple `coder-utils` instances can safely
share a `module_directory`. Mirrors the layout #870 established for
`logs/` and aligns with the Module Data Layout standard in `AGENTS.md`
(#869).

## Changes

- Compute `local.scripts_directory = "${var.module_directory}/scripts"`
and use it for every `*.sh` path.
- Script filenames are now
`${agent_name}-utils-{pre_install,install,post_install,start}.sh` so two
`coder-utils` instances don't collide on disk.
- Pre-install and install `coder_script`s `mkdir -p` the `scripts/`
sub-path before writing their `.sh`; post-install and start sync-depend
on install, so the directory already exists by the time they run.
- Update the `module_directory` description to call out the nested
`scripts/` and `logs/` paths.
- Add `test_scripts_nested_under_module_directory` asserting the new
paths (including the `${agent_name}-utils-` prefix) and the `mkdir -p`
in each script.
- README: add a "Script file locations" section documenting the new
layout.
- Bump module version to `v1.3.0`.

## Breaking Changes

Consumers reading `${module_directory}/install.sh` (and friends)
directly must look under
`${module_directory}/scripts/${agent_name}-utils-install.sh` instead. No
in-repo consumers exist today.

## Validation

- `terraform fmt -recursive` clean
- `terraform validate` clean
- `terraform test` → 16/16 pass (includes the new
`test_scripts_nested_under_module_directory`)
- `bun test main.test.ts` → 5/5 pass
- `prettier --check` clean

> 🤖 This PR was created with the help of Coder Agents, and needs a human
review. 🧑‍💻
2026-04-23 21:46:59 +05:00
4 changed files with 145 additions and 156 deletions
+15 -10
View File
@@ -13,18 +13,13 @@ tags: [internal, library]
The Coder Utils module is a building block for modules that need to run multiple scripts in a specific order. It uses `coder exp sync` for dependency management and is designed for orchestrating pre-install, install, post-install, and start scripts.
> [!NOTE]
>
> - The `agent_name` should be the same as that of the agentapi module's `agent_name` if used together.
```tf
module "coder_utils" {
source = "registry.coder.com/coder/coder-utils/coder"
version = "1.2.0"
version = "0.0.1"
agent_id = coder_agent.main.id
agent_name = "myagent"
module_directory = ".my-module"
module_directory = "$HOME/.coder-modules/coder/claude-code"
pre_install_script = <<-EOT
#!/bin/bash
@@ -70,11 +65,10 @@ 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 = "0.0.1"
agent_id = coder_agent.main.id
agent_name = "myagent"
module_directory = ".my-module"
module_directory = "$HOME/.coder-modules/coder/claude-code"
install_script = "echo installing"
display_name_prefix = "Claude Code" # yields "Claude Code: Install Script", etc.
@@ -94,3 +88,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.
@@ -1,13 +1,38 @@
import { describe } from "bun:test";
import { runTerraformInit, testRequiredVariables } from "~test";
import { describe, expect, it } from "bun:test";
import {
runTerraformApply,
runTerraformInit,
testRequiredVariables,
} from "~test";
describe("coder-utils", async () => {
await runTerraformInit(import.meta.dir);
testRequiredVariables(import.meta.dir, {
agent_id: "test-agent-id",
agent_name: "test-agent",
module_directory: ".test-module",
module_directory: "$HOME/.coder-modules/test/example",
install_script: "echo 'install'",
});
it("rejects invalid module_directory", async () => {
try {
await runTerraformApply(import.meta.dir, {
agent_id: "test-agent-id",
module_directory: "$HOME/.coder-modules/test",
install_script: "echo 'install'",
});
} catch (ex) {
if (!(ex instanceof Error)) {
throw new Error("Unknown error generated");
}
expect(ex.message).toContain("module_directory must match the pattern");
expect(ex.message).toContain(
"'$HOME/.coder-modules/<namespace>/<module-name>'",
);
return;
}
throw new Error("module_directory validation should have failed");
});
});
+23 -20
View File
@@ -43,15 +43,14 @@ variable "start_script" {
default = null
}
variable "agent_name" {
type = string
description = "The name of the agent. This is used to construct unique script names for the experiment sync."
}
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 calling module's working directory. Must follow the pattern '$HOME/.coder-modules/<namespace>/<module-name>'."
validation {
condition = can(regex("^\\$HOME/\\.coder-modules/[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+$", var.module_directory))
error_message = "module_directory must match the pattern '$HOME/.coder-modules/<namespace>/<module-name>' (e.g. '$HOME/.coder-modules/coder/claude-code')."
}
}
variable "display_name_prefix" {
@@ -67,29 +66,31 @@ variable "icon" {
}
locals {
path_parts = split("/", var.module_directory)
caller_name = "${local.path_parts[length(local.path_parts) - 2]}-${local.path_parts[length(local.path_parts) - 1]}"
encoded_pre_install_script = var.pre_install_script != null ? base64encode(var.pre_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) : ""
pre_install_script_name = "${var.agent_name}-pre_install_script"
install_script_name = "${var.agent_name}-install_script"
post_install_script_name = "${var.agent_name}-post_install_script"
start_script_name = "${var.agent_name}-start_script"
pre_install_script_name = "${local.caller_name}-pre_install_script"
install_script_name = "${local.caller_name}-install_script"
post_install_script_name = "${local.caller_name}-post_install_script"
start_script_name = "${local.caller_name}-start_script"
utils_script_path = "${var.module_directory}/${var.agent_name}-utils"
pre_install_path = "${local.utils_script_path}/pre_install.sh"
install_path = "${local.utils_script_path}/install.sh"
post_install_path = "${local.utils_script_path}/post_install.sh"
start_path = "${local.utils_script_path}/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
@@ -113,7 +114,8 @@ resource "coder_script" "pre_install_script" {
set -o errexit
set -o pipefail
mkdir -p ${local.utils_script_path}
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
@@ -136,7 +138,8 @@ resource "coder_script" "install_script" {
set -o errexit
set -o pipefail
mkdir -p ${local.utils_script_path}
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
@@ -6,8 +6,7 @@ run "test_with_all_scripts" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
pre_install_script = "echo 'pre-install'"
install_script = "echo 'install'"
post_install_script = "echo 'post-install'"
@@ -53,7 +52,7 @@ run "test_with_all_scripts" {
# 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))
condition = can(regex("sync want test-example-install_script test-example-pre_install_script", coder_script.install_script.script))
error_message = "Install script should sync-want pre_install_script when pre_install is provided"
}
@@ -100,14 +99,27 @@ run "test_with_all_scripts" {
}
}
run "test_invalid_module_directory" {
command = plan
variables {
agent_id = "test-agent-id"
module_directory = "$HOME/.coder-modules/test"
install_script = "echo 'install'"
}
expect_failures = [
var.module_directory,
]
}
# Test with only install_script (minimum required input)
run "test_install_only" {
command = plan
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
install_script = "echo 'install'"
}
@@ -140,8 +152,7 @@ run "test_install_and_start" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
install_script = "echo 'install'"
start_script = "echo 'start'"
}
@@ -173,7 +184,7 @@ run "test_install_and_start" {
# start should sync-want install (no post_install)
assert {
condition = can(regex("sync want test-agent-start_script test-agent-install_script", coder_script.start_script[0].script))
condition = can(regex("sync want test-example-start_script test-example-install_script", coder_script.start_script[0].script))
error_message = "Start script should sync-want install_script"
}
}
@@ -184,8 +195,7 @@ run "test_with_mock_data" {
variables {
agent_id = "mock-agent"
agent_name = "mock-agent"
module_directory = ".mock-module"
module_directory = "$HOME/.coder-modules/test/mock"
install_script = "echo 'install'"
start_script = "echo 'start'"
}
@@ -233,26 +243,25 @@ run "test_with_mock_data" {
}
}
# Test script naming with custom agent_name
run "test_script_naming" {
# Test sync naming derived from module_directory
run "test_script_naming_from_module_directory" {
command = plan
variables {
agent_id = "test-agent"
agent_name = "custom-name"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/custom/name"
install_script = "echo 'install'"
start_script = "echo 'start'"
}
assert {
condition = can(regex("custom-name-install_script", coder_script.install_script.script))
error_message = "Install script should use custom agent_name in sync commands"
error_message = "Install script should derive sync names from module_directory"
}
assert {
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"
error_message = "Start script should derive sync names from module_directory"
}
}
@@ -262,8 +271,7 @@ run "test_install_syncs_with_pre_install" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
pre_install_script = "echo 'pre-install'"
install_script = "echo 'install'"
}
@@ -274,7 +282,7 @@ run "test_install_syncs_with_pre_install" {
}
assert {
condition = can(regex("sync want test-agent-install_script test-agent-pre_install_script", coder_script.install_script.script))
condition = can(regex("sync want test-example-install_script test-example-pre_install_script", coder_script.install_script.script))
error_message = "Install script should sync-want pre_install_script"
}
}
@@ -285,8 +293,7 @@ run "test_start_syncs_with_post_install" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
install_script = "echo 'install'"
post_install_script = "echo 'post-install'"
start_script = "echo 'start'"
@@ -294,13 +301,13 @@ run "test_start_syncs_with_post_install" {
# start should sync-want both install and post_install
assert {
condition = can(regex("sync want test-agent-start_script test-agent-install_script test-agent-post_install_script", coder_script.start_script[0].script))
condition = can(regex("sync want test-example-start_script test-example-install_script test-example-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 = can(regex("sync want test-agent-post_install_script test-agent-install_script", coder_script.post_install_script[0].script))
condition = can(regex("sync want test-example-post_install_script test-example-install_script", coder_script.post_install_script[0].script))
error_message = "Post-install script should sync-want install_script"
}
}
@@ -311,8 +318,7 @@ run "test_display_name_prefix_applied" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
display_name_prefix = "Claude Code"
pre_install_script = "echo 'pre-install'"
install_script = "echo 'install'"
@@ -347,8 +353,7 @@ run "test_icon_applied" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
icon = "/icon/claude.svg"
pre_install_script = "echo 'pre-install'"
install_script = "echo 'install'"
@@ -383,8 +388,7 @@ run "test_optional_scripts_absent_by_default" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
install_script = "echo install"
}
@@ -410,8 +414,7 @@ run "test_scripts_output_with_all" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
pre_install_script = "echo pre"
install_script = "echo install"
post_install_script = "echo post"
@@ -424,22 +427,22 @@ run "test_scripts_output_with_all" {
}
assert {
condition = output.scripts[0] == "test-agent-pre_install_script"
condition = output.scripts[0] == "test-example-pre_install_script"
error_message = "scripts[0] must be the pre-install name"
}
assert {
condition = output.scripts[1] == "test-agent-install_script"
condition = output.scripts[1] == "test-example-install_script"
error_message = "scripts[1] must be the install name"
}
assert {
condition = output.scripts[2] == "test-agent-post_install_script"
condition = output.scripts[2] == "test-example-post_install_script"
error_message = "scripts[2] must be the post-install name"
}
assert {
condition = output.scripts[3] == "test-agent-start_script"
condition = output.scripts[3] == "test-example-start_script"
error_message = "scripts[3] must be the start name"
}
}
@@ -449,8 +452,7 @@ run "test_scripts_output_with_install_only" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
install_script = "echo install"
}
@@ -460,7 +462,7 @@ run "test_scripts_output_with_install_only" {
}
assert {
condition = output.scripts[0] == "test-agent-install_script"
condition = output.scripts[0] == "test-example-install_script"
error_message = "scripts[0] must be the install name"
}
}
@@ -470,8 +472,7 @@ run "test_scripts_output_with_install_and_post" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
install_script = "echo install"
post_install_script = "echo post"
}
@@ -482,12 +483,12 @@ run "test_scripts_output_with_install_and_post" {
}
assert {
condition = output.scripts[0] == "test-agent-install_script"
condition = output.scripts[0] == "test-example-install_script"
error_message = "scripts[0] must be the install name"
}
assert {
condition = output.scripts[1] == "test-agent-post_install_script"
condition = output.scripts[1] == "test-example-post_install_script"
error_message = "scripts[1] must be the post-install name"
}
}
@@ -501,8 +502,7 @@ run "test_scripts_tee_stdout_and_log_file" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
pre_install_script = "echo pre"
install_script = "echo install"
post_install_script = "echo post"
@@ -510,22 +510,22 @@ run "test_scripts_tee_stdout_and_log_file" {
}
assert {
condition = can(regex("pre_install.sh 2>&1 \\| tee .*logs/pre_install.log", coder_script.pre_install_script[0].script))
condition = can(regex("pre_install\\.sh 2>&1 \\| tee .*logs/pre_install\\.log", coder_script.pre_install_script[0].script))
error_message = "pre_install wrapper must tee combined output to the logs/ subdirectory"
}
assert {
condition = can(regex("install.sh 2>&1 \\| tee .*logs/install.log", coder_script.install_script.script))
condition = can(regex("install\\.sh 2>&1 \\| tee .*logs/install\\.log", coder_script.install_script.script))
error_message = "install wrapper must tee combined output to the logs/ subdirectory"
}
assert {
condition = can(regex("post_install.sh 2>&1 \\| tee .*logs/post_install.log", coder_script.post_install_script[0].script))
condition = can(regex("post_install\\.sh 2>&1 \\| tee .*logs/post_install\\.log", coder_script.post_install_script[0].script))
error_message = "post_install wrapper must tee combined output to the logs/ subdirectory"
}
assert {
condition = can(regex("start.sh 2>&1 \\| tee .*logs/start.log", coder_script.start_script[0].script))
condition = can(regex("start\\.sh 2>&1 \\| tee .*logs/start\\.log", coder_script.start_script[0].script))
error_message = "start wrapper must tee combined output to the logs/ subdirectory"
}
}
@@ -537,8 +537,7 @@ run "test_logs_nested_under_module_directory" {
variables {
agent_id = "test-agent-id"
agent_name = "test-agent"
module_directory = ".test-module"
module_directory = "$HOME/.coder-modules/test/example"
pre_install_script = "echo pre"
install_script = "echo install"
post_install_script = "echo post"
@@ -546,22 +545,22 @@ run "test_logs_nested_under_module_directory" {
}
assert {
condition = can(regex("tee .test-module/logs/pre_install.log", coder_script.pre_install_script[0].script))
condition = strcontains(coder_script.pre_install_script[0].script, "tee $HOME/.coder-modules/test/example/logs/pre_install.log")
error_message = "pre_install log must land under module_directory/logs"
}
assert {
condition = can(regex("tee .test-module/logs/install.log", coder_script.install_script.script))
condition = strcontains(coder_script.install_script.script, "tee $HOME/.coder-modules/test/example/logs/install.log")
error_message = "install log must land under module_directory/logs"
}
assert {
condition = can(regex("tee .test-module/logs/post_install.log", coder_script.post_install_script[0].script))
condition = strcontains(coder_script.post_install_script[0].script, "tee $HOME/.coder-modules/test/example/logs/post_install.log")
error_message = "post_install log must land under module_directory/logs"
}
assert {
condition = can(regex("tee .test-module/logs/start.log", coder_script.start_script[0].script))
condition = strcontains(coder_script.start_script[0].script, "tee $HOME/.coder-modules/test/example/logs/start.log")
error_message = "start log must land under module_directory/logs"
}
@@ -569,104 +568,61 @@ run "test_logs_nested_under_module_directory" {
# and start sync-depend on install so the directory already exists by
# the time they run.
assert {
condition = can(regex("mkdir -p .test-module/logs", coder_script.pre_install_script[0].script))
condition = strcontains(coder_script.pre_install_script[0].script, "mkdir -p $HOME/.coder-modules/test/example/logs")
error_message = "pre_install script must mkdir -p the logs/ sub-path"
}
assert {
condition = can(regex("mkdir -p .test-module/logs", coder_script.install_script.script))
condition = strcontains(coder_script.install_script.script, "mkdir -p $HOME/.coder-modules/test/example/logs")
error_message = "install script must mkdir -p the logs/ sub-path"
}
}
# Scripts are written to ${module_directory}/${agent_name}-utils/ so the
# wrapper must mkdir that directory and all script paths must nest under it.
run "test_scripts_nested_under_utils_directory" {
# 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"
module_directory = "$HOME/.coder-modules/test/example"
pre_install_script = "echo pre"
install_script = "echo install"
post_install_script = "echo post"
start_script = "echo start"
}
# pre_install and install create the utils directory.
assert {
condition = can(regex("mkdir -p .test-module/test-agent-utils", coder_script.pre_install_script[0].script))
error_message = "pre_install script must mkdir -p the utils directory"
condition = strcontains(coder_script.pre_install_script[0].script, "> $HOME/.coder-modules/test/example/scripts/pre_install.sh")
error_message = "pre_install script must be written under module_directory/scripts"
}
assert {
condition = can(regex("mkdir -p .test-module/test-agent-utils", coder_script.install_script.script))
error_message = "install script must mkdir -p the utils directory"
}
# Every script writes its file under the utils directory.
assert {
condition = can(regex("base64 -d > .test-module/test-agent-utils/pre_install.sh", coder_script.pre_install_script[0].script))
error_message = "pre_install script must write to the utils directory"
condition = strcontains(coder_script.install_script.script, "> $HOME/.coder-modules/test/example/scripts/install.sh")
error_message = "install script must be written under module_directory/scripts"
}
assert {
condition = can(regex("base64 -d > .test-module/test-agent-utils/install.sh", coder_script.install_script.script))
error_message = "install script must write to the utils directory"
condition = strcontains(coder_script.post_install_script[0].script, "> $HOME/.coder-modules/test/example/scripts/post_install.sh")
error_message = "post_install script must be written under module_directory/scripts"
}
assert {
condition = can(regex("base64 -d > .test-module/test-agent-utils/post_install.sh", coder_script.post_install_script[0].script))
error_message = "post_install script must write to the utils directory"
condition = strcontains(coder_script.start_script[0].script, "> $HOME/.coder-modules/test/example/scripts/start.sh")
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 = strcontains(coder_script.pre_install_script[0].script, "mkdir -p $HOME/.coder-modules/test/example/scripts")
error_message = "pre_install script must mkdir -p the scripts/ sub-path"
}
assert {
condition = can(regex("base64 -d > .test-module/test-agent-utils/start.sh", coder_script.start_script[0].script))
error_message = "start script must write to the utils directory"
}
# Every script executes from the utils directory.
assert {
condition = can(regex(".test-module/test-agent-utils/pre_install.sh 2>&1", coder_script.pre_install_script[0].script))
error_message = "pre_install script must execute from the utils directory"
}
assert {
condition = can(regex(".test-module/test-agent-utils/install.sh 2>&1", coder_script.install_script.script))
error_message = "install script must execute from the utils directory"
}
assert {
condition = can(regex(".test-module/test-agent-utils/post_install.sh 2>&1", coder_script.post_install_script[0].script))
error_message = "post_install script must execute from the utils directory"
}
assert {
condition = can(regex(".test-module/test-agent-utils/start.sh 2>&1", coder_script.start_script[0].script))
error_message = "start script must execute from the utils directory"
}
}
# The utils directory name includes agent_name so multiple modules sharing
# the same module_directory do not collide.
run "test_utils_directory_uses_agent_name" {
command = plan
variables {
agent_id = "test-agent-id"
agent_name = "custom-name"
module_directory = ".test-module"
install_script = "echo install"
}
assert {
condition = can(regex("mkdir -p .test-module/custom-name-utils", coder_script.install_script.script))
error_message = "utils directory must include agent_name"
}
assert {
condition = can(regex("base64 -d > .test-module/custom-name-utils/install.sh", coder_script.install_script.script))
error_message = "install script must be written under agent-name-specific utils directory"
condition = strcontains(coder_script.install_script.script, "mkdir -p $HOME/.coder-modules/test/example/scripts")
error_message = "install script must mkdir -p the scripts/ sub-path"
}
}