diff --git a/src/config/user/mod.rs b/src/config/user/mod.rs index e567d421d..d503cc03c 100644 --- a/src/config/user/mod.rs +++ b/src/config/user/mod.rs @@ -78,16 +78,16 @@ pub use sections::{ /// identifies which layer failed so callers can emit targeted diagnostics /// (file errors with line/col vs env-var attribution). /// -/// Strict loading treats the first issue as fatal; best-effort -/// [`UserConfig::load_with_warnings()`] returns all issues alongside the -/// usable config. +/// Strict loading treats the first issue other than a rejected env-var +/// override as fatal; best-effort [`UserConfig::load_with_warnings()`] +/// returns all issues alongside the usable config. #[derive(Debug)] pub enum LoadError { /// A file parser failed, retaining its source and raw diagnosis. File(super::ConfigParseError), - /// Config files parsed cleanly; applying env-var overrides failed. - /// `vars` lists the exact `WORKTRUNK_*` env vars that were parsed - /// as `(name, value)` pairs. + /// An env-var override setting was rejected; other settings' overrides + /// may still apply. `vars` lists the `WORKTRUNK_*` env vars forming the + /// rejected setting as `(name, value)` pairs. Env { err: String, vars: Vec<(String, String)>, @@ -675,10 +675,18 @@ impl UserConfig { /// Like [`load()`](Self::load), but returns a [`LoadError`] that /// distinguishes file-level parse failures (with line/col) from - /// env-var override failures. + /// `--config-set` and validation failures. + /// + /// A rejected env-var override is not an error: like the tolerant load, + /// the setting falls back to the file layers and the other overrides + /// still apply. Its warning is emitted at startup by the user-config + /// prewarm, so every command reports it the same way. pub(crate) fn load_with_cause() -> Result { let (config, warnings) = Self::load_with_warnings(); - if let Some(err) = warnings.into_iter().next() { + if let Some(err) = warnings + .into_iter() + .find(|warning| !matches!(warning, LoadError::Env { .. })) + { return Err(err); } Ok(config) diff --git a/tests/integration_tests/eval.rs b/tests/integration_tests/eval.rs index 7a0859878..da0abf4c8 100644 --- a/tests/integration_tests/eval.rs +++ b/tests/integration_tests/eval.rs @@ -15,22 +15,21 @@ fn test_eval_branch(repo: TestRepo) { )); } -/// A strict command keeps the invalid override's diagnosis once in its fatal -/// block, independently of the earlier tolerant-load warning. +/// A command skips an invalid env override the way `wt list` does: the +/// startup warning names it once, and the command still runs. #[rstest] -fn test_eval_invalid_env_override_keeps_one_fatal_diagnosis(repo: TestRepo) { +fn test_eval_skips_invalid_env_override(repo: TestRepo) { repo.write_test_config("[list]\nbranches = true\n"); let mut cmd = repo.wt_command(); cmd.env("WORKTRUNK__LIST__BRANCHES", "not-a-bool") .args(["step", "eval", "{{ branch }}"]); let output = cmd.output().unwrap(); - assert_eq!(output.status.code(), Some(1)); - assert!(output.stdout.is_empty()); + assert!(output.status.success(), "{output:?}"); + assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "main"); let stderr = String::from_utf8_lossy(&output.stderr); let stderr = stderr.ansi_strip(); - let (_, fatal) = stderr.split_once("✗ Failed to load config").unwrap(); - assert_eq!(fatal.matches("invalid type:").count(), 1, "{stderr}"); + assert_eq!(stderr.matches("invalid type:").count(), 1, "{stderr}"); let settings = crate::common::setup_snapshot_settings(&repo); settings.bind(|| insta::assert_snapshot!(stderr)); diff --git a/tests/snapshots/integration__integration_tests__eval__eval_invalid_env_override_keeps_one_fatal_diagnosis.snap b/tests/snapshots/integration__integration_tests__eval__eval_skips_invalid_env_override.snap similarity index 67% rename from tests/snapshots/integration__integration_tests__eval__eval_invalid_env_override_keeps_one_fatal_diagnosis.snap rename to tests/snapshots/integration__integration_tests__eval__eval_skips_invalid_env_override.snap index 2b96a44b5..eb10cbaf3 100644 --- a/tests/snapshots/integration__integration_tests__eval__eval_invalid_env_override_keeps_one_fatal_diagnosis.snap +++ b/tests/snapshots/integration__integration_tests__eval__eval_skips_invalid_env_override.snap @@ -5,6 +5,3 @@ expression: stderr ▲ Ignoring env var overrides: WORKTRUNK__LIST__BRANCHES=not-a-bool invalid type: string "not-a-bool", expected a boolean in `list.branches` -✗ Failed to load config - invalid type: string "not-a-bool", expected a boolean - in `list.branches`