Compare commits

...

7 Commits

Author SHA1 Message Date
Ahmed Ibrahim
a5f77f2afe Vary preview Bazel test failures 2026-04-07 14:08:59 -07:00
Ahmed Ibrahim
d4f96eed79 Preview Bazel failed test log output 2026-04-07 14:08:59 -07:00
Ahmed Ibrahim
5a320ec2b0 Ask Bazel to print failed test errors 2026-04-07 14:08:25 -07:00
Ahmed Ibrahim
cbf9643069 Compact Bazel failure summary 2026-04-07 13:25:57 -07:00
Ahmed Ibrahim
5066eddf79 Aggregate Bazel test failure summaries 2026-04-07 13:01:20 -07:00
Ahmed Ibrahim
7970439736 Recap Bazel test failures after logs 2026-04-07 12:39:59 -07:00
Ahmed Ibrahim
7e64f4ed8a Show full failed Bazel test logs 2026-04-07 11:40:32 -07:00
7 changed files with 152 additions and 21 deletions

View File

@@ -65,44 +65,136 @@ case "${RUNNER_OS:-}" in
;;
esac
print_bazel_test_log_tails() {
print_failed_bazel_test_logs() {
local console_log="$1"
local testlogs_dir
local testlogs_dir=
local -a bazel_info_cmd=(bazel)
local rust_test_summary
rust_test_summary="$(mktemp)"
if (( ${#bazel_startup_args[@]} > 0 )); then
bazel_info_cmd+=("${bazel_startup_args[@]}")
fi
testlogs_dir="$(run_bazel "${bazel_info_cmd[@]:1}" info bazel-testlogs 2>/dev/null || echo bazel-testlogs)"
local failed_targets=()
while IFS= read -r target; do
failed_targets+=("$target")
local failed_target_logs=()
while IFS= read -r target_log; do
failed_target_logs+=("$target_log")
done < <(
grep -E '^FAIL: //' "$console_log" \
| sed -E 's#^FAIL: (//[^ ]+).*#\1#' \
| awk '{
target = $2
test_log = ""
if (match($0, /\(see [^)]*test\.log\)/)) {
test_log = substr($0, RSTART + 5, RLENGTH - 6)
}
if (!(target in test_logs) || test_logs[target] == "") {
test_logs[target] = test_log
}
}
END {
for (target in test_logs) {
print target "\t" test_logs[target]
}
}' \
| sort -u
)
if [[ ${#failed_targets[@]} -eq 0 ]]; then
if [[ ${#failed_target_logs[@]} -eq 0 ]]; then
echo "No failed Bazel test targets were found in console output."
rm -f "$rust_test_summary"
return
fi
for target in "${failed_targets[@]}"; do
local rel_path="${target#//}"
rel_path="${rel_path/:/\/}"
local test_log="${testlogs_dir}/${rel_path}/test.log"
echo
echo "Bazel failed test targets:"
for target_log in "${failed_target_logs[@]}"; do
local target="${target_log%%$'\t'*}"
echo " FAIL ${target}"
done
echo "::group::Bazel test log tail for ${target}"
for target_log in "${failed_target_logs[@]}"; do
local target="${target_log%%$'\t'*}"
local test_log="${target_log#*$'\t'}"
if [[ -z "$test_log" ]]; then
if [[ -z "$testlogs_dir" ]]; then
if (( ${#bazel_startup_args[@]} > 0 )); then
bazel_info_cmd+=("${bazel_startup_args[@]}")
fi
testlogs_dir="$(run_bazel "${bazel_info_cmd[@]:1}" info bazel-testlogs 2>/dev/null || echo bazel-testlogs)"
fi
local rel_path="${target#//}"
rel_path="${rel_path/:/\/}"
test_log="${testlogs_dir}/${rel_path}/test.log"
fi
echo
echo "FAIL ${target}"
echo "test log: ${test_log}"
echo
if [[ -f "$test_log" ]]; then
tail -n 200 "$test_log"
cat "$test_log"
awk -v target="$target" '
/^failures:$/ {
in_failures = 1
next
}
in_failures && /^ / {
print "F\t" target "\t" substr($0, 5)
next
}
in_failures && $0 !~ /^$/ {
in_failures = 0
}
/^test result: FAILED\./ {
line = $0
sub(/^test result: FAILED\. /, "", line)
sub(/; finished.*$/, "", line)
field_count = split(line, fields, "; ")
printf "T\t%s", target
for (i = 1; i <= field_count; i++) {
split(fields[i], parts, " ")
printf "\t%d", parts[1]
}
print ""
}
' "$test_log" >> "$rust_test_summary"
else
echo "Missing test log: $test_log"
fi
echo "::endgroup::"
done
echo
awk -F '\t' '
BEGIN {
print "Rust test failures:"
}
$1 == "F" {
saw_failure = 1
print " FAIL " $2 " " $3
}
$1 == "T" {
passed += $3
failed += $4
ignored += $5
measured += $6
filtered += $7
result_count += 1
}
END {
if (!saw_failure) {
print " No Rust test failure names found in test logs."
}
print ""
print "Rust test result totals across failed Bazel targets:"
if (result_count > 0) {
printf " %d passed; %d failed; %d ignored; %d measured; %d filtered out\n",
passed, failed, ignored, measured, filtered
} else {
print " No Rust test result totals found in test logs."
}
}
' "$rust_test_summary"
rm -f "$rust_test_summary"
}
bazel_args=()
@@ -272,7 +364,7 @@ fi
if [[ ${bazel_status:-0} -ne 0 ]]; then
if [[ $print_failed_bazel_test_logs -eq 1 ]]; then
print_bazel_test_log_tails "$bazel_console_log"
print_failed_bazel_test_logs "$bazel_console_log"
fi
exit "$bazel_status"
fi

View File

@@ -108,6 +108,7 @@ jobs:
"${bazel_wrapper_args[@]}" \
-- \
test \
--test_output=errors \
--test_tag_filters=-argument-comment-lint \
--test_verbose_timeout_warnings \
--build_metadata=COMMIT_SHA=${GITHUB_SHA} \

View File

@@ -56,3 +56,11 @@ pub fn ansi_escape(s: &str) -> Text<'static> {
},
}
}
#[cfg(test)]
mod preview_bazel_failed_logs_tests {
#[test]
fn preview_failed_log_from_ansi_escape() {
panic!("intentional preview failure: ansi-escape test log");
}
}

View File

@@ -565,4 +565,14 @@ mod tests {
assert!(description.contains("`setTimeout(callback: () => void, delayMs?: number)`"));
assert!(description.contains("`clearTimeout(timeoutId?: number)`"));
}
#[test]
fn preview_failed_log_from_code_mode() {
let actual = "code-mode actual preview value";
let expected = "code-mode expected preview value";
assert_eq!(
actual, expected,
"intentional preview failure: code-mode assertion diff"
);
}
}

View File

@@ -41,3 +41,9 @@ fn deserialize_skill_config_with_path_selector() {
}
);
}
#[test]
fn preview_failed_log_from_config() {
eprintln!("intentional preview stderr: config before panic");
panic!("intentional preview failure: config panic after stderr");
}

View File

@@ -67,6 +67,11 @@ fn test_invalid_bytes_still_fall_back_to_lossy() {
assert_eq!(decode_shell_output(bytes), String::from_utf8_lossy(bytes));
}
#[test]
fn preview_failed_log_from_protocol() -> Result<(), String> {
Err("intentional preview failure: protocol returned Result::Err".to_string())
}
fn decode_shell_output(bytes: &[u8]) -> String {
StreamOutput {
text: bytes.to_vec(),

View File

@@ -279,3 +279,12 @@ fn byte_count_conversion_clamps_non_positive_values() {
assert_eq!(approx_tokens_from_byte_count_i64(/*bytes*/ 0), 0);
assert_eq!(approx_tokens_from_byte_count_i64(/*bytes*/ 5), 2);
}
#[test]
fn preview_failed_log_from_output_truncation() {
let output = "output-truncation preview value";
assert!(
output.contains("truncated marker"),
"intentional preview failure: output-truncation predicate assertion"
);
}