diff --git a/registry/thezoker/modules/nodejs/README.md b/registry/thezoker/modules/nodejs/README.md index 873aac06..1c3e4eac 100644 --- a/registry/thezoker/modules/nodejs/README.md +++ b/registry/thezoker/modules/nodejs/README.md @@ -55,6 +55,28 @@ module "nodejs" { } ``` +## Cross-Module Dependency Ordering + +This module uses `coder exp sync` to coordinate execution ordering with other modules. It exposes the following outputs for use with `coder exp sync want`: + +- `install_script_name` — the sync name for the main Node.js installation script +- `pre_install_script_name` — the sync name for the pre-install script +- `post_install_script_name` — the sync name for the post-install script + +For example, to ensure another module waits for Node.js to be fully installed: + +```tf +module "nodejs" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/thezoker/nodejs/coder" + version = "1.1.0" + agent_id = coder_agent.example.id +} + +# In another module's coder_script, wait for Node.js installation: +# coder exp sync want my-script ${module.nodejs[0].install_script_name} +``` + ## Full example A example with all available options: diff --git a/registry/thezoker/modules/nodejs/main.tf b/registry/thezoker/modules/nodejs/main.tf index 0f420b38..c11b8996 100644 --- a/registry/thezoker/modules/nodejs/main.tf +++ b/registry/thezoker/modules/nodejs/main.tf @@ -50,17 +50,113 @@ variable "post_install_script" { default = null } +locals { + encoded_pre_install_script = var.pre_install_script != null ? base64encode(var.pre_install_script) : "" + encoded_post_install_script = var.post_install_script != null ? base64encode(var.post_install_script) : "" + + install_script = templatefile("${path.module}/run.sh", { + NVM_VERSION = var.nvm_version, + INSTALL_PREFIX = var.nvm_install_prefix, + NODE_VERSIONS = join(",", var.node_versions), + DEFAULT = var.default_node_version, + }) + encoded_install_script = base64encode(local.install_script) + + pre_install_script_name = "nodejs-pre_install_script" + install_script_name = "nodejs-install_script" + post_install_script_name = "nodejs-post_install_script" + + module_dir_path = "$HOME/.nodejs-module" + + pre_install_path = "${local.module_dir_path}/pre_install.sh" + pre_install_log_path = "${local.module_dir_path}/pre_install.log" + install_path = "${local.module_dir_path}/install.sh" + install_log_path = "${local.module_dir_path}/install.log" + post_install_path = "${local.module_dir_path}/post_install.sh" + post_install_log_path = "${local.module_dir_path}/post_install.log" +} + +resource "coder_script" "pre_install_script" { + count = var.pre_install_script == null ? 0 : 1 + agent_id = var.agent_id + display_name = "Node.js: Pre-Install" + run_on_start = true + script = <<-EOT + #!/bin/bash + set -o errexit + set -o pipefail + + mkdir -p ${local.module_dir_path} + + trap 'coder exp sync complete ${local.pre_install_script_name}' EXIT + coder exp sync start ${local.pre_install_script_name} + + echo -n '${local.encoded_pre_install_script}' | base64 -d > ${local.pre_install_path} + chmod +x ${local.pre_install_path} + + ${local.pre_install_path} 2>&1 | tee ${local.pre_install_log_path} + EOT +} + resource "coder_script" "nodejs" { agent_id = var.agent_id - display_name = "Node.js:" - script = templatefile("${path.module}/run.sh", { - NVM_VERSION : var.nvm_version, - INSTALL_PREFIX : var.nvm_install_prefix, - NODE_VERSIONS : join(",", var.node_versions), - DEFAULT : var.default_node_version, - PRE_INSTALL_SCRIPT : var.pre_install_script != null ? var.pre_install_script : "", - POST_INSTALL_SCRIPT : var.post_install_script != null ? var.post_install_script : "", - }) + display_name = "Node.js: Install" + script = <<-EOT + #!/bin/bash + set -o errexit + set -o pipefail + + 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} + %{endif~} + coder exp sync start ${local.install_script_name} + + echo -n '${local.encoded_install_script}' | base64 -d > ${local.install_path} + chmod +x ${local.install_path} + + ${local.install_path} 2>&1 | tee ${local.install_log_path} + EOT run_on_start = true start_blocks_login = true } + +resource "coder_script" "post_install_script" { + count = var.post_install_script != null ? 1 : 0 + agent_id = var.agent_id + display_name = "Node.js: Post-Install" + run_on_start = true + script = <<-EOT + #!/bin/bash + 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} + + echo -n '${local.encoded_post_install_script}' | base64 -d > ${local.post_install_path} + chmod +x ${local.post_install_path} + + ${local.post_install_path} 2>&1 | tee ${local.post_install_log_path} + EOT +} + +output "pre_install_script_name" { + description = "The name of the pre-install script for coder exp sync coordination." + value = local.pre_install_script_name +} + +output "install_script_name" { + description = "The name of the install script for coder exp sync coordination." + value = local.install_script_name +} + +output "post_install_script_name" { + description = "The name of the post-install script for coder exp sync coordination." + value = local.post_install_script_name +} diff --git a/registry/thezoker/modules/nodejs/nodejs.tftest.hcl b/registry/thezoker/modules/nodejs/nodejs.tftest.hcl index e8024e56..1897eed0 100644 --- a/registry/thezoker/modules/nodejs/nodejs.tftest.hcl +++ b/registry/thezoker/modules/nodejs/nodejs.tftest.hcl @@ -29,6 +29,11 @@ run "test_nodejs_basic" { condition = var.post_install_script == null error_message = "post_install_script should default to null" } + + assert { + condition = output.install_script_name == "nodejs-install_script" + error_message = "install_script_name output should be set" + } } run "test_with_scripts" { @@ -49,6 +54,16 @@ run "test_with_scripts" { condition = var.post_install_script == "echo 'Post-install script'" error_message = "Post-install script should be set correctly" } + + assert { + condition = output.pre_install_script_name == "nodejs-pre_install_script" + error_message = "pre_install_script_name output should be set" + } + + assert { + condition = output.post_install_script_name == "nodejs-post_install_script" + error_message = "post_install_script_name output should be set" + } } run "test_custom_options" { diff --git a/registry/thezoker/modules/nodejs/run.sh b/registry/thezoker/modules/nodejs/run.sh index 53e4b6ca..31044eb5 100644 --- a/registry/thezoker/modules/nodejs/run.sh +++ b/registry/thezoker/modules/nodejs/run.sh @@ -4,17 +4,10 @@ NVM_VERSION='${NVM_VERSION}' NODE_VERSIONS='${NODE_VERSIONS}' INSTALL_PREFIX='${INSTALL_PREFIX}' DEFAULT='${DEFAULT}' -PRE_INSTALL_SCRIPT='${PRE_INSTALL_SCRIPT}' -POST_INSTALL_SCRIPT='${POST_INSTALL_SCRIPT}' BOLD='\033[0;1m' CODE='\033[36;40;1m' RESET='\033[0m' -if [ -n "$${PRE_INSTALL_SCRIPT}" ]; then - printf "$${BOLD}Running pre-install script...$${RESET}\n" - eval "$${PRE_INSTALL_SCRIPT}" -fi - printf "$${BOLD}Installing nvm!$${RESET}\n" export NVM_DIR="$HOME/$${INSTALL_PREFIX}/nvm" @@ -58,8 +51,3 @@ if [ -n "$${DEFAULT}" ]; then printf "🛠️ Setting default node version $${CODE}$DEFAULT$${RESET}...\n" output=$(nvm alias default $DEFAULT 2>&1) fi - -if [ -n "$${POST_INSTALL_SCRIPT}" ]; then - printf "$${BOLD}Running post-install script...$${RESET}\n" - eval "$${POST_INSTALL_SCRIPT}" -fi