|
| 1 | +#!/bin/sh |
| 2 | +# |
| 3 | +# scripts/ci/ci-summary.sh |
| 4 | +# |
| 5 | +# Wrapped awk script that reads the test record file and emits a markdown |
| 6 | +# summary to stdout, intended for piping into $GITHUB_STEP_SUMMARY. |
| 7 | +# |
| 8 | + |
| 9 | +set -eu |
| 10 | + |
| 11 | +file=${1:-${CI_TEST_RECORD_FILE:-build/tests/results.tsv}} |
| 12 | + |
| 13 | +if [ ! -s "$file" ]; then |
| 14 | + echo "## Test results" |
| 15 | + echo |
| 16 | + echo "_No results recorded._" |
| 17 | + exit 0 |
| 18 | +fi |
| 19 | + |
| 20 | +awk -F'\t' ' |
| 21 | +{ |
| 22 | + key = $1 "\t" $2 |
| 23 | + cat[key] = $1 |
| 24 | + name[key] = $2 |
| 25 | + status[key] = $3 |
| 26 | + logf[key] = $4 |
| 27 | + seen[key] = NR # last-wins |
| 28 | +} |
| 29 | +END { |
| 30 | + # Per-category counts |
| 31 | + for (k in seen) { |
| 32 | + c = cat[k] |
| 33 | + cats[c] = 1 |
| 34 | + if (status[k] == "PASS") { cat_pass[c]++; total_pass++ } |
| 35 | + else if (status[k] == "FAIL") { cat_fail[c]++; total_fail++ } |
| 36 | + total++ |
| 37 | + } |
| 38 | +
|
| 39 | + # Header |
| 40 | + printf("## Test results\n\n") |
| 41 | + if (total_fail > 0) { |
| 42 | + printf("**%d / %d passed** (%d failed)\n\n", total_pass, total, total_fail) |
| 43 | + } else { |
| 44 | + printf("**%d / %d passed**\n\n", total_pass, total) |
| 45 | + } |
| 46 | +
|
| 47 | + # Failure logs as collapsible blocks |
| 48 | + if (total_fail > 0) { |
| 49 | + printf("### Failure logs (last 20 lines)\n\n") |
| 50 | + for (k in seen) { |
| 51 | + if (status[k] != "FAIL") continue |
| 52 | + printf("<details><summary><code>%s/%s</code> — <code>%s</code></summary>\n\n", |
| 53 | + cat[k], name[k], (logf[k] != "" ? logf[k] : "(no log captured)")) |
| 54 | + if (logf[k] != "") { |
| 55 | + printf("```\n") |
| 56 | + n = 0 |
| 57 | + while ((getline line < logf[k]) > 0) buf[++n % 20] = line |
| 58 | + close(logf[k]) |
| 59 | + start = (n < 20) ? 1 : n - 19 |
| 60 | + for (j = start; j <= n; j++) print buf[j % 20] |
| 61 | + delete buf |
| 62 | + printf("```\n") |
| 63 | + } else { |
| 64 | + printf("_No log file recorded._\n") |
| 65 | + } |
| 66 | + printf("\n</details>\n\n") |
| 67 | + } |
| 68 | + printf("---\n\n") |
| 69 | + } |
| 70 | +
|
| 71 | + # Per-category sections. Categories with failures float to the top |
| 72 | + # via a single insertion sort; otherwise alphabetical. |
| 73 | + n = 0 |
| 74 | + for (c in cats) ordered[++n] = c |
| 75 | + for (i = 2; i <= n; i++) { |
| 76 | + cur = ordered[i]; j = i - 1 |
| 77 | + while (j >= 1) { |
| 78 | + a = ordered[j]; b = cur |
| 79 | + af = (cat_fail[a] ? 0 : 1); bf = (cat_fail[b] ? 0 : 1) |
| 80 | + if (af < bf || (af == bf && a < b)) break |
| 81 | + ordered[j+1] = ordered[j]; j-- |
| 82 | + } |
| 83 | + ordered[j+1] = cur |
| 84 | + } |
| 85 | +
|
| 86 | + for (i = 1; i <= n; i++) { |
| 87 | + c = ordered[i] |
| 88 | + cp = cat_pass[c] + 0; cf = cat_fail[c] + 0 |
| 89 | + ct = cp + cf |
| 90 | + if (cf > 0) printf("### %s (%d/%d, %d failed)\n\n", c, cp, ct, cf) |
| 91 | + else printf("### %s (%d/%d)\n\n", c, cp, ct) |
| 92 | + printf("| Test | Status |\n|---|---|\n") |
| 93 | + # FAIL rows first, then PASS, each in test-execution order. |
| 94 | + for (k in seen) if (cat[k] == c && status[k] == "FAIL") emit(k) |
| 95 | + for (k in seen) if (cat[k] == c && status[k] == "PASS") emit(k) |
| 96 | + printf("\n") |
| 97 | + } |
| 98 | +} |
| 99 | +
|
| 100 | +function emit(k) { |
| 101 | + printf("| `%s` | %s |\n", name[k], status[k]) |
| 102 | +} |
| 103 | +' "$file" |
0 commit comments