Skip to content

Commit

Permalink
feat!: added MISE_OVERRIDE_CONFIG_FILENAMES config (#3266)
Browse files Browse the repository at this point in the history
Before this change, MISE_DEFAULT_CONFIG_FILENAME and MISE_DEFAULT_TOOL_VERSIONS_FILENAME accomplished 2 things where it should only have been doing one.
These commands both ignored "mise.toml"/".tool-versions" (but only that one filename) if set and also changed the default location for commands like `mise use` to write to.

This made it so you could not set MISE_DEFAULT_CONFIG_FILENAME=.mise.local.toml if you always want to use that file without also ignoring any "mise.toml" files.

This change adds 2 new env vars, MISE_OVERRIDE_CONFIG_FILENAMES and MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES which can be arrays of filenames. If these are set, mise will not load any local filenames (globals are still loaded, use MISE_CONFIG_FILE to change that) and instead mise will use those filenames. For the common pattern of just wanting to ignore .tool-versions you can set MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES=none

Fixes #1901

BREAKING CHANGE:
This causes mise to start reading mise.toml if MISE_DEFAULT_CONFIG_FILENAME was set previously which it did not before.

This change also changes the behavior slightly for writing new config files. Before it was not consistent across commands like `mise settings -l` and `mise use` but now it will use the following order if no file exists and it needs to create one:

- if MISE_DEFAULT_CONFIG_FILENAME is set, create that
- if MISE_OVERRIDE_CONFIG_FILENAMES has anything, use the first.
- if MISE_ENV is set, create "mise.$MISE_ENV.toml"
- else, create "mise.toml"

If you have not been using any of these env vars nothing should change.
  • Loading branch information
jdx authored Nov 28, 2024
1 parent a443aa0 commit 5a0508f
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 51 deletions.
5 changes: 4 additions & 1 deletion docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export default defineConfig({
items: [
{ text: "mise.toml", link: "/configuration" },
{ text: "Settings", link: "/configuration/settings" },
{
text: "Configuration Environments",
link: "/configuration/environments",
},
],
},
{
Expand Down Expand Up @@ -92,7 +96,6 @@ export default defineConfig({
text: "Environments",
items: [
{ text: "Environment variables", link: "/environments/" },
{ text: "Profiles", link: "/profiles" },
{ text: "direnv", link: "/direnv" },
],
},
Expand Down
7 changes: 7 additions & 0 deletions docs/cli/use.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ Installs a tool and adds the version it to mise.toml.
This will install the tool version if it is not already installed.
By default, this will use a `mise.toml` file in the current directory.

In the following order:

- If `MISE_DEFAULT_CONFIG_FILENAME` is set, it will use that instead.
- If `MISE_OVERRIDE_CONFIG_FILENAMES` is set, it will the first from that list.
- If `MISE_ENV` is set, it will use a `mise.<env>.toml` instead.
- Otherwise just "mise.toml"

Use the `--global` flag to use the global config file instead.

## Arguments
Expand Down
30 changes: 10 additions & 20 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
Notes:

- Paths which start with `mise` can be dotfiles, e.g.: `mise.toml` or `.mise/config.toml`.
- This list doesn't include [Profiles](/profiles) which allow for environment-specific config files like `mise.development.toml`—set with `MISE_PROFILE=development`.
- This list doesn't include [Configuration Environments](/configuration/environments) which allow for environment-specific config files like `mise.development.toml`—set with `MISE_ENV=development`.
- See [`LOCAL_CONFIG_FILENAMES` in `src/config/mod.rs`](https://github.com/jdx/mise/blob/main/src/config/mod.rs) for the actual code for these paths and their precedence. Some legacy paths are not listed here for brevity.

These files recurse upwards, so if you have a `~/src/work/myproj/mise.toml` file, what is defined
Expand Down Expand Up @@ -77,7 +77,7 @@ Then when inside of `~/src/myproj/backend`, `node` will be `18`, `python` will b
will be `3.1`. You can check the active versions with `mise ls --current`.

You can also have environment specific config files like `.mise.production.toml`, see
[Profiles](/profiles) for more details.
[Configuration Environments](/configuration/environments) for more details.

### `[tools]` - Dev tools

Expand Down Expand Up @@ -291,6 +291,14 @@ See [Tasks](/tasks/) for the full list of configuration options.

## Environment variables

::: tip
Normally environment variables in mise are used to set [settings](/configuration/settings) so most
environment variables are in that doc. The following are environment variables that are not settings.

A setting in mise is generally something that can be configured either as an environment variable
or set in a config file.
:::

mise can also be configured via environment variables. The following options are available:

### `MISE_DATA_DIR`
Expand Down Expand Up @@ -328,24 +336,6 @@ Default: `$MISE_CONFIG_DIR/config.toml` (Usually ~/.config/mise/config.toml)

This is the path to the config file.

### `MISE_DEFAULT_TOOL_VERSIONS_FILENAME`

Set to something other than ".tool-versions" to have mise look for `.tool-versions` files but with
a different name.

### `MISE_DEFAULT_CONFIG_FILENAME`

Set to something other than `.mise.toml` to have mise look for `.mise.toml` config files with a
different name.

### `MISE_PROFILE`

Enables profile-specific config files such as `.mise.development.toml`.
Use this for different env vars or different tool versions in
development/staging/production environments. See
[Profiles](/profiles) for more on how
to use this feature.

### `MISE_ENV_FILE`

Set to a filename to read from env from a dotenv file. e.g.: `MISE_ENV_FILE=.env`.
Expand Down
25 changes: 12 additions & 13 deletions docs/profiles.md → docs/configuration/environments.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
# Profiles
# Config Environments

It's possible to have separate `mise.toml` files in the same directory for different
environments like `development` and `production`. To enable, either set the `-P,--profile` option or `MISE_PROFILE` environment
variable to an environment like `development` or `production`. mise will then look for a `mise.{MISE_PROFILE}.toml` file
environments like `development` and `production`. To enable, either set the `-E,--env` option or `MISE_ENV` environment
variable to an environment like `development` or `production`. mise will then look for a `mise.{MISE_ENV}.toml` file
in the current directory, parent directories and the `MISE_CONFIG_DIR` directory.

mise will also look for "local" files like `mise.local.toml` and `mise.{MISE_PROFILE}.local.toml`
mise will also look for "local" files like `mise.local.toml` and `mise.{MISE_ENV}.local.toml`
in the current directory and parent directories.
These are intended to not be committed to version control.
(Add `mise.local.toml` and `mise.*.local.toml` to your `.gitignore` file.)

The priority of these files goes in this order (top overrides bottom):

- `mise.{MISE_PROFILE}.local.toml`
- `mise.{MISE_ENV}.local.toml`
- `mise.local.toml`
- `mise.{MISE_PROFILE}.toml`
- `mise.{MISE_ENV}.toml`
- `mise.toml`

You can also use paths like `mise/config.{MISE_PROFILE}.toml` or `.config/mise.{MISE_PROFILE}.toml` Those rules
follow the order in [Configuration](./configuration.md).
If `MISE_OVERRIDE_CONFIG_FILENAMES` is set, that will be used instead of all of this.

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).

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

::: warning
Note that currently modifying `MISE_DEFAULT_CONFIG_FILENAME` to something other than `mise.toml`
will not work with this feature. For now, it will disable it entirely. This may change in the
future.
:::
The rules around which file is written are different because we ultimately need to choose one. See
the docs for [`mise use`](/cli/use.html) for more information.
10 changes: 8 additions & 2 deletions mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -1485,12 +1485,18 @@ See https://usage.jdx.dev for more information on this specification."
}
cmd "use" help="Installs a tool and adds the version it to mise.toml." {
alias "u"
long_help r"Installs a tool and adds the version it to mise.toml.
long_help r#"Installs a tool and adds the version it to mise.toml.

This will install the tool version if it is not already installed.
By default, this will use a `mise.toml` file in the current directory.

Use the `--global` flag to use the global config file instead."
In the following order:
- If `MISE_DEFAULT_CONFIG_FILENAME` is set, it will use that instead.
- If `MISE_OVERRIDE_CONFIG_FILENAMES` is set, it will the first from that list.
- If `MISE_ENV` is set, it will use a `mise.<env>.toml` instead.
- Otherwise just "mise.toml"

Use the `--global` flag to use the global config file instead."#
after_long_help r"Examples:

# set the current version of node to 20.x in mise.toml of current directory
Expand Down
30 changes: 30 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,24 @@
"description": "Use color in mise terminal output",
"type": "boolean"
},
"config_file": {
"description": "Path to the global mise config file. Default is `~/.config/mise/config.toml`. This must be an env var.",
"type": "string"
},
"debug": {
"description": "Sets log level to debug",
"type": "boolean"
},
"default_config_filename": {
"default": "mise.toml",
"description": "The default config filename read. `mise use` and other commands that create new config files will use this value. This must be an env var.",
"type": "string"
},
"default_tool_versions_filename": {
"default": ".tool-versions",
"description": "The default .tool-versions filename read. `mise use` and other commands that write to new config files will use this if asdf_compat=1. This must be an env var.",
"type": "string"
},
"disable_backends": {
"default": [],
"description": "Backends to disable such as `asdf` or `pipx`",
Expand Down Expand Up @@ -377,6 +391,22 @@
}
}
},
"override_config_filenames": {
"default": [],
"description": "If set, mise will ignore default config files like `mise.toml` and use these filenames instead. This must be an env var.",
"type": "array",
"items": {
"type": "string"
}
},
"override_tool_versions_filename": {
"default": [],
"description": "If set, mise will ignore .tool-versions files and use these filename instead. Can be set to `none` to disable .tool-versions. This must be an env var.",
"type": "array",
"items": {
"type": "string"
}
},
"paranoid": {
"description": "Enables extra-secure behavior.",
"type": "boolean"
Expand Down
39 changes: 39 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,30 @@ type = "Bool"
default = true
description = "Use color in mise terminal output"

[config_file]
env = "MISE_CONFIG_FILE"
type = "Path"
optional = true
description = "Path to the global mise config file. Default is `~/.config/mise/config.toml`. This must be an env var."

[debug]
env = "MISE_DEBUG"
type = "Bool"
hide = true
description = "Sets log level to debug"

[default_config_filename]
env = "MISE_DEFAULT_CONFIG_FILENAME"
type = "String"
default = "mise.toml"
description = "The default config filename read. `mise use` and other commands that create new config files will use this value. This must be an env var."

[default_tool_versions_filename]
env = "MISE_DEFAULT_TOOL_VERSIONS_FILENAME"
type = "String"
default = ".tool-versions"
description = "The default .tool-versions filename read. `mise use` and other commands that write to new config files will use this if asdf_compat=1. This must be an env var."

[disable_backends]
env = "MISE_DISABLE_BACKENDS"
type = "ListString"
Expand Down Expand Up @@ -212,6 +230,13 @@ env = "MISE_ENV"
type = "String"
description = "Env to use for mise.<MISE_ENV>.toml files."
optional = true
docs = """
Enables profile-specific config files such as `.mise.development.toml`.
Use this for different env vars or different tool versions in
development/staging/production environments. See
[Configuration Environments](/configuration/environments) for more on how
to use this feature.
"""

[env_file]
env = "MISE_ENV_FILE"
Expand Down Expand Up @@ -469,6 +494,20 @@ mise use -g bun
```
"""

[override_config_filenames]
env = "MISE_OVERRIDE_CONFIG_FILENAMES"
type = "ListString"
default = []
description = "If set, mise will ignore default config files like `mise.toml` and use these filenames instead. This must be an env var."
parse_env = "list_by_colon"

[override_tool_versions_filename]
env = "MISE_OVERRIDE_TOOL_VERSIONS_FILENAME"
type = "ListString"
default = []
description = "If set, mise will ignore .tool-versions files and use these filename instead. Can be set to `none` to disable .tool-versions. This must be an env var."
parse_env = "list_by_colon"

[paranoid]
env = "MISE_PARANOID"
type = "Bool"
Expand Down
10 changes: 8 additions & 2 deletions src/cli/use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use path_absolutize::Absolutize;

use crate::cli::args::{BackendArg, ToolArg};
use crate::config::config_file::ConfigFile;
use crate::config::{config_file, is_global_config, Config, LOCAL_CONFIG_FILENAMES, SETTINGS};
use crate::config::{config_file, is_global_config, Config, DEFAULT_CONFIG_FILENAMES, SETTINGS};
use crate::env::{
MISE_DEFAULT_CONFIG_FILENAME, MISE_DEFAULT_TOOL_VERSIONS_FILENAME, MISE_GLOBAL_CONFIG_FILE,
};
Expand All @@ -23,6 +23,12 @@ use crate::{config, env, file};
/// This will install the tool version if it is not already installed.
/// By default, this will use a `mise.toml` file in the current directory.
///
/// In the following order:
/// - If `MISE_DEFAULT_CONFIG_FILENAME` is set, it will use that instead.
/// - If `MISE_OVERRIDE_CONFIG_FILENAMES` is set, it will the first from that list.
/// - If `MISE_ENV` is set, it will use a `mise.<env>.toml` instead.
/// - Otherwise just "mise.toml"
///
/// Use the `--global` flag to use the global config file instead.
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, visible_alias = "u", after_long_help = AFTER_LONG_HELP)]
Expand Down Expand Up @@ -244,7 +250,7 @@ fn config_file_from_dir(p: &Path) -> PathBuf {
if !p.is_dir() {
return p.to_path_buf();
}
let filenames = LOCAL_CONFIG_FILENAMES
let filenames = DEFAULT_CONFIG_FILENAMES
.iter()
.map(|f| f.to_string())
.collect::<Vec<_>>();
Expand Down
7 changes: 7 additions & 0 deletions src/config/config_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,14 @@ fn trust_file_hash(path: &Path) -> eyre::Result<bool> {
fn detect_config_file_type(path: &Path) -> Option<ConfigFileType> {
match path.file_name().unwrap().to_str().unwrap() {
f if f.ends_with(".toml") => Some(ConfigFileType::MiseToml),
f if env::MISE_OVERRIDE_CONFIG_FILENAMES.contains(f) => Some(ConfigFileType::MiseToml),
f if env::MISE_DEFAULT_CONFIG_FILENAME.as_str() == f => Some(ConfigFileType::MiseToml),
f if env::MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES
.as_ref()
.is_some_and(|o| o.contains(f)) =>
{
Some(ConfigFileType::ToolVersions)
}
f if env::MISE_DEFAULT_TOOL_VERSIONS_FILENAME.as_str() == f => {
Some(ConfigFileType::ToolVersions)
}
Expand Down
20 changes: 12 additions & 8 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
use std::sync::{Arc, OnceLock, RwLock};

use eyre::{ensure, eyre, Context, Result};
use indexmap::IndexMap;
use indexmap::{IndexMap, IndexSet};
use itertools::Itertools;
use once_cell::sync::{Lazy, OnceCell};
use rayon::prelude::*;
Expand Down Expand Up @@ -619,16 +619,18 @@ fn load_idiomatic_files() -> BTreeMap<String, Vec<String>> {
idiomatic_filenames
}

pub static LOCAL_CONFIG_FILENAMES: Lazy<Vec<&'static str>> = Lazy::new(|| {
if *env::MISE_DEFAULT_CONFIG_FILENAME == "mise.toml" {
vec![
static LOCAL_CONFIG_FILENAMES: Lazy<IndexSet<&'static str>> = Lazy::new(|| {
if env::MISE_OVERRIDE_CONFIG_FILENAMES.is_empty() {
[
".tool-versions",
&*env::MISE_DEFAULT_TOOL_VERSIONS_FILENAME, // .tool-versions
".config/mise/config.toml",
".config/mise.toml",
".mise/config.toml",
"mise/config.toml",
".mise/config.toml",
".rtx.toml",
"mise.toml",
&*env::MISE_DEFAULT_CONFIG_FILENAME, // mise.toml
".mise.toml",
".config/mise/config.local.toml",
Expand All @@ -638,11 +640,13 @@ pub static LOCAL_CONFIG_FILENAMES: Lazy<Vec<&'static str>> = Lazy::new(|| {
"mise.local.toml",
".mise.local.toml",
]
.into_iter()
.collect()
} else {
vec![
&*env::MISE_DEFAULT_TOOL_VERSIONS_FILENAME,
&*env::MISE_DEFAULT_CONFIG_FILENAME,
]
env::MISE_OVERRIDE_CONFIG_FILENAMES
.iter()
.map(|s| s.as_str())
.collect()
}
});
pub static DEFAULT_CONFIG_FILENAMES: Lazy<Vec<String>> = Lazy::new(|| {
Expand Down
10 changes: 8 additions & 2 deletions src/config/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ impl Settings {
.to_string_lossy();
// if the file doesn't exist or is actually a .tool-versions config
if !global_config.exists()
|| env::MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES
.as_ref()
.is_some_and(|f| f.contains(&filename.to_string()))
|| filename == *env::MISE_DEFAULT_TOOL_VERSIONS_FILENAME
|| filename == ".tool-versions"
{
Expand Down Expand Up @@ -295,8 +298,11 @@ impl Settings {
.iter()
.filter(|p| {
let filename = p.file_name().unwrap_or_default().to_string_lossy();
filename != *env::MISE_DEFAULT_TOOL_VERSIONS_FILENAME
&& filename != ".tool-versions"
env::MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES
.as_ref()
.is_some_and(|f| f.contains(&filename.to_string()))
|| filename != *env::MISE_DEFAULT_TOOL_VERSIONS_FILENAME
&& filename != ".tool-versions"
})
.map(Self::parse_settings_file)
.chain(once(Self::config_settings()))
Expand Down
Loading

0 comments on commit 5a0508f

Please sign in to comment.