// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. //! `fabrica config check` and `fabrica config show`. use std::path::Path; use std::process::ExitCode; use clap::Subcommand; /// Actions under `fabrica config`. #[derive(Debug, Subcommand)] pub(crate) enum ConfigCommand { /// Validate the effective configuration and exit non-zero on any error. Check, /// Print the effective, merged configuration with secrets redacted. Show, } /// Dispatch a `config` subcommand. /// /// Warnings are always written to stderr; on `check` they do not affect the exit /// status. A validation failure is reported to stderr and yields /// [`ExitCode::FAILURE`] without returning an `Err`, so no backtrace-style /// wrapper is printed for the expected "your config is wrong" case. pub(crate) fn run( command: &ConfigCommand, config_path: Option<&Path>, json: bool, ) -> anyhow::Result { match command { ConfigCommand::Check => match config::load(config_path) { Ok(loaded) => { warn(&loaded.warnings); println!("configuration ok"); Ok(ExitCode::SUCCESS) } Err(err) => { eprintln!("error: {err}"); Ok(ExitCode::FAILURE) } }, ConfigCommand::Show => { let loaded = config::load(config_path)?; warn(&loaded.warnings); if json { println!("{}", serde_json::to_string_pretty(&loaded.config)?); } else { print!("{}", loaded.config.to_toml_string()?); } Ok(ExitCode::SUCCESS) } } } /// Write each warning to stderr, prefixed, leaving stdout for real output. fn warn(warnings: &[String]) { for warning in warnings { eprintln!("warning: {warning}"); } }