mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-12 23:02:41 +00:00
fix: preserve file path in config parse errors and fix test assertion
The error standardization lost the file path from parse error messages when anyhow::Context was removed. Add path field to ParseSettings variant so errors like "Failed to parse settings file at /path: ..." include the file location. Also fix test that expected capitalized "Workflow not found" to match the new lowercase error message. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1802a61963
commit
dd44220bc3
3 changed files with 36 additions and 13 deletions
|
|
@ -436,10 +436,10 @@ fn settings_local_workflow_name_applies_run_overlay_and_deep_merges() {
|
|||
|
||||
// checkpoint.exclude_globs is a security/policy list: replace by default.
|
||||
let checkpoint = run_checkpoint(&cfg);
|
||||
assert_eq!(checkpoint.exclude_globs, vec![
|
||||
"run-only".to_string(),
|
||||
"shared".to_string()
|
||||
]);
|
||||
assert_eq!(
|
||||
checkpoint.exclude_globs,
|
||||
vec!["run-only".to_string(), "shared".to_string()]
|
||||
);
|
||||
|
||||
// Hooks: id-based replacement. The "shared" hook appears in both cli and
|
||||
// workflow layers and resolves to the workflow entry; project and run-only
|
||||
|
|
@ -529,9 +529,10 @@ fn settings_local_explicit_workflow_path_uses_workflow_project_layers() {
|
|||
assert!(auto_approve_enabled(&cfg));
|
||||
// v2 R30: run.prepare.steps replaces the whole ordered list across layers.
|
||||
// The highest-precedence layer (workflow) wins.
|
||||
assert_eq!(run_prepare_commands(&cfg), vec![
|
||||
"workflow-setup".to_string()
|
||||
]);
|
||||
assert_eq!(
|
||||
run_prepare_commands(&cfg),
|
||||
vec!["workflow-setup".to_string()]
|
||||
);
|
||||
assert_eq!(run_sandbox(&cfg).preserve, Some(true));
|
||||
}
|
||||
|
||||
|
|
@ -644,7 +645,7 @@ fn settings_missing_run_config_errors() {
|
|||
assert!(String::from_utf8_lossy(&output.stdout).trim().is_empty());
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(
|
||||
stderr.contains("error: Workflow not found:"),
|
||||
stderr.contains("workflow not found:"),
|
||||
"stderr should report missing workflow path, got:\n{stderr}"
|
||||
);
|
||||
assert!(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use toml::de::Error as TomlError;
|
||||
|
||||
use crate::parse::ParseError;
|
||||
use crate::resolve::ResolveError;
|
||||
|
||||
|
|
@ -11,6 +13,13 @@ fn format_resolve_errors(errors: &[ResolveError]) -> String {
|
|||
.join("\n")
|
||||
}
|
||||
|
||||
fn format_path_suffix(path: Option<&PathBuf>) -> String {
|
||||
match path {
|
||||
Some(p) => format!(" at {}", p.display()),
|
||||
None => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("reading config file {path}: {source}")]
|
||||
|
|
@ -20,9 +29,10 @@ pub enum Error {
|
|||
source: std::io::Error,
|
||||
},
|
||||
|
||||
#[error("{context}: {source}")]
|
||||
#[error("{context}{}: {source}", format_path_suffix(.path.as_ref()))]
|
||||
ParseSettings {
|
||||
context: &'static str,
|
||||
path: Option<PathBuf>,
|
||||
#[source]
|
||||
source: ParseError,
|
||||
},
|
||||
|
|
@ -31,7 +41,7 @@ pub enum Error {
|
|||
TomlParse {
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: toml::de::Error,
|
||||
source: TomlError,
|
||||
},
|
||||
|
||||
#[error("{context}:\n{}", format_resolve_errors(.errors))]
|
||||
|
|
@ -67,10 +77,22 @@ impl Error {
|
|||
}
|
||||
|
||||
pub fn parse(context: &'static str, source: ParseError) -> Self {
|
||||
Self::ParseSettings { context, source }
|
||||
Self::ParseSettings {
|
||||
context,
|
||||
path: None,
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toml_parse(path: &Path, source: toml::de::Error) -> Self {
|
||||
pub fn parse_file(context: &'static str, path: &Path, source: ParseError) -> Self {
|
||||
Self::ParseSettings {
|
||||
context,
|
||||
path: Some(path.to_path_buf()),
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toml_parse(path: &Path, source: TomlError) -> Self {
|
||||
Self::TomlParse {
|
||||
path: path.to_path_buf(),
|
||||
source,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::{Error, Result, project, user};
|
|||
pub fn load_settings_path(path: &Path) -> Result<SettingsLayer> {
|
||||
let content = std::fs::read_to_string(path).map_err(|source| Error::read_file(path, source))?;
|
||||
let mut layer = parse_settings_layer(&content)
|
||||
.map_err(|err| Error::parse("Failed to parse settings file", err))?;
|
||||
.map_err(|err| Error::parse_file("Failed to parse settings file", path, err))?;
|
||||
let base_dir = path.parent().unwrap_or_else(|| Path::new("."));
|
||||
resolve_goal_file_paths(&mut layer, base_dir);
|
||||
Ok(layer)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue