feat(preflight): show spinner while server runs checks

`fabro preflight` blocks on a single server-side `run_preflight` call.
Without feedback the terminal sits blank until it returns. Mirror the
existing `fabro doctor` spinner (cyan braille, "Running checks...",
80ms tick), gated on `!ctx.json_output()` so JSON and piped callers
stay clean. The network calls run inside an inline async block so the
spinner is `finish_and_clear`ed before any `?`-propagated error
prints.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-04-29 14:41:05 -04:00
parent 9c09694d3b
commit fa2cb2a839
No known key found for this signature in database

View file

@ -30,8 +30,30 @@ pub(crate) async fn execute(
run_id: None,
user_settings_path: Some(active_settings_path(None)),
})?;
let client = ctx.server().await?;
let response = client.run_preflight(manifest.manifest).await?;
let spinner = if ctx.json_output() {
None
} else {
let spinner = indicatif::ProgressBar::new_spinner();
spinner.set_style(
indicatif::ProgressStyle::with_template("{spinner:.cyan} {msg}")
.expect("valid template")
.tick_strings(&["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏", ""]),
);
spinner.set_message("Running checks...");
spinner.enable_steady_tick(std::time::Duration::from_millis(80));
Some(spinner)
};
let result = async {
let client = ctx.server().await?;
client.run_preflight(manifest.manifest).await
}
.await;
if let Some(spinner) = spinner.as_ref() {
spinner.finish_and_clear();
}
let response = result?;
let diagnostics = api_diagnostics_to_local(&response.workflow.diagnostics);
if ctx.json_output() {