maestro-cli/src/config.rs was two pass-throughs, a newtype error, a two-field projection of MaestroConfigFile, and one four-line or_else with a single caller. `resolve_daemon_url` moves onto MaestroConfigFile, next to the schema it reads, and the module goes; its tests move with it. `[web].dev_proxy_target` is deleted end to end — schema, env var, normalisation, three tests, README line, and the startup warning that admitted the server ignores it. MaestroConfigFile::save had no callers outside its own tests. Deleting it also removes every skip_serializing_if, the five is_empty impls, and the Serialize derives that existed only to make its output tidy. BroadcastTuning was a struct that was never instantiated: all three uses were `::DEFAULT.field` in const position and there is no [broadcast] section. Now two plain consts. $MAESTRO_CONFIG was honoured twice, by resolve_config_path and by clap's `env =`. Every binary already gets it through clap, so resolve_config_path and CONFIG_PATH_ENV go and the TUI falls back to default_config_path like everything else. Also collapses three layers of 1:1 forwarding: the umbrella's cli_dispatch shim, and four near-identical 8-line functions in cli/dispatch.rs that differed only in which run_* they called. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
63 lines
1.8 KiB
Rust
63 lines
1.8 KiB
Rust
//! `maestro-web` binary entry point. See `lib.rs` for the architecture.
|
|
|
|
use std::error::Error;
|
|
use std::path::PathBuf;
|
|
use std::process::ExitCode;
|
|
|
|
use clap::Parser;
|
|
use maestro_web::config::{default_config_path, EnvOverrides};
|
|
use maestro_web::{load_config, router};
|
|
use tokio::net::TcpListener;
|
|
use tracing_subscriber::EnvFilter;
|
|
|
|
#[derive(Debug, Parser)]
|
|
#[command(
|
|
name = "maestro-web",
|
|
version,
|
|
about = "Serves the Maestro web UI and reverse-proxies to a co-located maestrod"
|
|
)]
|
|
struct Cli {
|
|
/// Override the unified Maestro config-file path.
|
|
#[arg(long, env = "MAESTRO_CONFIG")]
|
|
config: Option<PathBuf>,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> ExitCode {
|
|
let cli = Cli::parse();
|
|
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
|
tracing_subscriber::fmt().with_env_filter(filter).init();
|
|
|
|
match run(cli.config).await {
|
|
Ok(()) => ExitCode::SUCCESS,
|
|
Err(e) => {
|
|
tracing::error!(error = %e, "maestro-web failed");
|
|
eprintln!("maestro-web: {e}");
|
|
ExitCode::FAILURE
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn run(config_override: Option<PathBuf>) -> Result<(), Box<dyn Error>> {
|
|
let path = match config_override {
|
|
Some(p) => p,
|
|
None => default_config_path()?,
|
|
};
|
|
let cfg = load_config(&path, EnvOverrides::from_env())?;
|
|
tracing::info!(
|
|
bind = %cfg.bind_addr,
|
|
daemon = %cfg.daemon_url,
|
|
"loaded config",
|
|
);
|
|
let router = router(&cfg)?;
|
|
let listener = TcpListener::bind(cfg.bind_addr).await?;
|
|
tracing::info!(addr = %listener.local_addr()?, "serving");
|
|
axum::serve(listener, router)
|
|
.with_graceful_shutdown(async {
|
|
let _ = tokio::signal::ctrl_c().await;
|
|
tracing::info!("ctrl-c received — shutting down");
|
|
})
|
|
.await?;
|
|
Ok(())
|
|
}
|