lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit d0449cc33e3b75d4d1c9d35efa66a2f361a52fab
parent e2abc88d25d831dc499cbbd19f57a23cf62249fe
Author: triesap <tyson@radroots.org>
Date:   Sat, 21 Mar 2026 17:53:15 +0000

xtask: capture export test failures

- replace inherited cargo test stderr with captured command output
- return compact failure details for ts-rs export crate runs
- assert the captured syntax error context in the synthetic failure test
- keep nix run .#contract logs free of fake workspace crate noise

Diffstat:
Mcrates/xtask/src/export_ts.rs | 44+++++++++++++++++++++++++++++++++++++++-----
1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/crates/xtask/src/export_ts.rs b/crates/xtask/src/export_ts.rs @@ -6,7 +6,7 @@ use sha2::{Digest, Sha256}; use std::collections::BTreeMap; use std::fs; use std::path::{Path, PathBuf}; -use std::process::Command; +use std::process::{Command, Output}; #[derive(Serialize)] struct ExportManifest { @@ -165,6 +165,35 @@ fn copy_dir_contents(src: &Path, dst: &Path) -> Result<usize, String> { Ok(copied) } +fn summarize_command_output(output: &[u8]) -> Option<String> { + let lines = String::from_utf8_lossy(output) + .lines() + .map(str::trim) + .filter(|line| !line.is_empty()) + .map(ToOwned::to_owned) + .collect::<Vec<_>>(); + if lines.is_empty() { + return None; + } + let keep = lines.len().saturating_sub(8); + Some(lines[keep..].join(" | ")) +} + +fn cargo_test_failure(crate_name: &str, output: &Output) -> String { + let status = output + .status + .code() + .map(|code| format!("exit code {code}")) + .unwrap_or_else(|| "terminated by signal".to_string()); + let stderr = summarize_command_output(&output.stderr); + let stdout = summarize_command_output(&output.stdout); + match (stderr, stdout) { + (Some(stderr), _) => format!("cargo test failed for {crate_name} ({status}): {stderr}"), + (None, Some(stdout)) => format!("cargo test failed for {crate_name} ({status}): {stdout}"), + (None, None) => format!("cargo test failed for {crate_name} ({status})"), + } +} + fn collect_manifest_entries( root: &Path, current: &Path, @@ -438,7 +467,7 @@ fn generate_ts_rs_sources_with_selector( .unwrap_or(package_name); let export_dir = source_root.join(package_dir); let _ = fs::create_dir_all(&export_dir); - let status = Command::new("cargo") + let output = Command::new("cargo") .arg("test") .arg("-q") .arg("-p") @@ -447,9 +476,13 @@ fn generate_ts_rs_sources_with_selector( .arg("ts-rs") .env("RADROOTS_TS_RS_EXPORT_DIR", &export_dir) .current_dir(workspace_root) - .status(); - if !status.is_ok_and(|status| status.success()) { - return Err(format!("cargo test failed for {crate_name}")); + .output(); + let output = match output { + Ok(output) => output, + Err(e) => return Err(format!("run cargo test for {crate_name}: {e}")), + }; + if !output.status.success() { + return Err(cargo_test_failure(crate_name, &output)); } } Ok(source_root) @@ -1343,6 +1376,7 @@ manifest_file = "nested/export-manifest.json" let command_fail_err = generate_ts_rs_sources(&root_command_fail) .expect_err("cargo test failure should surface"); assert!(command_fail_err.contains("cargo test failed for radroots-a")); + assert!(command_fail_err.contains("unclosed delimiter")); let _ = fs::remove_dir_all(root_command_fail); }