fabro/lib/foundation/fabro-dev/src/lib.rs
2026-07-23 17:59:34 -04:00

80 lines
2.1 KiB
Rust

use std::process::ExitCode;
use anyhow::Result;
use clap::{Parser, Subcommand};
mod commands;
#[derive(Debug, Parser)]
#[command(
name = "fabro-dev",
version,
about = "Internal development tooling for Fabro"
)]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
/// Run the test suite N times and capture per-test timing to CSV.
BenchTests(commands::BenchTestsArgs),
/// Refresh embedded SPA assets and run cargo build.
Build(commands::BuildArgs),
/// Build Fabro Docker images with the release pipeline layout.
DockerBuild(commands::DockerBuildArgs),
/// Manage generated reference documentation.
Docs(commands::DocsArgs),
/// Run Fabro release automation.
Release(commands::ReleaseArgs),
/// Manage embedded Fabro web SPA assets.
Spa(commands::SpaArgs),
}
impl Command {
fn run(self) -> Result<()> {
match self {
Self::BenchTests(args) => commands::bench_tests(args),
Self::Build(args) => commands::build(args),
Self::DockerBuild(args) => commands::docker_build(args),
Self::Docs(args) => commands::docs(args),
Self::Release(args) => commands::release(args),
Self::Spa(args) => commands::spa(args),
}
}
}
pub fn run() -> ExitCode {
install_tracing();
match Cli::parse().command.run() {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
report_error(&error);
ExitCode::FAILURE
}
}
}
#[expect(
clippy::disallowed_methods,
reason = "dev CLI installs a process-global stderr tracing sink before command dispatch"
)]
fn install_tracing() {
let _ = tracing_subscriber::fmt()
.with_writer(std::io::stderr)
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.try_init();
}
#[expect(
clippy::print_stderr,
reason = "dev CLI reports final command errors to stderr"
)]
fn report_error(error: &anyhow::Error) {
eprintln!("fabro-dev failed");
for cause in error.chain() {
eprintln!(" caused by: {cause}");
}
}