From 3c2399ecf6ea737ec875f201ad2f22eabf8eadbe Mon Sep 17 00:00:00 2001 From: alexion Date: Sat, 19 Sep 2026 16:58:27 -0400 Subject: [PATCH] feat(xatu): set CLI exit statuses --- src/xatu/BUILD | 11 +++++++ src/xatu/xatu_cli_test.sh | 65 +++++++++++++++++++++++++++++++++++++++ src/xatu/xatu_main.rs | 29 ++++++++++++----- 3 files changed, 97 insertions(+), 8 deletions(-) create mode 100755 src/xatu/xatu_cli_test.sh diff --git a/src/xatu/BUILD b/src/xatu/BUILD index dea31a6..dda8da0 100644 --- a/src/xatu/BUILD +++ b/src/xatu/BUILD @@ -41,6 +41,17 @@ rust_test( ], ) +sh_test( + name = "xatu_cli_test", + srcs = ["xatu_cli_test.sh"], + data = [ + ":xatu", + "testdata/clean.nix", + "testdata/invalid.nix", + "testdata/lint_findings.nix", + ], +) + rust_binary( name = "xatu", crate_name = "xatu_cli", diff --git a/src/xatu/xatu_cli_test.sh b/src/xatu/xatu_cli_test.sh new file mode 100755 index 0000000..e4b1e09 --- /dev/null +++ b/src/xatu/xatu_cli_test.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -euo pipefail + +xatu="$TEST_SRCDIR/$TEST_WORKSPACE/src/xatu/xatu" +fixture="$TEST_SRCDIR/$TEST_WORKSPACE/src/xatu/testdata" +tmp="${TEST_TMPDIR:-$(mktemp -d)}" + +cp "$fixture/clean.nix" "$tmp/clean.nix" +cp "$fixture/invalid.nix" "$tmp/invalid.nix" +cp "$fixture/lint_findings.nix" "$tmp/lint_findings.nix" + +run_xatu() { + local name="$1" + local expected_status="$2" + shift 2 + + set +e + "$xatu" "$@" >"$tmp/$name.stdout" 2>"$tmp/$name.stderr" + local actual_status="$?" + set -e + + if [[ "$actual_status" != "$expected_status" ]]; then + echo "expected $name to exit $expected_status, got $actual_status" >&2 + echo "stdout:" >&2 + cat "$tmp/$name.stdout" >&2 + echo "stderr:" >&2 + cat "$tmp/$name.stderr" >&2 + exit 1 + fi +} + +run_xatu clean 0 "$tmp/clean.nix" +if [[ "$(<"$tmp/clean.stdout")" != "No findings." ]]; then + echo "expected clean output to report no findings" >&2 + exit 1 +fi +if [[ -s "$tmp/clean.stderr" ]]; then + echo "expected clean stderr to be empty" >&2 + cat "$tmp/clean.stderr" >&2 + exit 1 +fi + +run_xatu findings 1 "$tmp/lint_findings.nix" +if ! grep -Fq "deprecated_to_path" "$tmp/findings.stdout"; then + echo "expected findings on stdout" >&2 + cat "$tmp/findings.stdout" >&2 + exit 1 +fi +if [[ -s "$tmp/findings.stderr" ]]; then + echo "expected findings stderr to be empty" >&2 + cat "$tmp/findings.stderr" >&2 + exit 1 +fi + +run_xatu fatal 2 "$tmp/invalid.nix" +if [[ -s "$tmp/fatal.stdout" ]]; then + echo "expected fatal stdout to be empty" >&2 + cat "$tmp/fatal.stdout" >&2 + exit 1 +fi +if ! grep -Fq "FailedPrecondition: failed to parse" "$tmp/fatal.stderr"; then + echo "expected fatal error on stderr" >&2 + cat "$tmp/fatal.stderr" >&2 + exit 1 +fi diff --git a/src/xatu/xatu_main.rs b/src/xatu/xatu_main.rs index 5c50fe8..7e43fac 100644 --- a/src/xatu/xatu_main.rs +++ b/src/xatu/xatu_main.rs @@ -1,7 +1,8 @@ use clap::Parser; use status::ResultExt; use std::path::{Path, PathBuf}; -use xatu::SourceFile; +use std::process::ExitCode; +use xatu::{Report, SourceFile}; fn is_nix_file(path: &Path) -> bool { path.extension().is_some_and(|extension| extension == "nix") @@ -66,9 +67,7 @@ struct Args { paths: Vec, } -fn main() -> status::Result<()> { - let args = Args::parse(); - +fn analyze(args: Args) -> status::Result { let paths: Vec = args .paths .into_iter() @@ -83,8 +82,22 @@ fn main() -> status::Result<()> { .flatten() .collect(); - let report = xatu::future_sight(files)?; - print!("{report}"); - - Ok(()) + xatu::future_sight(files) +} + +fn main() -> ExitCode { + match analyze(Args::parse()) { + Ok(report) if report.is_clean() => { + println!("No findings."); + ExitCode::SUCCESS + } + Ok(report) => { + print!("{report}"); + ExitCode::from(1) + } + Err(error) => { + eprintln!("{error}"); + ExitCode::from(2) + } + } }