Skip to content

Commit 81623dd

Browse files
committed
[run-qemu] Replace jq script with a python script
embedded jq script is hard to maintain. This change does: - call a external script instead of having it embedded within the main run.sh one - convert it to python to make it easier to selectively handle how to format the content depending on the output (github step summary or console). the latter could be done by `jq` but this is becoming an escape-hell to get the content properly passed and handle by each individual component of the pipeline. https://gist.github.com/chantra/fcaf4847393dc98ffda82c4ba116eb2d Signed-off-by: Manu Bretelle <[email protected]>
1 parent 15ed51a commit 81623dd

File tree

3 files changed

+107
-31
lines changed

3 files changed

+107
-31
lines changed

run-qemu/fixtures/test_progs.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

run-qemu/print_test_summary.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/bin/python3
2+
# prints a summary of the tests to both the console and the job summary:
3+
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary
4+
#
5+
# To test the output of the GH test summary:
6+
# python3 run-qemu/print_test_summary.py -j run-qemu/fixtures/test_progs.json -s /dev/stderr > /dev/null
7+
# To test the output of the console:
8+
# python3 run-qemu/print_test_summary.py -j run-qemu/fixtures/test_progs.json -s /dev/stderr 2> /dev/null
9+
10+
import argparse
11+
import json
12+
13+
14+
def parse_args():
15+
parser = argparse.ArgumentParser()
16+
parser.add_argument(
17+
"-j",
18+
"--json-summary",
19+
required=True,
20+
metavar="FILE",
21+
help="test_progs's json summary file",
22+
)
23+
parser.add_argument(
24+
"-s",
25+
"--step-summary",
26+
required=True,
27+
metavar="FILE",
28+
help="Github step summary file",
29+
)
30+
parser.add_argument(
31+
"-a", "--append", action="store_true", help="Append to github step summary file"
32+
)
33+
return parser.parse_args()
34+
35+
36+
def notice(text: str) -> str:
37+
return f"::notice::{text}"
38+
39+
40+
def error(text: str) -> str:
41+
return f"::error::{text}"
42+
43+
44+
def markdown_summary(json_summary: json):
45+
return f"""- :heavy_check_mark: Success: {json_summary['success']}/{json_summary['success_subtest']}
46+
- :next_track_button: Skipped: ${json_summary['skipped']}
47+
- :x: Failed: {json_summary['failed']}"""
48+
49+
50+
def console_summary(json_summary: json):
51+
return f"Success: {json_summary['success']}/{json_summary['success_subtest']}, Skipped: {json_summary['skipped']}, Failed: {json_summary['failed']}"
52+
53+
54+
def log_gh_summary(file, text: str):
55+
print(text, file=file)
56+
57+
58+
def log_console(text: str):
59+
print(text)
60+
61+
62+
def group(text: str, title: str = "", error: bool = False) -> str:
63+
if error and title:
64+
title = f"\033[1;31mError:\033[0m {title}"
65+
return f"""::group::{title}
66+
{text}
67+
::endgroup::"""
68+
69+
70+
def test_error_console_log(test_error: str, test_message: str) -> str:
71+
error_msg = error(test_error)
72+
if test_message:
73+
error_msg += "\n" + test_message.strip()
74+
return group(error_msg, title=test_error, error=True)
75+
else:
76+
return error_msg
77+
78+
79+
if __name__ == "__main__":
80+
args = parse_args()
81+
step_open_mode = "a" if args.append else "w"
82+
json_summary = None
83+
84+
with open(args.json_summary, "r") as f:
85+
json_summary = json.load(f)
86+
87+
with open(args.step_summary, step_open_mode) as f:
88+
log_gh_summary(f, "# Tests summary")
89+
log_gh_summary(f, markdown_summary(json_summary))
90+
91+
log_console(notice(console_summary(json_summary)))
92+
93+
for test in json_summary["results"]:
94+
test_name = test["name"]
95+
test_number = test["number"]
96+
if test["failed"]:
97+
test_log = f"#{test_number} {test_name}"
98+
log_gh_summary(f, test_log)
99+
log_console(test_error_console_log(test_log, test["message"]))
100+
101+
for subtest in test["subtests"]:
102+
if subtest["failed"]:
103+
subtest_log = f"#{test_number}/{subtest['number']} {test_name}/{subtest['name']}"
104+
log_gh_summary(f, subtest_log)
105+
log_console(test_error_console_log(subtest_log, subtest["message"]))

run-qemu/run.sh

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -111,37 +111,7 @@ then
111111
if [ $? ]
112112
then
113113
## Job summary
114-
echo "# Tests summary" >> "${GITHUB_STEP_SUMMARY}"
115-
read -r T_SUCCESS T_SUCCESS_SUBTEST T_SKIPPED T_FAILED < \
116-
<(jq -r < "${KERNEL_TEST}.json" '"\(.success) \(.success_subtest) \(.skipped) \(.failed)"')
117-
echo "- :heavy_check_mark: Success: ${T_SUCCESS}/${T_SUCCESS_SUBTEST}
118-
- :next_track_button: Skipped: ${T_SKIPPED}
119-
- :x: Failed: ${T_FAILED}" >> "${GITHUB_STEP_SUMMARY}"
120-
121-
summary_annotation="Success: ${T_SUCCESS}/${T_SUCCESS_SUBTEST}, Skipped: ${T_SKIPPED}, Failed: ${T_FAILED}"
122-
echo "::notice::${summary_annotation}"
123-
124-
# Print failed tests to summary/annotations
125-
if [ "${T_FAILED}" -gt 0 ]
126-
then
127-
echo "# Failed tests" >> "${GITHUB_STEP_SUMMARY}"
128-
jq -r < "${KERNEL_TEST}.json" \
129-
'.results | map([
130-
if .failed then "#\(.number) \(.name)" else empty end,
131-
(
132-
. as {name: $tname, number: $tnum} | .subtests | map(
133-
if .failed then "#\($tnum)/\(.number) \($tname)/\(.name)" else empty end
134-
)
135-
)
136-
]) | flatten | .[]' | \
137-
while read -r line
138-
do
139-
# Job summary
140-
echo "${line}" >> "${GITHUB_STEP_SUMMARY}"
141-
# Annotations
142-
echo "::error::${line}"
143-
done
144-
fi
114+
"${GITHUB_ACTION_PATH}/print_test_summary.py" -s "${GITHUB_STEP_SUMMARY}" -j "${KERNEL_TEST}.json"
145115
fi
146116
fi
147117
# Final summary - Don't use a fold, keep it visible

0 commit comments

Comments
 (0)