Merge branch 'main' into 35C4n0r/feat-agentapi-architecture-improv
This commit is contained in:
commit
71c5a4fe11
@ -18,7 +18,7 @@ Under the hood, this module uses the [coder dotfiles](https://coder.com/docs/v2/
|
|||||||
module "dotfiles" {
|
module "dotfiles" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/dotfiles/coder"
|
source = "registry.coder.com/coder/dotfiles/coder"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -31,7 +31,7 @@ module "dotfiles" {
|
|||||||
module "dotfiles" {
|
module "dotfiles" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/dotfiles/coder"
|
source = "registry.coder.com/coder/dotfiles/coder"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -42,7 +42,7 @@ module "dotfiles" {
|
|||||||
module "dotfiles" {
|
module "dotfiles" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/dotfiles/coder"
|
source = "registry.coder.com/coder/dotfiles/coder"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
user = "root"
|
user = "root"
|
||||||
}
|
}
|
||||||
@ -54,14 +54,14 @@ module "dotfiles" {
|
|||||||
module "dotfiles" {
|
module "dotfiles" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/dotfiles/coder"
|
source = "registry.coder.com/coder/dotfiles/coder"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
}
|
}
|
||||||
|
|
||||||
module "dotfiles-root" {
|
module "dotfiles-root" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/dotfiles/coder"
|
source = "registry.coder.com/coder/dotfiles/coder"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
user = "root"
|
user = "root"
|
||||||
dotfiles_uri = module.dotfiles.dotfiles_uri
|
dotfiles_uri = module.dotfiles.dotfiles_uri
|
||||||
@ -76,7 +76,7 @@ You can set a default dotfiles repository for all users by setting the `default_
|
|||||||
module "dotfiles" {
|
module "dotfiles" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/dotfiles/coder"
|
source = "registry.coder.com/coder/dotfiles/coder"
|
||||||
version = "1.3.0"
|
version = "1.3.1"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
default_dotfiles_uri = "https://github.com/coder/dotfiles"
|
default_dotfiles_uri = "https://github.com/coder/dotfiles"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ describe("dotfiles", async () => {
|
|||||||
"git@github.com:coder/dotfiles.git",
|
"git@github.com:coder/dotfiles.git",
|
||||||
"git://github.com/coder/dotfiles.git",
|
"git://github.com/coder/dotfiles.git",
|
||||||
"ssh://git@github.com/coder/dotfiles.git",
|
"ssh://git@github.com/coder/dotfiles.git",
|
||||||
|
"ssh://git@bitbucket.example.org:7999/~myusername/dotfiles.git",
|
||||||
];
|
];
|
||||||
for (const url of validUrls) {
|
for (const url of validUrls) {
|
||||||
const state = await runTerraformApply(import.meta.dir, {
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
|||||||
@ -40,7 +40,7 @@ variable "default_dotfiles_uri" {
|
|||||||
validation {
|
validation {
|
||||||
condition = (
|
condition = (
|
||||||
var.default_dotfiles_uri == "" ||
|
var.default_dotfiles_uri == "" ||
|
||||||
can(regex("^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@-]+$", var.default_dotfiles_uri))
|
can(regex("^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@~-]+$", var.default_dotfiles_uri))
|
||||||
)
|
)
|
||||||
error_message = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters."
|
error_message = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters."
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ variable "dotfiles_uri" {
|
|||||||
condition = (
|
condition = (
|
||||||
var.dotfiles_uri == null ||
|
var.dotfiles_uri == null ||
|
||||||
var.dotfiles_uri == "" ||
|
var.dotfiles_uri == "" ||
|
||||||
can(regex("^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@-]+$", var.dotfiles_uri))
|
can(regex("^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@~-]+$", var.dotfiles_uri))
|
||||||
)
|
)
|
||||||
error_message = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters."
|
error_message = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters."
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ data "coder_parameter" "dotfiles_uri" {
|
|||||||
icon = "/icon/dotfiles.svg"
|
icon = "/icon/dotfiles.svg"
|
||||||
|
|
||||||
validation {
|
validation {
|
||||||
regex = "^$|^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@-]+$"
|
regex = "^$|^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@~-]+$"
|
||||||
error = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters."
|
error = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,13 +8,13 @@ tags: [ai, agents, development, multiplexer]
|
|||||||
|
|
||||||
# Mux
|
# Mux
|
||||||
|
|
||||||
Automatically install and run [Mux](https://github.com/coder/mux) in a Coder workspace. By default, the module installs `mux@next` from npm (with a fallback to downloading the npm tarball if npm is unavailable). Mux is a desktop application for parallel agentic development that enables developers to run multiple AI agents simultaneously across isolated workspaces.
|
Automatically install and run [Mux](https://github.com/coder/mux) in a Coder workspace. By default, the module auto-detects an available package manager (`npm`, `pnpm`, or `bun`) to install `mux@next` (with a fallback to downloading the npm tarball if none is found). You can also force a specific package manager via `package_manager` and point to a custom registry with `registry_url`. Mux is a desktop application for parallel agentic development that enables developers to run multiple AI agents simultaneously across isolated workspaces.
|
||||||
|
|
||||||
```tf
|
```tf
|
||||||
module "mux" {
|
module "mux" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/mux/coder"
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -37,7 +37,7 @@ module "mux" {
|
|||||||
module "mux" {
|
module "mux" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/mux/coder"
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -48,7 +48,7 @@ module "mux" {
|
|||||||
module "mux" {
|
module "mux" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/mux/coder"
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
# Default is "latest"; set to a specific version to pin
|
# Default is "latest"; set to a specific version to pin
|
||||||
install_version = "0.4.0"
|
install_version = "0.4.0"
|
||||||
@ -63,7 +63,7 @@ Start Mux with `mux server --add-project /path/to/project`:
|
|||||||
module "mux" {
|
module "mux" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/mux/coder"
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
add-project = "/path/to/project"
|
add-project = "/path/to/project"
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ The module parses quoted values, so grouped arguments remain intact.
|
|||||||
module "mux" {
|
module "mux" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/mux/coder"
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
additional_arguments = "--open-mode pinned --add-project '/workspaces/my repo'"
|
additional_arguments = "--open-mode pinned --add-project '/workspaces/my repo'"
|
||||||
}
|
}
|
||||||
@ -90,12 +90,40 @@ module "mux" {
|
|||||||
module "mux" {
|
module "mux" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/mux/coder"
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
port = 8080
|
port = 8080
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Custom Package Manager
|
||||||
|
|
||||||
|
Force a specific package manager instead of auto-detection:
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "mux" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
|
version = "1.3.0"
|
||||||
|
agent_id = coder_agent.main.id
|
||||||
|
package_manager = "pnpm" # or "npm", "bun"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Registry
|
||||||
|
|
||||||
|
Use a private or mirrored npm registry:
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "mux" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
|
version = "1.3.0"
|
||||||
|
agent_id = coder_agent.main.id
|
||||||
|
registry_url = "https://npm.pkg.github.com"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Use Cached Installation
|
### Use Cached Installation
|
||||||
|
|
||||||
Run an existing copy of Mux if found, otherwise install from npm:
|
Run an existing copy of Mux if found, otherwise install from npm:
|
||||||
@ -104,7 +132,7 @@ Run an existing copy of Mux if found, otherwise install from npm:
|
|||||||
module "mux" {
|
module "mux" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/mux/coder"
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
use_cached = true
|
use_cached = true
|
||||||
}
|
}
|
||||||
@ -118,7 +146,7 @@ Run without installing from the network (requires Mux to be pre-installed):
|
|||||||
module "mux" {
|
module "mux" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/mux/coder"
|
source = "registry.coder.com/coder/mux/coder"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
install = false
|
install = false
|
||||||
}
|
}
|
||||||
@ -132,4 +160,6 @@ module "mux" {
|
|||||||
|
|
||||||
- Mux is currently in preview and you may encounter bugs
|
- Mux is currently in preview and you may encounter bugs
|
||||||
- Requires internet connectivity for agent operations (unless `install` is set to false)
|
- Requires internet connectivity for agent operations (unless `install` is set to false)
|
||||||
- Installs `mux@next` from npm by default (falls back to the npm tarball if npm is unavailable)
|
- Auto-detects `npm`, `pnpm`, or `bun` by default; set `package_manager` to force a specific one
|
||||||
|
- Installs `mux@next` from the npm registry by default; set `registry_url` to use a private or mirrored registry
|
||||||
|
- Falls back to a direct tarball download when no package manager is found
|
||||||
|
|||||||
@ -35,7 +35,7 @@ describe("mux", async () => {
|
|||||||
}
|
}
|
||||||
expect(output.exitCode).toBe(0);
|
expect(output.exitCode).toBe(0);
|
||||||
const expectedLines = [
|
const expectedLines = [
|
||||||
"📥 npm not found; downloading tarball from npm registry...",
|
"📥 No package manager found; downloading tarball from registry...",
|
||||||
"🥳 mux has been installed in /tmp/mux",
|
"🥳 mux has been installed in /tmp/mux",
|
||||||
"🚀 Starting mux server on port 4000...",
|
"🚀 Starting mux server on port 4000...",
|
||||||
"Check logs at /tmp/mux.log!",
|
"Check logs at /tmp/mux.log!",
|
||||||
@ -111,7 +111,7 @@ chmod +x /tmp/mux/mux`,
|
|||||||
expect(output.exitCode).toBe(0);
|
expect(output.exitCode).toBe(0);
|
||||||
const expectedLines = [
|
const expectedLines = [
|
||||||
"📦 Installing mux via npm into /tmp/mux...",
|
"📦 Installing mux via npm into /tmp/mux...",
|
||||||
"⏭️ Skipping npm lifecycle scripts with --ignore-scripts",
|
"⏭️ Skipping lifecycle scripts with --ignore-scripts",
|
||||||
"🥳 mux has been installed in /tmp/mux",
|
"🥳 mux has been installed in /tmp/mux",
|
||||||
"🚀 Starting mux server on port 4000...",
|
"🚀 Starting mux server on port 4000...",
|
||||||
"Check logs at /tmp/mux.log!",
|
"Check logs at /tmp/mux.log!",
|
||||||
|
|||||||
@ -67,6 +67,23 @@ variable "install_version" {
|
|||||||
default = "next"
|
default = "next"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "package_manager" {
|
||||||
|
type = string
|
||||||
|
description = "Package manager to install Mux. 'auto' detects npm, pnpm, or bun (falling back to tarball download). Set to 'npm', 'pnpm', or 'bun' to force a specific one."
|
||||||
|
default = "auto"
|
||||||
|
validation {
|
||||||
|
condition = contains(["auto", "npm", "pnpm", "bun"], var.package_manager)
|
||||||
|
error_message = "The 'package_manager' variable must be one of: 'auto', 'npm', 'pnpm', 'bun'."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "registry_url" {
|
||||||
|
type = string
|
||||||
|
description = "The npm-compatible registry URL to install Mux from. Override this for private registries or mirrors."
|
||||||
|
default = "https://registry.npmjs.org"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
variable "share" {
|
variable "share" {
|
||||||
type = string
|
type = string
|
||||||
default = "owner"
|
default = "owner"
|
||||||
@ -137,6 +154,7 @@ resource "random_password" "mux_auth_token" {
|
|||||||
|
|
||||||
locals {
|
locals {
|
||||||
mux_auth_token = random_password.mux_auth_token.result
|
mux_auth_token = random_password.mux_auth_token.result
|
||||||
|
registry_url = trimsuffix(var.registry_url, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "coder_script" "mux" {
|
resource "coder_script" "mux" {
|
||||||
@ -153,6 +171,8 @@ resource "coder_script" "mux" {
|
|||||||
OFFLINE : !var.install,
|
OFFLINE : !var.install,
|
||||||
USE_CACHED : var.use_cached,
|
USE_CACHED : var.use_cached,
|
||||||
AUTH_TOKEN : local.mux_auth_token,
|
AUTH_TOKEN : local.mux_auth_token,
|
||||||
|
PACKAGE_MANAGER : var.package_manager,
|
||||||
|
REGISTRY_URL : local.registry_url,
|
||||||
})
|
})
|
||||||
run_on_start = true
|
run_on_start = true
|
||||||
|
|
||||||
|
|||||||
@ -121,3 +121,96 @@ run "use_cached_only_success" {
|
|||||||
use_cached = true
|
use_cached = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Custom package_manager should appear in generated script
|
||||||
|
run "custom_package_manager_npm" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
package_manager = "npm"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = strcontains(resource.coder_script.mux.script, "PM_CMD=\"npm\"")
|
||||||
|
error_message = "mux script must set PM_CMD to the configured package manager"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run "custom_package_manager_pnpm" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
package_manager = "pnpm"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = strcontains(resource.coder_script.mux.script, "PM_CMD=\"pnpm\"")
|
||||||
|
error_message = "mux script must set PM_CMD to the configured package manager"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run "custom_package_manager_bun" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
package_manager = "bun"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = strcontains(resource.coder_script.mux.script, "PM_CMD=\"bun\"")
|
||||||
|
error_message = "mux script must set PM_CMD to the configured package manager"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Invalid package_manager should fail validation
|
||||||
|
run "invalid_package_manager" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
package_manager = "yarn"
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_failures = [
|
||||||
|
var.package_manager
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Custom registry_url should appear in generated script
|
||||||
|
run "custom_registry_url" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
registry_url = "https://npm.example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = strcontains(resource.coder_script.mux.script, "https://npm.example.com")
|
||||||
|
error_message = "mux script must use the configured registry URL"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = !strcontains(resource.coder_script.mux.script, "registry.npmjs.org")
|
||||||
|
error_message = "mux script must not contain hardcoded registry.npmjs.org when custom registry is set"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# registry_url trailing slash should be stripped
|
||||||
|
run "registry_url_trailing_slash" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
registry_url = "https://npm.example.com/"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = strcontains(resource.coder_script.mux.script, "https://npm.example.com/mux/")
|
||||||
|
error_message = "registry URL trailing slash must be stripped to avoid double slashes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,7 @@ fi
|
|||||||
|
|
||||||
# If there is no cached install OR we don't want to use a cached install
|
# If there is no cached install OR we don't want to use a cached install
|
||||||
if [ ! -f "$MUX_BINARY" ] || [ "${USE_CACHED}" != true ]; then
|
if [ ! -f "$MUX_BINARY" ] || [ "${USE_CACHED}" != true ]; then
|
||||||
printf "$${BOLD}Installing mux from npm...\n"
|
printf "$${BOLD}Installing mux...\n"
|
||||||
|
|
||||||
# Clean up from other install (in case install prefix changed).
|
# Clean up from other install (in case install prefix changed).
|
||||||
if [ -n "$CODER_SCRIPT_BIN_DIR" ] && [ -e "$CODER_SCRIPT_BIN_DIR/mux" ]; then
|
if [ -n "$CODER_SCRIPT_BIN_DIR" ] && [ -e "$CODER_SCRIPT_BIN_DIR/mux" ]; then
|
||||||
@ -63,41 +63,76 @@ if [ ! -f "$MUX_BINARY" ] || [ "${USE_CACHED}" != true ]; then
|
|||||||
|
|
||||||
mkdir -p "$(dirname "$MUX_BINARY")"
|
mkdir -p "$(dirname "$MUX_BINARY")"
|
||||||
|
|
||||||
if command -v npm > /dev/null 2>&1; then
|
# Determine which package manager to use
|
||||||
echo "📦 Installing mux via npm into ${INSTALL_PREFIX}..."
|
PM_CMD=""
|
||||||
|
if [ "${PACKAGE_MANAGER}" = "auto" ]; then
|
||||||
|
for pm in npm pnpm bun; do
|
||||||
|
if command -v "$pm" > /dev/null 2>&1; then
|
||||||
|
PM_CMD="$pm"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
PM_CMD="${PACKAGE_MANAGER}"
|
||||||
|
if ! command -v "$PM_CMD" > /dev/null 2>&1; then
|
||||||
|
echo "❌ Configured package manager '${PACKAGE_MANAGER}' not found on PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$PM_CMD" ]; then
|
||||||
|
echo "📦 Installing mux via $PM_CMD into ${INSTALL_PREFIX}..."
|
||||||
NPM_WORKDIR="${INSTALL_PREFIX}/npm"
|
NPM_WORKDIR="${INSTALL_PREFIX}/npm"
|
||||||
mkdir -p "$NPM_WORKDIR"
|
mkdir -p "$NPM_WORKDIR"
|
||||||
cd "$NPM_WORKDIR" || exit 1
|
cd "$NPM_WORKDIR" || exit 1
|
||||||
if [ ! -f package.json ]; then
|
if [ ! -f package.json ]; then
|
||||||
echo '{}' > package.json
|
echo '{}' > package.json
|
||||||
fi
|
fi
|
||||||
echo "⏭️ Skipping npm lifecycle scripts with --ignore-scripts"
|
echo "⏭️ Skipping lifecycle scripts with --ignore-scripts"
|
||||||
PKG="mux"
|
PKG="mux"
|
||||||
if [ -z "${VERSION}" ] || [ "${VERSION}" = "latest" ]; then
|
if [ -z "${VERSION}" ] || [ "${VERSION}" = "latest" ]; then
|
||||||
PKG_SPEC="$PKG@latest"
|
PKG_SPEC="$PKG@latest"
|
||||||
else
|
else
|
||||||
PKG_SPEC="$PKG@${VERSION}"
|
PKG_SPEC="$PKG@${VERSION}"
|
||||||
fi
|
fi
|
||||||
if ! npm install --no-audit --no-fund --omit=dev --ignore-scripts "$PKG_SPEC"; then
|
INSTALL_OK=true
|
||||||
echo "❌ Failed to install mux via npm"
|
case "$PM_CMD" in
|
||||||
|
npm)
|
||||||
|
if ! npm install --no-audit --no-fund --omit=dev --ignore-scripts --registry "${REGISTRY_URL}" "$PKG_SPEC"; then
|
||||||
|
INSTALL_OK=false
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
pnpm)
|
||||||
|
if ! pnpm add --ignore-scripts --registry "${REGISTRY_URL}" "$PKG_SPEC"; then
|
||||||
|
INSTALL_OK=false
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
bun)
|
||||||
|
if ! bun add --ignore-scripts --registry "${REGISTRY_URL}" "$PKG_SPEC"; then
|
||||||
|
INSTALL_OK=false
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ "$INSTALL_OK" != true ]; then
|
||||||
|
echo "❌ Failed to install mux via $PM_CMD"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# Determine the installed binary path
|
# Determine the installed binary path
|
||||||
BIN_DIR="$NPM_WORKDIR/node_modules/.bin"
|
BIN_DIR="$NPM_WORKDIR/node_modules/.bin"
|
||||||
CANDIDATE="$BIN_DIR/mux"
|
CANDIDATE="$BIN_DIR/mux"
|
||||||
if [ ! -f "$CANDIDATE" ]; then
|
if [ ! -f "$CANDIDATE" ]; then
|
||||||
echo "❌ Could not locate mux binary after npm install"
|
echo "❌ Could not locate mux binary after $PM_CMD install"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
chmod +x "$CANDIDATE" || true
|
chmod +x "$CANDIDATE" || true
|
||||||
ln -sf "$CANDIDATE" "$MUX_BINARY"
|
ln -sf "$CANDIDATE" "$MUX_BINARY"
|
||||||
else
|
else
|
||||||
echo "📥 npm not found; downloading tarball from npm registry..."
|
echo "📥 No package manager found; downloading tarball from registry..."
|
||||||
VERSION_TO_USE="${VERSION}"
|
VERSION_TO_USE="${VERSION}"
|
||||||
if [ -z "$VERSION_TO_USE" ]; then
|
if [ -z "$VERSION_TO_USE" ]; then
|
||||||
VERSION_TO_USE="next"
|
VERSION_TO_USE="next"
|
||||||
fi
|
fi
|
||||||
META_URL="https://registry.npmjs.org/mux/$VERSION_TO_USE"
|
META_URL="${REGISTRY_URL}/mux/$VERSION_TO_USE"
|
||||||
META_JSON="$(curl -fsSL "$META_URL" || true)"
|
META_JSON="$(curl -fsSL "$META_URL" || true)"
|
||||||
if [ -z "$META_JSON" ]; then
|
if [ -z "$META_JSON" ]; then
|
||||||
echo "❌ Failed to fetch npm metadata: $META_URL"
|
echo "❌ Failed to fetch npm metadata: $META_URL"
|
||||||
@ -136,7 +171,7 @@ if [ ! -f "$MUX_BINARY" ] || [ "${USE_CACHED}" != true ]; then
|
|||||||
echo "❌ Could not determine version for mux"
|
echo "❌ Could not determine version for mux"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
TARBALL_URL="https://registry.npmjs.org/mux/-/mux-$VERSION_TO_USE.tgz"
|
TARBALL_URL="${REGISTRY_URL}/mux/-/mux-$VERSION_TO_USE.tgz"
|
||||||
fi
|
fi
|
||||||
TMP_DIR="$(mktemp -d)"
|
TMP_DIR="$(mktemp -d)"
|
||||||
TAR_PATH="$TMP_DIR/mux.tgz"
|
TAR_PATH="$TMP_DIR/mux.tgz"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user