refactor(settings): resolve feature flags

This commit is contained in:
Bryan Helmkamp 2026-04-10 07:16:10 -04:00
parent e7d890bbf5
commit 7796c4d4e1
No known key found for this signature in database
7 changed files with 71 additions and 7 deletions

View file

@ -15,9 +15,9 @@ pub use config::ConfigLayer;
pub use fabro_util::path::expand_tilde;
pub use home::Home;
pub use resolve::{
ResolveError, resolve_cli, resolve_cli_from_file, resolve_project, resolve_project_from_file,
resolve_run, resolve_run_from_file, resolve_server, resolve_server_from_file, resolve_workflow,
resolve_workflow_from_file,
ResolveError, resolve_cli, resolve_cli_from_file, resolve_features, resolve_features_from_file,
resolve_project, resolve_project_from_file, resolve_run, resolve_run_from_file, resolve_server,
resolve_server_from_file, resolve_workflow, resolve_workflow_from_file,
};
pub use storage::{RunScratch, ServerState, Storage};

View file

@ -0,0 +1,12 @@
use fabro_types::settings::features::{FeaturesLayer, FeaturesSettings};
use super::ResolveError;
pub fn resolve_features(
layer: &FeaturesLayer,
_errors: &mut Vec<ResolveError>,
) -> FeaturesSettings {
FeaturesSettings {
session_sandboxes: layer.session_sandboxes.unwrap_or(false),
}
}

View file

@ -1,16 +1,19 @@
mod cli;
mod error;
mod features;
mod project;
mod run;
mod server;
mod workflow;
use fabro_types::settings::{
CliSettings, ProjectSettings, RunSettings, ServerSettings, SettingsFile, WorkflowSettings,
CliSettings, FeaturesSettings, ProjectSettings, RunSettings, ServerSettings, SettingsFile,
WorkflowSettings,
};
pub use cli::resolve_cli;
pub use error::ResolveError;
pub use features::resolve_features;
pub use project::resolve_project;
pub use run::resolve_run;
pub use server::resolve_server;
@ -51,6 +54,19 @@ pub fn resolve_project_from_file(
}
}
pub fn resolve_features_from_file(
file: &SettingsFile,
) -> Result<FeaturesSettings, Vec<ResolveError>> {
let mut errors = Vec::new();
let layer = file.features.as_ref().cloned().unwrap_or_default();
let resolved = resolve_features(&layer, &mut errors);
if errors.is_empty() {
Ok(resolved)
} else {
Err(errors)
}
}
pub fn resolve_run_from_file(file: &SettingsFile) -> Result<RunSettings, Vec<ResolveError>> {
let mut errors = Vec::new();
let layer = file.run.as_ref().cloned().unwrap_or_default();

View file

@ -0,0 +1,29 @@
use fabro_config::resolve_features_from_file;
use fabro_types::settings::SettingsFile;
#[test]
fn resolves_features_defaults_from_empty_settings() {
let settings = SettingsFile::default();
let features = resolve_features_from_file(&settings).expect("empty settings should resolve");
assert!(!features.session_sandboxes);
}
#[test]
fn resolves_session_sandboxes_flag() {
let settings: SettingsFile = fabro_config::ConfigLayer::parse(
r#"
_version = 1
[features]
session_sandboxes = true
"#,
)
.expect("fixture should parse")
.into();
let features = resolve_features_from_file(&settings).expect("features should resolve");
assert!(features.session_sandboxes);
}

View file

@ -147,8 +147,9 @@ fn json_response(status: StatusCode, body: serde_json::Value) -> Response {
}
fn features_json(settings: &SettingsFile) -> serde_json::Value {
let features = settings.features.as_ref();
let session_sandboxes = features.and_then(|f| f.session_sandboxes).unwrap_or(false);
let session_sandboxes = fabro_config::resolve_features_from_file(settings)
.map(|settings| settings.session_sandboxes)
.unwrap_or(false);
let retros = fabro_config::resolve_run_from_file(settings)
.map(|settings| settings.execution.retros)
.unwrap_or(false);

View file

@ -5,6 +5,12 @@
use serde::{Deserialize, Serialize};
/// A structurally resolved `[features]` view for consumers.
#[derive(Debug, Clone, Default, PartialEq)]
pub struct FeaturesSettings {
pub session_sandboxes: bool,
}
/// A sparse `[features]` layer as it appears in a single settings file.
///
/// Every field is an `Option<bool>` so layers can independently set or

View file

@ -30,7 +30,7 @@ pub use cli::{
CliUpdatesSettings,
};
pub use duration::{Duration, ParseDurationError};
pub use features::FeaturesLayer;
pub use features::{FeaturesLayer, FeaturesSettings};
pub use interp::{InterpString, Provenance, ResolveEnvError, Resolved};
pub use model_ref::{
AmbiguousModelRef, ModelRef, ModelRegistry, ParseModelRefError, ResolvedModelRef,