Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ Learn how to configure mise for your project with `mise.toml` files, environment
- `mise.toml`
- `mise/config.toml`
- `.mise/config.toml`
- `.mise/conf.d/*.toml` - all non-hidden TOML files in this directory will be loaded in alphabetical order
- `.mise/conf.d/*.toml` - non-hidden TOML fragments, loaded in alphabetical order; environment suffixes such as `tools.development.toml` load only when that environment is active
- `.config/mise.toml` - use this in order to group config files into a common directory
- `.config/mise/config.toml`
- `.config/mise/conf.d/*.toml` - all non-hidden TOML files in this directory will be loaded in alphabetical order
- `.config/mise/conf.d/*.toml` - the same fragment and environment-suffix behavior under the grouped config directory

::: tip
Run [`mise cfg`](/cli/config.html) to figure out what order mise is loading files on your particular setup. This is often
Expand Down
13 changes: 13 additions & 0 deletions docs/configuration/environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,19 @@ If `MISE_OVERRIDE_CONFIG_FILENAMES` is set, that will be used instead of all of
You can also use paths like `mise/config.{MISE_ENV}.toml` or `.config/mise.{MISE_ENV}.toml` Those rules
follow the order in [Configuration](/configuration).

Files in `.mise/conf.d` and `.config/mise/conf.d` use the same environment suffixes. This allows a
configuration to stay split into named fragments:

```text
.mise/conf.d/tools.toml # always loaded
.mise/conf.d/tools.local.toml # always loaded, usually gitignored
.mise/conf.d/tools.development.toml # MISE_ENV=development
.mise/conf.d/tools.development.local.toml # MISE_ENV=development, usually gitignored
```

An extra filename component before `.toml` is reserved for the environment, so use hyphens rather
than dots inside an unconditional fragment name: `node-tools.toml`, not `node.tools.toml`.

Use `mise config` to see which files are being used.

The rules around which file is written are different because we ultimately need to choose one. See
Expand Down
11 changes: 11 additions & 0 deletions e2e/config/test_config_auto_env
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ env.UNIX_LOADED = "1"' >mise.unix.toml
echo "env.AAA = \"$os\"" >"mise.$os.toml"
echo "env.AAA = \"$os-$arch\"" >"mise.$os-$arch.toml"
echo 'env.AAA = "prod"' >mise.prod.toml
mkdir -p .mise/conf.d
echo 'env.CONF_D_AUTO = "base"' >.mise/conf.d/00-base.toml
echo 'env.CONF_D_AUTO = "unix"' >.mise/conf.d/10-platform.unix.toml
echo "env.CONF_D_AUTO = \"$os\"" >".mise/conf.d/20-platform.$os.toml"
echo "env.CONF_D_AUTO = \"$os-$arch\"" >".mise/conf.d/30-platform.$os-$arch.toml"

# default: off, platform configs are not loaded
assert "mise env --json | jq -r .AAA" "base"
assert "mise env --json | jq -r .CONF_D_AUTO" "base"

# the rollout warning never fires once the user has set auto_env explicitly,
# regardless of the phase the current version is in (the version-gated unset
Expand All @@ -35,6 +41,7 @@ assert_not_contains "MISE_AUTO_ENV=true mise env 2>&1" "load automatically"
MISE_AUTO_ENV=true assert "mise env --json | jq -r .AAA" "$os-$arch"
MISE_AUTO_ENV=true assert "mise env --json | jq -r .UNIX_LOADED" "1"
MISE_AUTO_ENV=true assert "mise env --json | jq -r .BBB" "base"
MISE_AUTO_ENV=true assert "mise env --json | jq -r .CONF_D_AUTO" "$os-$arch"

# explicit MISE_ENV entries take precedence over auto platform envs
MISE_AUTO_ENV=true MISE_ENV=prod assert "mise env --json | jq -r .AAA" "prod"
Expand Down Expand Up @@ -66,6 +73,10 @@ rm -f .miserc.toml
# global config dir platform configs load too
mkdir -p "$MISE_CONFIG_DIR"
echo "env.GLOBAL_AUTO = \"$os\"" >"$MISE_CONFIG_DIR/config.$os.toml"
mkdir -p "$MISE_CONFIG_DIR/conf.d"
echo "env.GLOBAL_CONF_D_AUTO = \"$os\"" >"$MISE_CONFIG_DIR/conf.d/10-platform.$os.toml"
MISE_AUTO_ENV=true assert "mise env --json | jq -r .GLOBAL_AUTO" "$os"
MISE_AUTO_ENV=true assert "mise env --json | jq -r .GLOBAL_CONF_D_AUTO" "$os"
assert "mise env --json | jq -r .GLOBAL_AUTO" "null"
assert "mise env --json | jq -r .GLOBAL_CONF_D_AUTO" "null"
rm -f "$MISE_CONFIG_DIR/config.$os.toml"
55 changes: 55 additions & 0 deletions e2e/config/test_config_env
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,58 @@ MISE_ENV=test assert "mise ls dummy" "dummy 2.0.0 (missing) ~/workdir/mise.tes
MISE_ENV=ci assert "mise ls dummy" "dummy 3 (missing) ~/workdir/mise.ci.toml 3"
MISE_ENV=ci,test assert "mise ls dummy" "dummy 2.0.0 (missing) ~/workdir/mise.test.toml 2"
MISE_ENV=test,ci assert "mise ls dummy" "dummy 3 (missing) ~/workdir/mise.ci.toml 3"

