From dfd1ac626c29c7d98b9ad2e9be2f161900ff1232 Mon Sep 17 00:00:00 2001 From: Taku Kodma <79110363+risu729@users.noreply.github.com> Date: Sat, 18 Apr 2026 05:34:26 +1000 Subject: [PATCH] fix(config): warn for deprecated env keys --- docs/environments/index.md | 5 +++ schema/mise.json | 6 ++-- src/config/config_file/mise_toml.rs | 49 ++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/docs/environments/index.md b/docs/environments/index.md index 37ed3e85bf..0a9b824495 100644 --- a/docs/environments/index.md +++ b/docs/environments/index.md @@ -315,6 +315,11 @@ TOML table for the configuration of these directives. In `mise.toml`: `env._.file` can be used to specify a [dotenv](https://dotenv.org) file to load. +::: warning +Top-level `env_file`, `dotenv`, and `env_path` are deprecated. Use `env._.file` and +`env._.path` instead. These keys will be removed in mise 2027.4.0. +::: + ```toml [env] _.file = '.env' diff --git a/schema/mise.json b/schema/mise.json index 64576ad2c3..4ebd640d37 100644 --- a/schema/mise.json +++ b/schema/mise.json @@ -3161,7 +3161,7 @@ ] }, "env_file": { - "description": "dotenv file(s) to load", + "description": "dotenv file(s) to load. Deprecated; use env._.file instead. This will be removed in mise 2027.4.0.", "deprecated": true, "oneOf": [ { @@ -3178,7 +3178,7 @@ ] }, "dotenv": { - "description": "dotenv file(s) to load", + "description": "dotenv file(s) to load. Deprecated; use env._.file instead. This will be removed in mise 2027.4.0.", "deprecated": true, "oneOf": [ { @@ -3195,7 +3195,7 @@ ] }, "env_path": { - "description": "PATH entries to add", + "description": "PATH entries to add. Deprecated; use env._.path instead. This will be removed in mise 2027.4.0.", "deprecated": true, "oneOf": [ { diff --git a/src/config/config_file/mise_toml.rs b/src/config/config_file/mise_toml.rs index 9653654ae1..5969952eef 100644 --- a/src/config/config_file/mise_toml.rs +++ b/src/config/config_file/mise_toml.rs @@ -38,6 +38,9 @@ use crate::{env, file}; use super::diagnostic::toml_parse_error; use super::{ConfigFileType, min_version::MinVersionSpec}; +const LEGACY_ENV_KEYS_DEPRECATED_WARN_AT: &str = "2026.4.17"; +const LEGACY_ENV_KEYS_DEPRECATED_REMOVE_AT: &str = "2027.4.0"; + /// Convert a `toml::Value` to a `toml_edit::Value` for serialization. fn toml_value_to_edit(v: toml::Value) -> Value { match v { @@ -79,8 +82,10 @@ pub struct MiseToml { context: TeraContext, #[serde(skip)] path: PathBuf, - #[serde(default, alias = "dotenv", deserialize_with = "deserialize_arr")] + #[serde(default, deserialize_with = "deserialize_arr")] env_file: Vec, + #[serde(default, deserialize_with = "deserialize_arr")] + dotenv: Vec, #[serde(default)] env: EnvList, #[serde(default, deserialize_with = "deserialize_arr")] @@ -250,6 +255,36 @@ impl MiseToml { .cloned() } + fn warn_deprecated_env_keys(&self) { + if !self.env_file.is_empty() { + deprecated_at!( + LEGACY_ENV_KEYS_DEPRECATED_WARN_AT, + LEGACY_ENV_KEYS_DEPRECATED_REMOVE_AT, + "config.env_file", + "`env_file` in {} is deprecated. Use `env._.file` instead.", + display_path(&self.path) + ); + } + if !self.dotenv.is_empty() { + deprecated_at!( + LEGACY_ENV_KEYS_DEPRECATED_WARN_AT, + LEGACY_ENV_KEYS_DEPRECATED_REMOVE_AT, + "config.dotenv", + "`dotenv` in {} is deprecated. Use `env._.file` instead.", + display_path(&self.path) + ); + } + if !self.env_path.is_empty() { + deprecated_at!( + LEGACY_ENV_KEYS_DEPRECATED_WARN_AT, + LEGACY_ENV_KEYS_DEPRECATED_REMOVE_AT, + "config.env_path", + "`env_path` in {} is deprecated. Use `env._.path` instead.", + display_path(&self.path) + ); + } + } + fn doc_mut(&self) -> eyre::Result>> { self.doc()?; Ok(self.doc.lock().unwrap()) @@ -518,6 +553,7 @@ impl ConfigFile for MiseToml { } fn env_entries(&self) -> eyre::Result> { + self.warn_deprecated_env_keys(); let env_entries = self.env.0.iter().cloned(); let path_entries = self .env_path @@ -527,6 +563,7 @@ impl ConfigFile for MiseToml { let env_files = self .env_file .iter() + .chain(&self.dotenv) .map(|p| EnvDirective::File(p.clone(), Default::default())) .collect_vec(); let all = path_entries @@ -929,6 +966,9 @@ impl Debug for MiseToml { if !self.env_file.is_empty() { d.field("env_file", &self.env_file); } + if !self.dotenv.is_empty() { + d.field("dotenv", &self.dotenv); + } if let Ok(env) = self.env_entries() && !env.is_empty() { @@ -955,6 +995,7 @@ impl Clone for MiseToml { context: self.context.clone(), path: self.path.clone(), env_file: self.env_file.clone(), + dotenv: self.dotenv.clone(), env: self.env.clone(), env_path: self.env_path.clone(), alias: self.alias.clone(), @@ -2223,6 +2264,12 @@ mod tests { dotenv = ".env" [env] _.file = ".env2" + "#}); + assert_debug_snapshot!(env, @r#""_.file = \".env\"\n_.file = \".env2\"""#); + + let env = parse_env(formatdoc! {r#" + env_file = ".env" + dotenv = ".env2" "#}); assert_debug_snapshot!(env, @r#""_.file = \".env\"\n_.file = \".env2\"""#); }