Skip to content

Commit dc8f22d

Browse files
committed
Upload json files instead of json string
Signed-off-by: Hanxi Zhang <hanxizh@amazon.com>
1 parent cf81bc0 commit dc8f22d

4 files changed

Lines changed: 74 additions & 48 deletions

File tree

.github/actions/upload-test-failures/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: 'Upload Test Failures'
2-
description: 'Upload test-failures.json as artifact'
2+
description: 'Upload test failure artifacts'
33
inputs:
44
job-name:
55
description: 'Unique name for the artifact'
@@ -11,6 +11,6 @@ runs:
1111
uses: actions/upload-artifact@v4
1212
with:
1313
name: test-failures-${{ inputs.job-name }}
14-
path: test-failures.json
14+
path: test-failures/
1515
if-no-files-found: ignore
1616
retention-days: 7

.github/workflows/daily.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,24 +1985,24 @@ jobs:
19851985
import json, glob, os
19861986
19871987
merged = {}
1988-
for d in sorted(glob.glob("individual-failures/test-failures-*")):
1989-
job_name = os.path.basename(d).replace("test-failures-", "")
1990-
failures_file = os.path.join(d, "test-failures.json")
1991-
if os.path.exists(failures_file):
1992-
with open(failures_file) as f:
1988+
1989+
for job_dir in sorted(glob.glob("individual-failures/test-failures-*")):
1990+
job_name = os.path.basename(job_dir).replace("test-failures-", "")
1991+
merged[job_name] = {}
1992+
1993+
for suite_file in glob.glob(os.path.join(job_dir, "*.json")):
1994+
suite_name = os.path.splitext(os.path.basename(suite_file))[0]
1995+
with open(suite_file) as f:
19931996
data = json.load(f)
1994-
if data:
1995-
merged[job_name] = data
1996-
print(f"{job_name}: {len(data)} failure(s)")
1997+
merged[job_name][suite_name] = data
1998+
count = len(data)
1999+
if count:
2000+
print(f"{job_name}/{suite_name}: {count} failure(s)")
19972001
else:
1998-
print(f"{job_name}: no failures")
1999-
else:
2000-
print(f"{job_name}: no file found")
2002+
print(f"{job_name}/{suite_name}: no failures")
20012003
20022004
with open("all-test-failures.json", "w") as f:
20032005
json.dump(merged, f, indent=2)
2004-
2005-
print(f"\nTotal: {len(merged)} jobs with failures")
20062006
EOF
20072007
20082008
- name: Upload consolidated failures

.github/workflows/test-failure-detector.yml

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -121,25 +121,25 @@ jobs:
121121
122122
grouped = {}
123123
124-
for job_name, entries in all_failures.items():
125-
print(f"Processing: {job_name} ({len(entries)} failures)")
126-
for entry in entries:
127-
failure = parse_failure_entry(entry, job_name)
128-
name = f"{failure['test_name']} in {failure['test_file']}"
129-
130-
if name not in grouped:
131-
grouped[name] = {
132-
"name": name,
133-
"test_name": failure["test_name"],
134-
"test_file": failure["test_file"],
135-
"error": failure["error"],
136-
"jobs": []
137-
}
138-
grouped[name]["jobs"].append({
139-
"job": job_name,
140-
"url": job_urls.get(job_name, "")
141-
})
142-
print(f"{name} in {job_name}")
124+
for job_name, suites in all_failures.items():
125+
for suite_name, entries in suites.items():
126+
for entry in entries:
127+
name = f"{entry['test_name']} in {entry['test_file']}"
128+
129+
if name not in grouped:
130+
grouped[name] = {
131+
"name": name,
132+
"test_name": entry["test_name"],
133+
"test_file": entry["test_file"],
134+
"error": entry.get("error", ""),
135+
"jobs": []
136+
}
137+
grouped[name]["jobs"].append({
138+
"job": job_name,
139+
"suite": suite_name,
140+
"url": job_urls.get(job_name, "")
141+
})
142+
print(f"{name} in {job_name}/{suite_name}")
143143
144144
unique_failures = list(grouped.values())
145145
print(f"\nTotal unique failures: {len(unique_failures)}")

tests/test_helper.tcl

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -607,33 +607,59 @@ proc print_test_summary {} {
607607
puts "\nTest Summary: [colorstr bold-green $::ok_count] passed, [colorstr bold-red $::err_count] failed"
608608
}
609609

610+
proc write_test_failures {} {
611+
set failures {}
612+
foreach failed $::failed_tests {
613+
if {[string match {*\[*TIMEOUT*\]*} $failed]} continue
614+
if {[string match {*Sanitizer error*} $failed]} continue
615+
if {[string match {*Valgrind error*} $failed]} continue
616+
617+
set status "err"
618+
set test_name ""
619+
set test_file ""
620+
set error_msg ""
621+
622+
if {[regexp {\[(\w+)\]:\s*(.+?)\s+in\s+(tests/\S+\.tcl)\s*(.*)} $failed -> status test_name test_file error_msg]} {
623+
# Successfully parsed
624+
} else {
625+
set test_name $failed
626+
set test_file "unknown"
627+
set error_msg $failed
628+
}
629+
630+
set test_name [string map {"\\" "\\\\" "\"" "\\\"" "\n" "\\n" "\r" ""} $test_name]
631+
set test_file [string map {"\\" "\\\\" "\"" "\\\"" "\n" "\\n" "\r" ""} $test_file]
632+
set error_msg [string map {"\\" "\\\\" "\"" "\\\"" "\n" "\\n" "\r" ""} $error_msg]
633+
set status [string map {"\\" "\\\\" "\"" "\\\"" "\n" "\\n" "\r" ""} $status]
634+
635+
lappend failures "\{\"test_name\":\"$test_name\",\"test_file\":\"$test_file\",\"status\":\"$status\",\"error\":\"$error_msg\"\}"
636+
}
637+
638+
file mkdir "test-failures"
639+
set fp [open "test-failures/valkey.json" w]
640+
puts $fp "\[[join $failures ","]\]"
641+
close $fp
642+
}
643+
610644
proc the_end {} {
611-
# TODO: print the status, exit with the right exit code.
612645
puts "\n The End\n"
613646
puts "Execution time of different units:"
614647
foreach {time name} $::clients_time_history {
615648
puts " $time seconds - $name"
616649
}
617650
print_test_summary
651+
652+
# Write structured failures for automated detection
653+
if {[catch {write_test_failures} err]} {
654+
puts "Warning: Failed to write test failures: $err"
655+
}
656+
618657
if {[llength $::failed_tests]} {
619658
puts "\n[colorstr bold-red {!!! WARNING}] The following tests failed:\n"
620659
foreach failed $::failed_tests {
621660
puts "*** $failed"
622661
}
623662

624-
# Write failures to JSON file for automated detection
625-
set json_entries {}
626-
foreach failed $::failed_tests {
627-
if {[string match {*\[*TIMEOUT*\]*} $failed]} continue
628-
if {[string match {*Sanitizer error*} $failed]} continue
629-
if {[string match {*Valgrind error*} $failed]} continue
630-
set escaped [string map {"\\" "\\\\" "\"" "\\\"" "\n" "\\n" "\r" ""} $failed]
631-
lappend json_entries "\"$escaped\""
632-
}
633-
set fp [open "test-failures.json" w]
634-
puts $fp "\[[join $json_entries ","]\]"
635-
close $fp
636-
637663
if {!$::dont_clean} cleanup
638664
exit 1
639665
} else {

0 commit comments

Comments
 (0)