From 39b408f2dad314810fdc78a4559610477cb86668 Mon Sep 17 00:00:00 2001 From: Dmytro Makovey Date: Thu, 20 Aug 2026 11:45:10 -0700 Subject: [PATCH 1/6] Add Mise module --- registry/droopy4096/.images/avatar.png | 0 registry/droopy4096/README.md | 11 ++ .../droopy4096/modules/mise-install/README.md | 101 ++++++++++++++++++ .../droopy4096/modules/mise-install/main.tf | 98 +++++++++++++++++ .../mise-install/mise-install.tftest.hcl | 73 +++++++++++++ .../mise-install/scripts/install.sh.tftpl | 34 ++++++ .../scripts/post_install.sh.tftpl | 42 ++++++++ 7 files changed, 359 insertions(+) create mode 100644 registry/droopy4096/.images/avatar.png create mode 100644 registry/droopy4096/README.md create mode 100644 registry/droopy4096/modules/mise-install/README.md create mode 100644 registry/droopy4096/modules/mise-install/main.tf create mode 100644 registry/droopy4096/modules/mise-install/mise-install.tftest.hcl create mode 100644 registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl create mode 100644 registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl diff --git a/registry/droopy4096/.images/avatar.png b/registry/droopy4096/.images/avatar.png new file mode 100644 index 000000000..e69de29bb diff --git a/registry/droopy4096/README.md b/registry/droopy4096/README.md new file mode 100644 index 000000000..6ee97a1ec --- /dev/null +++ b/registry/droopy4096/README.md @@ -0,0 +1,11 @@ +--- +display_name: "D Makovey" +bio: "Lifelong tinkerer" +avatar: "./.images/avatar.png" +github: "droopy4096" +status: "community" +--- + +# D Makovey + +Lifelong tinkerer and breaker of things diff --git a/registry/droopy4096/modules/mise-install/README.md b/registry/droopy4096/modules/mise-install/README.md new file mode 100644 index 000000000..5076fde8b --- /dev/null +++ b/registry/droopy4096/modules/mise-install/README.md @@ -0,0 +1,101 @@ +--- +display_name: mise install +description: Install mise and run `mise install` inside a cloned repository. +icon: ../../../../.icons/code.svg +verified: false +tags: [helper, mise, devtools] +--- + +# mise install + +Installs [`mise`](https://mise.jdx.dev/getting-started.html) on the workspace and runs `mise install` inside a repository directory so language runtimes and tools declared in `.mise.toml` / `.tool-versions` are provisioned before the user starts working. + +Designed to compose with the [`coder/git-clone`](https://registry.coder.com/modules/coder/git-clone) module: pass `module.git_clone.repo_dir` as `repo_dir`. + +## Usage + +```tf +module "git_clone" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/git-clone/coder" + version = "2.0.3" + agent_id = coder_agent.main.id + url = "https://github.com/example/repo" +} + +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir +} +``` + +The install script downloads `mise` from `https://mise.run` into `install_dir` (defaults to `$HOME/.local/bin`) and appends `mise activate` to `~/.bashrc` and `~/.zshrc`. The post-install script then runs `mise trust` (optional) and `mise install` inside `repo_dir`. + +## Examples + +### Disable shell activation and `mise trust` + +Use this when the workspace image already activates `mise` globally, or the repository does not use `.mise.toml`: + +```tf +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir + activate_shells = [] + mise_trust = false +} +``` + +### Custom install directory + +```tf +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir + install_dir = "$HOME/.mise/bin" +} +``` + +## Execution order + +This module uses [`coder/coder-utils`](https://registry.coder.com/modules/coder/coder-utils) to run two ordered scripts via `coder exp sync`: + +1. **Install Script** — installs `mise` and (optionally) configures shell activation. +2. **Post-Install Script** — waits for the clone to complete, then runs `mise trust` and `mise install` in `repo_dir`. + +Coder starts every `coder_script` on an agent in parallel, so this module's post-install script cannot use `coder exp sync` to wait on `git-clone` (git-clone does not participate in `coder exp sync`). Instead, the post-install script polls for `${repo_dir}/.git` and only runs `mise install` once the clone has finished. The bound is controlled by `wait_seconds` (default `300`). If the timeout expires, the script logs a message and exits `0` without running `mise install`. + +### Custom wait timeout + +```tf +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir + wait_seconds = 900 # wait up to 15 minutes for large clones +} +``` + +## Troubleshooting + +Scripts and logs are written under a per-module root: + +- Scripts: `$HOME/.coder-modules/droopy4096/mise-install/scripts/{install.sh,post_install.sh}` +- Logs: `$HOME/.coder-modules/droopy4096/mise-install/logs/{install.log,post_install.log}` + +If `mise install` fails, inspect `post_install.log` for the exact `mise` output. Common causes: + +- Missing `.mise.toml` / `.tool-versions` in `repo_dir`. +- Untrusted config (rerun with `mise_trust = true`). +- Network egress restrictions on downloading plugins from `mise.jdx.dev`. diff --git a/registry/droopy4096/modules/mise-install/main.tf b/registry/droopy4096/modules/mise-install/main.tf new file mode 100644 index 000000000..54130830f --- /dev/null +++ b/registry/droopy4096/modules/mise-install/main.tf @@ -0,0 +1,98 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.13" + } + } +} + +variable "agent_id" { + description = "The ID of a Coder agent." + type = string +} + +variable "repo_dir" { + description = "Absolute path to the repository where `mise install` should run. Typically wired to `module.git-clone.repo_dir`." + type = string +} + +variable "mise_trust" { + description = "Whether to run `mise trust` on the repository before `mise install`. Required for projects that ship a `.mise.toml`." + type = bool + default = true +} + +variable "activate_shells" { + description = "Shell rc files to append `mise activate` to. Pass an empty list to skip activation." + type = list(string) + default = ["bash", "zsh"] + + validation { + condition = alltrue([for s in var.activate_shells : contains(["bash", "zsh"], s)]) + error_message = "activate_shells entries must be one of: bash, zsh." + } +} + +variable "install_dir" { + description = "Directory to install the `mise` binary into. Passed to the mise installer as `MISE_INSTALL_PATH`'s parent." + type = string + default = "$HOME/.local/bin" +} + +variable "wait_seconds" { + description = "Maximum seconds to wait for `repo_dir/.git` to appear (i.e. for the git-clone module to finish) before skipping `mise install`." + type = number + default = 300 + + validation { + condition = var.wait_seconds >= 0 + error_message = "wait_seconds must be non-negative." + } +} + +variable "icon" { + description = "Icon shown in the Coder UI for the coder_script resources this module creates." + type = string + default = "/icon/code.svg" +} + +locals { + module_directory = "$HOME/.coder-modules/droopy4096/mise-install" + + install_script = templatefile("${path.module}/scripts/install.sh.tftpl", { + ARG_INSTALL_DIR = var.install_dir + ARG_ACTIVATE_SHELLS = join(" ", var.activate_shells) + }) + + post_install_script = templatefile("${path.module}/scripts/post_install.sh.tftpl", { + ARG_REPO_DIR = var.repo_dir + ARG_MISE_TRUST = tostring(var.mise_trust) + ARG_INSTALL_DIR = var.install_dir + ARG_WAIT_SECONDS = tostring(var.wait_seconds) + }) +} + +module "coder_utils" { + source = "registry.coder.com/coder/coder-utils/coder" + version = "0.0.1" + + agent_id = var.agent_id + module_directory = local.module_directory + display_name_prefix = "mise" + icon = var.icon + install_script = local.install_script + post_install_script = local.post_install_script +} + +output "repo_dir" { + description = "The repository directory where `mise install` was run." + value = var.repo_dir +} + +output "scripts" { + description = "Ordered list of `coder exp sync` names produced by this module, in run order." + value = module.coder_utils.scripts +} diff --git a/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl b/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl new file mode 100644 index 000000000..da4d0df6d --- /dev/null +++ b/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl @@ -0,0 +1,73 @@ +mock_provider "coder" {} + +run "plan_with_required_vars" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + } +} + +run "invalid_activate_shell_fails" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + activate_shells = ["fish"] + } + + expect_failures = [var.activate_shells] +} + +run "empty_activate_shells_allowed" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + activate_shells = [] + } +} + +run "negative_wait_seconds_fails" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + wait_seconds = -1 + } + + expect_failures = [var.wait_seconds] +} + +run "custom_wait_seconds_allowed" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + wait_seconds = 900 + } +} + +run "apply_emits_scripts_output" { + command = apply + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + } + + assert { + condition = length(output.scripts) == 2 + error_message = "Expected scripts output to contain install + post_install entries." + } + + assert { + condition = output.repo_dir == "/home/coder/repo" + error_message = "Expected repo_dir output to echo the input." + } +} diff --git a/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl b/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl new file mode 100644 index 000000000..ca4fedf32 --- /dev/null +++ b/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +ARG_INSTALL_DIR='${ARG_INSTALL_DIR}' +ARG_ACTIVATE_SHELLS='${ARG_ACTIVATE_SHELLS}' + +# Expand leading ~ and $HOME in the install directory path (safer than `eval`). +ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\~/$${HOME}}" +ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\$HOME/$${HOME}}" + +mkdir -p "$${ARG_INSTALL_DIR}" + +if ! command -v mise >/dev/null 2>&1 && [ ! -x "$${ARG_INSTALL_DIR}/mise" ]; then + echo "Installing mise into $${ARG_INSTALL_DIR}..." + MISE_INSTALL_PATH="$${ARG_INSTALL_DIR}/mise" curl -fsSL https://mise.run | sh +else + echo "mise already present, skipping download." +fi + +export PATH="$${ARG_INSTALL_DIR}:$${PATH}" +mise --version + +if [ -n "$${ARG_ACTIVATE_SHELLS}" ]; then + for shell in $${ARG_ACTIVATE_SHELLS}; do + rc="$${HOME}/.$${shell}rc" + touch "$${rc}" + if ! grep -qF "mise activate $${shell}" "$${rc}"; then + echo "Appending mise activation to $${rc}" + printf '\n# Added by droopy4096/mise-install\neval "$(%s/mise activate %s)"\n' "$${ARG_INSTALL_DIR}" "$${shell}" >> "$${rc}" + else + echo "mise activation already present in $${rc}" + fi + done +fi diff --git a/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl b/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl new file mode 100644 index 000000000..74c637802 --- /dev/null +++ b/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -euo pipefail + +ARG_REPO_DIR='${ARG_REPO_DIR}' +ARG_MISE_TRUST='${ARG_MISE_TRUST}' +ARG_INSTALL_DIR='${ARG_INSTALL_DIR}' +ARG_WAIT_SECONDS='${ARG_WAIT_SECONDS}' + +# Expand leading ~ and $HOME in caller-supplied paths (safer than `eval`). +ARG_REPO_DIR="$${ARG_REPO_DIR/#\~/$${HOME}}" +ARG_REPO_DIR="$${ARG_REPO_DIR/#\$HOME/$${HOME}}" +ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\~/$${HOME}}" +ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\$HOME/$${HOME}}" + +export PATH="$${ARG_INSTALL_DIR}:$${PATH}" + +if ! command -v mise >/dev/null 2>&1; then + echo "mise is not on PATH; the install script must run first." + exit 1 +fi + +# Wait for the clone to finish. Checking for ".git" (not just the directory) +# guards against racing a bare mkdir -p performed before cloning begins. +deadline=$(( $(date +%s) + ARG_WAIT_SECONDS )) +while [ ! -d "$${ARG_REPO_DIR}/.git" ]; do + if [ "$(date +%s)" -ge "$${deadline}" ]; then + echo "Timed out after $${ARG_WAIT_SECONDS}s waiting for $${ARG_REPO_DIR}/.git; skipping 'mise install'." + exit 0 + fi + echo "Waiting for $${ARG_REPO_DIR}/.git to appear..." + sleep 2 +done + +cd "$${ARG_REPO_DIR}" + +if [ "$${ARG_MISE_TRUST}" = "true" ]; then + echo "Running 'mise trust' in $${ARG_REPO_DIR}..." + mise trust || echo "Warning: 'mise trust' failed; continuing." +fi + +echo "Running 'mise install' in $${ARG_REPO_DIR}..." +mise install From 44f48bc53088b6a1ea6d400a233487e2dbb49f01 Mon Sep 17 00:00:00 2001 From: Dmytro Makovey Date: Thu, 20 Aug 2026 11:55:59 -0700 Subject: [PATCH 2/6] mise-install: place primary tf block inside h1 section The README validator (cmd/readmevalidation/codermodules.go) requires exactly one 'tf' code block with a 'version' field between the h1 heading and the first h2. Move the primary usage snippet directly under '# mise install' and demote the git-clone composition example to '### Compose with coder/git-clone' under '## Examples'. --- .../droopy4096/modules/mise-install/README.md | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/registry/droopy4096/modules/mise-install/README.md b/registry/droopy4096/modules/mise-install/README.md index 5076fde8b..a85316b42 100644 --- a/registry/droopy4096/modules/mise-install/README.md +++ b/registry/droopy4096/modules/mise-install/README.md @@ -12,7 +12,21 @@ Installs [`mise`](https://mise.jdx.dev/getting-started.html) on the workspace an Designed to compose with the [`coder/git-clone`](https://registry.coder.com/modules/coder/git-clone) module: pass `module.git_clone.repo_dir` as `repo_dir`. -## Usage +```tf +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir +} +``` + +The install script downloads `mise` from `https://mise.run` into `install_dir` (defaults to `$HOME/.local/bin`) and appends `mise activate` to `~/.bashrc` and `~/.zshrc`. The post-install script then runs `mise trust` (optional) and `mise install` inside `repo_dir`. + +## Examples + +### Compose with `coder/git-clone` ```tf module "git_clone" { @@ -32,10 +46,6 @@ module "mise_install" { } ``` -The install script downloads `mise` from `https://mise.run` into `install_dir` (defaults to `$HOME/.local/bin`) and appends `mise activate` to `~/.bashrc` and `~/.zshrc`. The post-install script then runs `mise trust` (optional) and `mise install` inside `repo_dir`. - -## Examples - ### Disable shell activation and `mise trust` Use this when the workspace image already activates `mise` globally, or the repository does not use `.mise.toml`: From 1e68e09065b24cd27768089d34bff350a2b9f75b Mon Sep 17 00:00:00 2001 From: Dmytro Makovey Date: Thu, 20 Aug 2026 11:45:10 -0700 Subject: [PATCH 3/6] Add Mise module --- registry/droopy4096/.images/avatar.png | 0 registry/droopy4096/README.md | 11 ++ .../droopy4096/modules/mise-install/README.md | 101 ++++++++++++++++++ .../droopy4096/modules/mise-install/main.tf | 98 +++++++++++++++++ .../mise-install/mise-install.tftest.hcl | 73 +++++++++++++ .../mise-install/scripts/install.sh.tftpl | 34 ++++++ .../scripts/post_install.sh.tftpl | 42 ++++++++ 7 files changed, 359 insertions(+) create mode 100644 registry/droopy4096/.images/avatar.png create mode 100644 registry/droopy4096/README.md create mode 100644 registry/droopy4096/modules/mise-install/README.md create mode 100644 registry/droopy4096/modules/mise-install/main.tf create mode 100644 registry/droopy4096/modules/mise-install/mise-install.tftest.hcl create mode 100644 registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl create mode 100644 registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl diff --git a/registry/droopy4096/.images/avatar.png b/registry/droopy4096/.images/avatar.png new file mode 100644 index 000000000..e69de29bb diff --git a/registry/droopy4096/README.md b/registry/droopy4096/README.md new file mode 100644 index 000000000..6ee97a1ec --- /dev/null +++ b/registry/droopy4096/README.md @@ -0,0 +1,11 @@ +--- +display_name: "D Makovey" +bio: "Lifelong tinkerer" +avatar: "./.images/avatar.png" +github: "droopy4096" +status: "community" +--- + +# D Makovey + +Lifelong tinkerer and breaker of things diff --git a/registry/droopy4096/modules/mise-install/README.md b/registry/droopy4096/modules/mise-install/README.md new file mode 100644 index 000000000..5076fde8b --- /dev/null +++ b/registry/droopy4096/modules/mise-install/README.md @@ -0,0 +1,101 @@ +--- +display_name: mise install +description: Install mise and run `mise install` inside a cloned repository. +icon: ../../../../.icons/code.svg +verified: false +tags: [helper, mise, devtools] +--- + +# mise install + +Installs [`mise`](https://mise.jdx.dev/getting-started.html) on the workspace and runs `mise install` inside a repository directory so language runtimes and tools declared in `.mise.toml` / `.tool-versions` are provisioned before the user starts working. + +Designed to compose with the [`coder/git-clone`](https://registry.coder.com/modules/coder/git-clone) module: pass `module.git_clone.repo_dir` as `repo_dir`. + +## Usage + +```tf +module "git_clone" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/git-clone/coder" + version = "2.0.3" + agent_id = coder_agent.main.id + url = "https://github.com/example/repo" +} + +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir +} +``` + +The install script downloads `mise` from `https://mise.run` into `install_dir` (defaults to `$HOME/.local/bin`) and appends `mise activate` to `~/.bashrc` and `~/.zshrc`. The post-install script then runs `mise trust` (optional) and `mise install` inside `repo_dir`. + +## Examples + +### Disable shell activation and `mise trust` + +Use this when the workspace image already activates `mise` globally, or the repository does not use `.mise.toml`: + +```tf +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir + activate_shells = [] + mise_trust = false +} +``` + +### Custom install directory + +```tf +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir + install_dir = "$HOME/.mise/bin" +} +``` + +## Execution order + +This module uses [`coder/coder-utils`](https://registry.coder.com/modules/coder/coder-utils) to run two ordered scripts via `coder exp sync`: + +1. **Install Script** — installs `mise` and (optionally) configures shell activation. +2. **Post-Install Script** — waits for the clone to complete, then runs `mise trust` and `mise install` in `repo_dir`. + +Coder starts every `coder_script` on an agent in parallel, so this module's post-install script cannot use `coder exp sync` to wait on `git-clone` (git-clone does not participate in `coder exp sync`). Instead, the post-install script polls for `${repo_dir}/.git` and only runs `mise install` once the clone has finished. The bound is controlled by `wait_seconds` (default `300`). If the timeout expires, the script logs a message and exits `0` without running `mise install`. + +### Custom wait timeout + +```tf +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir + wait_seconds = 900 # wait up to 15 minutes for large clones +} +``` + +## Troubleshooting + +Scripts and logs are written under a per-module root: + +- Scripts: `$HOME/.coder-modules/droopy4096/mise-install/scripts/{install.sh,post_install.sh}` +- Logs: `$HOME/.coder-modules/droopy4096/mise-install/logs/{install.log,post_install.log}` + +If `mise install` fails, inspect `post_install.log` for the exact `mise` output. Common causes: + +- Missing `.mise.toml` / `.tool-versions` in `repo_dir`. +- Untrusted config (rerun with `mise_trust = true`). +- Network egress restrictions on downloading plugins from `mise.jdx.dev`. diff --git a/registry/droopy4096/modules/mise-install/main.tf b/registry/droopy4096/modules/mise-install/main.tf new file mode 100644 index 000000000..54130830f --- /dev/null +++ b/registry/droopy4096/modules/mise-install/main.tf @@ -0,0 +1,98 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.13" + } + } +} + +variable "agent_id" { + description = "The ID of a Coder agent." + type = string +} + +variable "repo_dir" { + description = "Absolute path to the repository where `mise install` should run. Typically wired to `module.git-clone.repo_dir`." + type = string +} + +variable "mise_trust" { + description = "Whether to run `mise trust` on the repository before `mise install`. Required for projects that ship a `.mise.toml`." + type = bool + default = true +} + +variable "activate_shells" { + description = "Shell rc files to append `mise activate` to. Pass an empty list to skip activation." + type = list(string) + default = ["bash", "zsh"] + + validation { + condition = alltrue([for s in var.activate_shells : contains(["bash", "zsh"], s)]) + error_message = "activate_shells entries must be one of: bash, zsh." + } +} + +variable "install_dir" { + description = "Directory to install the `mise` binary into. Passed to the mise installer as `MISE_INSTALL_PATH`'s parent." + type = string + default = "$HOME/.local/bin" +} + +variable "wait_seconds" { + description = "Maximum seconds to wait for `repo_dir/.git` to appear (i.e. for the git-clone module to finish) before skipping `mise install`." + type = number + default = 300 + + validation { + condition = var.wait_seconds >= 0 + error_message = "wait_seconds must be non-negative." + } +} + +variable "icon" { + description = "Icon shown in the Coder UI for the coder_script resources this module creates." + type = string + default = "/icon/code.svg" +} + +locals { + module_directory = "$HOME/.coder-modules/droopy4096/mise-install" + + install_script = templatefile("${path.module}/scripts/install.sh.tftpl", { + ARG_INSTALL_DIR = var.install_dir + ARG_ACTIVATE_SHELLS = join(" ", var.activate_shells) + }) + + post_install_script = templatefile("${path.module}/scripts/post_install.sh.tftpl", { + ARG_REPO_DIR = var.repo_dir + ARG_MISE_TRUST = tostring(var.mise_trust) + ARG_INSTALL_DIR = var.install_dir + ARG_WAIT_SECONDS = tostring(var.wait_seconds) + }) +} + +module "coder_utils" { + source = "registry.coder.com/coder/coder-utils/coder" + version = "0.0.1" + + agent_id = var.agent_id + module_directory = local.module_directory + display_name_prefix = "mise" + icon = var.icon + install_script = local.install_script + post_install_script = local.post_install_script +} + +output "repo_dir" { + description = "The repository directory where `mise install` was run." + value = var.repo_dir +} + +output "scripts" { + description = "Ordered list of `coder exp sync` names produced by this module, in run order." + value = module.coder_utils.scripts +} diff --git a/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl b/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl new file mode 100644 index 000000000..da4d0df6d --- /dev/null +++ b/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl @@ -0,0 +1,73 @@ +mock_provider "coder" {} + +run "plan_with_required_vars" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + } +} + +run "invalid_activate_shell_fails" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + activate_shells = ["fish"] + } + + expect_failures = [var.activate_shells] +} + +run "empty_activate_shells_allowed" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + activate_shells = [] + } +} + +run "negative_wait_seconds_fails" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + wait_seconds = -1 + } + + expect_failures = [var.wait_seconds] +} + +run "custom_wait_seconds_allowed" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + wait_seconds = 900 + } +} + +run "apply_emits_scripts_output" { + command = apply + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + } + + assert { + condition = length(output.scripts) == 2 + error_message = "Expected scripts output to contain install + post_install entries." + } + + assert { + condition = output.repo_dir == "/home/coder/repo" + error_message = "Expected repo_dir output to echo the input." + } +} diff --git a/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl b/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl new file mode 100644 index 000000000..ca4fedf32 --- /dev/null +++ b/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +ARG_INSTALL_DIR='${ARG_INSTALL_DIR}' +ARG_ACTIVATE_SHELLS='${ARG_ACTIVATE_SHELLS}' + +# Expand leading ~ and $HOME in the install directory path (safer than `eval`). +ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\~/$${HOME}}" +ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\$HOME/$${HOME}}" + +mkdir -p "$${ARG_INSTALL_DIR}" + +if ! command -v mise >/dev/null 2>&1 && [ ! -x "$${ARG_INSTALL_DIR}/mise" ]; then + echo "Installing mise into $${ARG_INSTALL_DIR}..." + MISE_INSTALL_PATH="$${ARG_INSTALL_DIR}/mise" curl -fsSL https://mise.run | sh +else + echo "mise already present, skipping download." +fi + +export PATH="$${ARG_INSTALL_DIR}:$${PATH}" +mise --version + +if [ -n "$${ARG_ACTIVATE_SHELLS}" ]; then + for shell in $${ARG_ACTIVATE_SHELLS}; do + rc="$${HOME}/.$${shell}rc" + touch "$${rc}" + if ! grep -qF "mise activate $${shell}" "$${rc}"; then + echo "Appending mise activation to $${rc}" + printf '\n# Added by droopy4096/mise-install\neval "$(%s/mise activate %s)"\n' "$${ARG_INSTALL_DIR}" "$${shell}" >> "$${rc}" + else + echo "mise activation already present in $${rc}" + fi + done +fi diff --git a/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl b/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl new file mode 100644 index 000000000..74c637802 --- /dev/null +++ b/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -euo pipefail + +ARG_REPO_DIR='${ARG_REPO_DIR}' +ARG_MISE_TRUST='${ARG_MISE_TRUST}' +ARG_INSTALL_DIR='${ARG_INSTALL_DIR}' +ARG_WAIT_SECONDS='${ARG_WAIT_SECONDS}' + +# Expand leading ~ and $HOME in caller-supplied paths (safer than `eval`). +ARG_REPO_DIR="$${ARG_REPO_DIR/#\~/$${HOME}}" +ARG_REPO_DIR="$${ARG_REPO_DIR/#\$HOME/$${HOME}}" +ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\~/$${HOME}}" +ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\$HOME/$${HOME}}" + +export PATH="$${ARG_INSTALL_DIR}:$${PATH}" + +if ! command -v mise >/dev/null 2>&1; then + echo "mise is not on PATH; the install script must run first." + exit 1 +fi + +# Wait for the clone to finish. Checking for ".git" (not just the directory) +# guards against racing a bare mkdir -p performed before cloning begins. +deadline=$(( $(date +%s) + ARG_WAIT_SECONDS )) +while [ ! -d "$${ARG_REPO_DIR}/.git" ]; do + if [ "$(date +%s)" -ge "$${deadline}" ]; then + echo "Timed out after $${ARG_WAIT_SECONDS}s waiting for $${ARG_REPO_DIR}/.git; skipping 'mise install'." + exit 0 + fi + echo "Waiting for $${ARG_REPO_DIR}/.git to appear..." + sleep 2 +done + +cd "$${ARG_REPO_DIR}" + +if [ "$${ARG_MISE_TRUST}" = "true" ]; then + echo "Running 'mise trust' in $${ARG_REPO_DIR}..." + mise trust || echo "Warning: 'mise trust' failed; continuing." +fi + +echo "Running 'mise install' in $${ARG_REPO_DIR}..." +mise install From 2c75a8a8cf4a716bc1965754f013927f30a785b4 Mon Sep 17 00:00:00 2001 From: Dmytro Makovey Date: Thu, 20 Aug 2026 11:55:59 -0700 Subject: [PATCH 4/6] mise-install: place primary tf block inside h1 section The README validator (cmd/readmevalidation/codermodules.go) requires exactly one 'tf' code block with a 'version' field between the h1 heading and the first h2. Move the primary usage snippet directly under '# mise install' and demote the git-clone composition example to '### Compose with coder/git-clone' under '## Examples'. --- .../droopy4096/modules/mise-install/README.md | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/registry/droopy4096/modules/mise-install/README.md b/registry/droopy4096/modules/mise-install/README.md index 5076fde8b..a85316b42 100644 --- a/registry/droopy4096/modules/mise-install/README.md +++ b/registry/droopy4096/modules/mise-install/README.md @@ -12,7 +12,21 @@ Installs [`mise`](https://mise.jdx.dev/getting-started.html) on the workspace an Designed to compose with the [`coder/git-clone`](https://registry.coder.com/modules/coder/git-clone) module: pass `module.git_clone.repo_dir` as `repo_dir`. -## Usage +```tf +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir +} +``` + +The install script downloads `mise` from `https://mise.run` into `install_dir` (defaults to `$HOME/.local/bin`) and appends `mise activate` to `~/.bashrc` and `~/.zshrc`. The post-install script then runs `mise trust` (optional) and `mise install` inside `repo_dir`. + +## Examples + +### Compose with `coder/git-clone` ```tf module "git_clone" { @@ -32,10 +46,6 @@ module "mise_install" { } ``` -The install script downloads `mise` from `https://mise.run` into `install_dir` (defaults to `$HOME/.local/bin`) and appends `mise activate` to `~/.bashrc` and `~/.zshrc`. The post-install script then runs `mise trust` (optional) and `mise install` inside `repo_dir`. - -## Examples - ### Disable shell activation and `mise trust` Use this when the workspace image already activates `mise` globally, or the repository does not use `.mise.toml`: From b9ce1f055b4103349700ff74e0f6fe82bff7733c Mon Sep 17 00:00:00 2001 From: Dmytro Makovey Date: Thu, 20 Aug 2026 12:56:43 -0700 Subject: [PATCH 5/6] Update logo --- .../modules/mise-install/.icons/logo.svg | 16 ++++++++++++++++ .../droopy4096/modules/mise-install/README.md | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 registry/droopy4096/modules/mise-install/.icons/logo.svg diff --git a/registry/droopy4096/modules/mise-install/.icons/logo.svg b/registry/droopy4096/modules/mise-install/.icons/logo.svg new file mode 100644 index 000000000..73ef48894 --- /dev/null +++ b/registry/droopy4096/modules/mise-install/.icons/logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/registry/droopy4096/modules/mise-install/README.md b/registry/droopy4096/modules/mise-install/README.md index a85316b42..e0583c709 100644 --- a/registry/droopy4096/modules/mise-install/README.md +++ b/registry/droopy4096/modules/mise-install/README.md @@ -1,7 +1,7 @@ --- display_name: mise install description: Install mise and run `mise install` inside a cloned repository. -icon: ../../../../.icons/code.svg +icon: .icons/logo.svg verified: false tags: [helper, mise, devtools] --- From 8833035ba3a2afee9d29e05b0d87303899123036 Mon Sep 17 00:00:00 2001 From: Dmytro Makovey Date: Thu, 20 Aug 2026 13:13:51 -0700 Subject: [PATCH 6/6] mise-install: restricted-environment readiness (install_url, install_mise, mise_bin, egress docs) Addresses the Restricted-Environment Readiness feedback from the PR scorecard (#1068 scored 2/20 on this category). Mirrorable artifact source: - Add 'install_url' variable (default https://mise.run) so operators can point the installer at an internal mirror. - Add 'mise_version' variable that, when non-empty, exports MISE_VERSION before piping the installer to sh for reproducible pinning. Bring-your-own binary: - Add 'install_mise' bool (default true). When false, the install script skips the download and expects mise to be provided by the workspace image. - Add 'mise_bin' string variable pointing at a pre-installed mise binary; when set, its directory is prepended to PATH for both the install and post-install scripts. The install script validates it is executable and fails loudly if mise is not on PATH after the install phase. Shell activation resolves mise via 'command -v mise' so the rc-file eval line uses an absolute path regardless of source. Egress transparency: - Add a dedicated 'Network egress' README section enumerating every external endpoint the module (or its transitive downloads) reach, which variable overrides each, and guidance for fully air-gapped workspaces. - Add an 'Air-gapped / mirrored installer' example demonstrating the three new variables together (mirror + pinned version + BYO binary). - Move the stray egress note out of Troubleshooting and link to the new section instead. Also: - Move the module logo from a module-local .icons/logo.svg to the repo-level .icons/mise.svg so it conforms to the CONTRIBUTING rule that module icons must live in the top-level /.icons directory and be referenced as ../../../../.icons/.svg. - Add tftest cases for the four new inputs. Tests: 10 passed, 0 failed. --- .../.icons/logo.svg => .icons/mise.svg | 0 .../droopy4096/modules/mise-install/README.md | 46 +++++++++++++++- .../droopy4096/modules/mise-install/main.tf | 29 +++++++++++ .../mise-install/mise-install.tftest.hcl | 41 +++++++++++++++ .../mise-install/scripts/install.sh.tftpl | 52 ++++++++++++++++--- .../scripts/post_install.sh.tftpl | 8 ++- 6 files changed, 165 insertions(+), 11 deletions(-) rename registry/droopy4096/modules/mise-install/.icons/logo.svg => .icons/mise.svg (100%) diff --git a/registry/droopy4096/modules/mise-install/.icons/logo.svg b/.icons/mise.svg similarity index 100% rename from registry/droopy4096/modules/mise-install/.icons/logo.svg rename to .icons/mise.svg diff --git a/registry/droopy4096/modules/mise-install/README.md b/registry/droopy4096/modules/mise-install/README.md index e0583c709..3639e4414 100644 --- a/registry/droopy4096/modules/mise-install/README.md +++ b/registry/droopy4096/modules/mise-install/README.md @@ -1,7 +1,7 @@ --- display_name: mise install description: Install mise and run `mise install` inside a cloned repository. -icon: .icons/logo.svg +icon: ../../../../.icons/mise.svg verified: false tags: [helper, mise, devtools] --- @@ -75,6 +75,48 @@ module "mise_install" { } ``` +### Air-gapped / mirrored installer + +Point the installer at an internal mirror, pin the release, and skip the download entirely by using the `mise` already baked into the workspace image: + +```tf +# Fully mirrored: download the installer from an internal HTTPS mirror +# and pin the mise release for reproducibility. +module "mise_install" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir + install_url = "https://artifacts.internal.example.com/mise/install.sh" + mise_version = "v2024.9.0" +} + +# Bring-your-own binary: the image already ships mise; skip the download. +module "mise_install_byo" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/droopy4096/mise-install/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + repo_dir = module.git_clone[count.index].repo_dir + install_mise = false + mise_bin = "/opt/mise/bin/mise" # optional; omit if 'mise' is on PATH +} +``` + +## Network egress + +This module reaches the following external endpoints. Mirror or allow-list them (or use `install_mise = false`) in restricted environments: + +| When | Endpoint | Overridable via | +| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| Install phase (only when `install_mise = true`) | `https://mise.run` — installer shell script | `install_url` | +| Install phase (transitive from installer) | `https://github.com/jdx/mise/releases/*` — mise binary release assets | Mirror inside `install_url`'s script or use `install_mise = false` + `mise_bin` | +| Post-install phase (`mise install`) | `https://mise.jdx.dev/*` — plugin registry and metadata | `MISE_*` env vars (see mise docs); not exposed by this module | +| Post-install phase (transitive) | Language-runtime hosts (`python.org`, `nodejs.org`, `go.dev`, etc.) — driven by `.mise.toml` / `.tool-versions` in `repo_dir` | Configure `mise` plugins/mirrors in the image | + +If your environment blocks all outbound traffic, set `install_mise = false`, ship `mise` in the image, and mirror the plugin/runtime hosts `mise install` needs at runtime. + ## Execution order This module uses [`coder/coder-utils`](https://registry.coder.com/modules/coder/coder-utils) to run two ordered scripts via `coder exp sync`: @@ -108,4 +150,4 @@ If `mise install` fails, inspect `post_install.log` for the exact `mise` output. - Missing `.mise.toml` / `.tool-versions` in `repo_dir`. - Untrusted config (rerun with `mise_trust = true`). -- Network egress restrictions on downloading plugins from `mise.jdx.dev`. +- Network egress blocked to endpoints listed under [Network egress](#network-egress). diff --git a/registry/droopy4096/modules/mise-install/main.tf b/registry/droopy4096/modules/mise-install/main.tf index 54130830f..b700d2297 100644 --- a/registry/droopy4096/modules/mise-install/main.tf +++ b/registry/droopy4096/modules/mise-install/main.tf @@ -42,6 +42,30 @@ variable "install_dir" { default = "$HOME/.local/bin" } +variable "install_mise" { + description = "Whether to download and install `mise`. Set to false in restricted or air-gapped environments where the workspace image already ships `mise`; the module will then only configure shell activation and run `mise install`." + type = bool + default = true +} + +variable "install_url" { + description = "URL of the mise installer script. Override to point at an internal mirror in restricted environments. Ignored when `install_mise = false`." + type = string + default = "https://mise.run" +} + +variable "mise_version" { + description = "Pin the mise release to install by setting `MISE_VERSION` before invoking the installer (e.g. `\"v2024.9.0\"`). Empty means install the latest release advertised by `install_url`. Ignored when `install_mise = false`." + type = string + default = "" +} + +variable "mise_bin" { + description = "Absolute path to a pre-installed `mise` binary (e.g. `/opt/mise/bin/mise` baked into a workspace image). When non-empty, its directory is prepended to PATH so this module and downstream scripts pick it up. Combine with `install_mise = false` to fully opt out of downloading." + type = string + default = "" +} + variable "wait_seconds" { description = "Maximum seconds to wait for `repo_dir/.git` to appear (i.e. for the git-clone module to finish) before skipping `mise install`." type = number @@ -65,12 +89,17 @@ locals { install_script = templatefile("${path.module}/scripts/install.sh.tftpl", { ARG_INSTALL_DIR = var.install_dir ARG_ACTIVATE_SHELLS = join(" ", var.activate_shells) + ARG_INSTALL_MISE = tostring(var.install_mise) + ARG_INSTALL_URL = var.install_url + ARG_MISE_VERSION = var.mise_version + ARG_MISE_BIN = var.mise_bin }) post_install_script = templatefile("${path.module}/scripts/post_install.sh.tftpl", { ARG_REPO_DIR = var.repo_dir ARG_MISE_TRUST = tostring(var.mise_trust) ARG_INSTALL_DIR = var.install_dir + ARG_MISE_BIN = var.mise_bin ARG_WAIT_SECONDS = tostring(var.wait_seconds) }) } diff --git a/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl b/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl index da4d0df6d..6c835bbad 100644 --- a/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl +++ b/registry/droopy4096/modules/mise-install/mise-install.tftest.hcl @@ -53,6 +53,47 @@ run "custom_wait_seconds_allowed" { } } +run "custom_install_url_allowed" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + install_url = "https://artifacts.internal.example.com/mise/install.sh" + } +} + +run "pinned_mise_version_allowed" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + mise_version = "v2024.9.0" + } +} + +run "install_mise_false_plans" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + install_mise = false + } +} + +run "bring_your_own_mise_bin_plans" { + command = plan + + variables { + agent_id = "example-agent-id" + repo_dir = "/home/coder/repo" + install_mise = false + mise_bin = "/opt/mise/bin/mise" + } +} + run "apply_emits_scripts_output" { command = apply diff --git a/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl b/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl index ca4fedf32..31aa7f47b 100644 --- a/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl +++ b/registry/droopy4096/modules/mise-install/scripts/install.sh.tftpl @@ -3,21 +3,57 @@ set -euo pipefail ARG_INSTALL_DIR='${ARG_INSTALL_DIR}' ARG_ACTIVATE_SHELLS='${ARG_ACTIVATE_SHELLS}' +ARG_INSTALL_MISE='${ARG_INSTALL_MISE}' +ARG_INSTALL_URL='${ARG_INSTALL_URL}' +ARG_MISE_VERSION='${ARG_MISE_VERSION}' +ARG_MISE_BIN='${ARG_MISE_BIN}' -# Expand leading ~ and $HOME in the install directory path (safer than `eval`). +# Expand leading ~ and $HOME in caller-supplied paths (safer than `eval`). ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\~/$${HOME}}" ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\$HOME/$${HOME}}" +if [ -n "$${ARG_MISE_BIN}" ]; then + ARG_MISE_BIN="$${ARG_MISE_BIN/#\~/$${HOME}}" + ARG_MISE_BIN="$${ARG_MISE_BIN/#\$HOME/$${HOME}}" +fi -mkdir -p "$${ARG_INSTALL_DIR}" +# If a pre-installed mise binary was pointed at, prepend its directory +# to PATH so both this script and downstream ones pick it up. +if [ -n "$${ARG_MISE_BIN}" ]; then + if [ ! -x "$${ARG_MISE_BIN}" ]; then + echo "ERROR: mise_bin='$${ARG_MISE_BIN}' is not an executable file." + exit 1 + fi + export PATH="$(dirname "$${ARG_MISE_BIN}"):$${PATH}" +fi -if ! command -v mise >/dev/null 2>&1 && [ ! -x "$${ARG_INSTALL_DIR}/mise" ]; then - echo "Installing mise into $${ARG_INSTALL_DIR}..." - MISE_INSTALL_PATH="$${ARG_INSTALL_DIR}/mise" curl -fsSL https://mise.run | sh +if [ "$${ARG_INSTALL_MISE}" = "true" ]; then + mkdir -p "$${ARG_INSTALL_DIR}" + if command -v mise >/dev/null 2>&1 || [ -x "$${ARG_INSTALL_DIR}/mise" ]; then + echo "mise already present, skipping download." + else + echo "Installing mise from $${ARG_INSTALL_URL} into $${ARG_INSTALL_DIR}..." + if [ -n "$${ARG_MISE_VERSION}" ]; then + MISE_VERSION="$${ARG_MISE_VERSION}" \ + MISE_INSTALL_PATH="$${ARG_INSTALL_DIR}/mise" \ + curl -fsSL "$${ARG_INSTALL_URL}" | sh + else + MISE_INSTALL_PATH="$${ARG_INSTALL_DIR}/mise" \ + curl -fsSL "$${ARG_INSTALL_URL}" | sh + fi + fi + export PATH="$${ARG_INSTALL_DIR}:$${PATH}" else - echo "mise already present, skipping download." + echo "install_mise=false; skipping download. Expecting 'mise' from the workspace image or 'mise_bin'." +fi + +if ! command -v mise >/dev/null 2>&1; then + echo "ERROR: 'mise' is not on PATH after the install phase." + echo "Either set install_mise=true, ensure the workspace image ships mise, or set mise_bin." + exit 1 fi -export PATH="$${ARG_INSTALL_DIR}:$${PATH}" +resolved_mise="$(command -v mise)" +echo "Using mise at $${resolved_mise}" mise --version if [ -n "$${ARG_ACTIVATE_SHELLS}" ]; then @@ -26,7 +62,7 @@ if [ -n "$${ARG_ACTIVATE_SHELLS}" ]; then touch "$${rc}" if ! grep -qF "mise activate $${shell}" "$${rc}"; then echo "Appending mise activation to $${rc}" - printf '\n# Added by droopy4096/mise-install\neval "$(%s/mise activate %s)"\n' "$${ARG_INSTALL_DIR}" "$${shell}" >> "$${rc}" + printf '\n# Added by droopy4096/mise-install\neval "$(%s activate %s)"\n' "$${resolved_mise}" "$${shell}" >> "$${rc}" else echo "mise activation already present in $${rc}" fi diff --git a/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl b/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl index 74c637802..5857d1f10 100644 --- a/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl +++ b/registry/droopy4096/modules/mise-install/scripts/post_install.sh.tftpl @@ -4,6 +4,7 @@ set -euo pipefail ARG_REPO_DIR='${ARG_REPO_DIR}' ARG_MISE_TRUST='${ARG_MISE_TRUST}' ARG_INSTALL_DIR='${ARG_INSTALL_DIR}' +ARG_MISE_BIN='${ARG_MISE_BIN}' ARG_WAIT_SECONDS='${ARG_WAIT_SECONDS}' # Expand leading ~ and $HOME in caller-supplied paths (safer than `eval`). @@ -11,11 +12,16 @@ ARG_REPO_DIR="$${ARG_REPO_DIR/#\~/$${HOME}}" ARG_REPO_DIR="$${ARG_REPO_DIR/#\$HOME/$${HOME}}" ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\~/$${HOME}}" ARG_INSTALL_DIR="$${ARG_INSTALL_DIR/#\$HOME/$${HOME}}" +if [ -n "$${ARG_MISE_BIN}" ]; then + ARG_MISE_BIN="$${ARG_MISE_BIN/#\~/$${HOME}}" + ARG_MISE_BIN="$${ARG_MISE_BIN/#\$HOME/$${HOME}}" + export PATH="$(dirname "$${ARG_MISE_BIN}"):$${PATH}" +fi export PATH="$${ARG_INSTALL_DIR}:$${PATH}" if ! command -v mise >/dev/null 2>&1; then - echo "mise is not on PATH; the install script must run first." + echo "mise is not on PATH; the install script must run first (or provide mise via mise_bin / image)." exit 1 fi