# conf.d fragments follow the same environment and local filename conventions
mkdir -p .mise/conf.d
cat >.mise/conf.d/00-base.toml <<'EOF'
[env]
CONF_D_COMMON = "base"
CONF_D_ENV = "base"
EOF
cat >.mise/conf.d/01-local.local.toml <<'EOF'
[env]
CONF_D_ALWAYS_LOCAL = "local"
EOF
cat >.mise/conf.d/10-test.test.toml <<'EOF'
[env]
CONF_D_ENV = "test"
CONF_D_ENV_LOCAL = "test"
EOF
cat >.mise/conf.d/11-test-local.test.local.toml <<'EOF'
[env]
CONF_D_ENV_LOCAL = "test-local"
EOF
cat >.mise/conf.d/20-ci.ci.toml <<'EOF'
[env]
CONF_D_ENV = "ci"
EOF
cat >.mise/conf.d/99-inactive.inactive.toml <<'EOF'
[env]
CONF_D_INACTIVE = "loaded"
EOF

assert "mise env --json | jq -r '[.CONF_D_COMMON, .CONF_D_ENV, .CONF_D_ALWAYS_LOCAL, .CONF_D_INACTIVE] | @tsv'" $'base\tbase\tlocal\t'
MISE_ENV=test assert "mise env --json | jq -r '[.CONF_D_ENV, .CONF_D_ENV_LOCAL, .CONF_D_INACTIVE] | @tsv'" $'test\ttest-local\t'
MISE_ENV=test,ci assert "mise env --json | jq -r '[.CONF_D_ENV, .CONF_D_ENV_LOCAL] | @tsv'" $'ci\ttest-local'

# Environment names are matched literally and by the complete suffix after the first dot
cat >'.mise/conf.d/30-literal.qa*.toml' <<'EOF'
[env]
CONF_D_LITERAL = "literal"
EOF
cat >.mise/conf.d/31-unrelated.qa1.toml <<'EOF'
[env]
CONF_D_UNRELATED = "loaded"
EOF
cat >.mise/conf.d/40-dotted.qa.prod.toml <<'EOF'
[env]
CONF_D_DOTTED = "dotted"
EOF
cat >.mise/conf.d/41-prod.prod.toml <<'EOF'
[env]
CONF_D_PROD = "prod"
EOF

MISE_ENV='qa*' assert "mise env --json | jq -r '[.CONF_D_LITERAL, .CONF_D_UNRELATED] | @tsv'" $'literal\t'
MISE_ENV=prod assert "mise env --json | jq -r '[.CONF_D_DOTTED, .CONF_D_PROD] | @tsv'" $'\tprod'
MISE_ENV=qa.prod assert "mise env --json | jq -r '[.CONF_D_DOTTED, .CONF_D_PROD] | @tsv'" $'dotted\t'
12 changes: 12 additions & 0 deletions e2e/tasks/test_task_monorepo_mise_env
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ echo "FRONTEND_VAR=\$FRONTEND_VAR"
echo "ENV_VAR=\$ENV_VAR"
echo "DEV_VAR=\$DEV_VAR"
echo "PROD_VAR=\$PROD_VAR"
echo "DEV_CONF_D=\$DEV_CONF_D"
echo "PROD_CONF_D=\$PROD_CONF_D"
echo "ROOT_VAR=\$ROOT_VAR"
'''
EOF
Expand All @@ -54,6 +56,10 @@ ENV_VAR = "frontend_prod"
PROD_VAR = "frontend_prod_only"
EOF

mkdir -p projects/frontend/.mise/conf.d
echo 'env.DEV_CONF_D = "dev-conf-d"' >projects/frontend/.mise/conf.d/frontend.dev.toml
echo 'env.PROD_CONF_D = "prod-conf-d"' >projects/frontend/.mise/conf.d/frontend.prod.toml

# Create backend project
mkdir -p projects/backend
cat <<EOF >projects/backend/mise.toml
Expand Down Expand Up @@ -99,6 +105,8 @@ echo "$output"
assert_contains "echo '$output'" "ENV_VAR=frontend_default"
assert_contains "echo '$output'" "FRONTEND_VAR=frontend_value"
assert_contains "echo '$output'" "ROOT_VAR=root_value"
assert_not_contains "echo '$output'" "dev-conf-d"
assert_not_contains "echo '$output'" "prod-conf-d"

# Test 4: Frontend task with MISE_ENV=dev should load mise.dev.toml
echo "=== Test 4: Frontend task with MISE_ENV=dev ==="
Expand All @@ -112,6 +120,8 @@ assert_contains "echo '$output'" "DEV_VAR=frontend_dev_only"
assert_contains "echo '$output'" "ROOT_VAR=root_value"
# Should have FRONTEND_VAR from base frontend config
assert_contains "echo '$output'" "FRONTEND_VAR=frontend_value"
assert_contains "echo '$output'" "DEV_CONF_D=dev-conf-d"
assert_not_contains "echo '$output'" "prod-conf-d"

# Test 5: Frontend task with MISE_ENV=prod should load mise.prod.toml
echo "=== Test 5: Frontend task with MISE_ENV=prod ==="
Expand All @@ -121,6 +131,8 @@ echo "$output"
assert_contains "echo '$output'" "ENV_VAR=frontend_prod"
# Should load PROD_VAR from frontend/mise.prod.toml
assert_contains "echo '$output'" "PROD_VAR=frontend_prod_only"
assert_contains "echo '$output'" "PROD_CONF_D=prod-conf-d"
assert_not_contains "echo '$output'" "dev-conf-d"

# Test 6: Backend task with MISE_ENV=dev should load backend's dev config
echo "=== Test 6: Backend task with MISE_ENV=dev ==="
Expand Down
Loading
Loading