Skip to content

Commit c5f4558

Browse files
bpamiriPeter Amiri
andauthored
ci: compat-matrix safe-slice hardening — zero-test guard, neutral soft-fail check, honest summary (#3366)
* ci: compat-matrix safe-slice hardening for #3302 Three workflow-plumbing fixes in compat-matrix.yml, shippable before the continue-on-error flip (which stays gated on PR #3365 merging plus one green dispatch on develop): - run-tests: per-leg zero-test guard — an HTTP 200/417 leg reporting totalSpecs below 4000 (suite runs ~4,700) now emits ::error:: and sets the leg fail flag, so a compile-wiped leg fails loudly instead of rendering as a pass. SOFT_FAIL_DBS is respected. - publish-results: fail_on: nothing on publish-unit-test-result-action, so oracle soft-fail debt stops pinning a red aggregate 'Wheels Test Results' check to innocent dispatch SHAs. Annotations, PR comments and artifacts are unchanged; leg gating stays in the tests job. - test-matrix-summary: zero-test legs render as ':warning: N tests' instead of a checkmark, soft-fail DB failures render as :warning:, and the Oracle column is annotated as soft-fail with a footnote. The rustcfml job is untouched (intentionally informational). Refs #3302 Signed-off-by: Peter Amiri <petera@pai.com> * ci: align per-engine summary with the zero-test guard Review follow-up for the #3302 safe slice: the per-engine step summary still rendered a compile-wiped leg (0 failures, 0 testcases) as a pass while the run-tests guard in the same job failed it with ::error::. Read totalSpecs alongside the failure count and render sub-floor legs as ':warning: N tests (zero-test guard)', mirroring the matrix grid. Refs #3302 Signed-off-by: Peter Amiri <petera@pai.com> --------- Signed-off-by: Peter Amiri <petera@pai.com> Co-authored-by: Peter Amiri <petera@pai.com>
1 parent 8bc8304 commit c5f4558

1 file changed

Lines changed: 73 additions & 16 deletions

File tree

.github/workflows/compat-matrix.yml

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -439,12 +439,40 @@ jobs:
439439
" || { echo "JUnit conversion failed for ${db} (non-fatal)"; rm -f "$JUNIT_FILE"; }
440440
fi
441441
442+
# Zero-test guard (#3302): a compile-wiped leg returns HTTP 200 with
443+
# totalSpecs=0 (one bad CFC zeroes the whole directory compile), which
444+
# previously rendered as a pass. Every engine runs the same core suite
445+
# (~4,700 specs), so anything below the floor means the suite never
446+
# actually ran. Revisit the floor if per-DB spec subsets ever ship.
447+
MIN_SPECS=4000
448+
TOTAL_SPECS="-1"
449+
if [ -f "$RESULT_FILE" ] && { [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "417" ]; }; then
450+
TOTAL_SPECS=$(python3 -c "
451+
import json, sys
452+
try:
453+
d = json.load(open('$RESULT_FILE'))
454+
print(int(d.get('totalSpecs', 0)))
455+
except:
456+
print(-1)
457+
" 2>/dev/null || echo "-1")
458+
fi
459+
460+
SPECS_OK=true
461+
if { [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "417" ]; } && [ "$TOTAL_SPECS" -lt "$MIN_SPECS" ]; then
462+
SPECS_OK=false
463+
echo "::error::${{ matrix.cfengine }} + ${db}: HTTP ${HTTP_CODE} but only ${TOTAL_SPECS} testcases reported (floor: ${MIN_SPECS}) — suite likely compile-wiped, treating leg as failed"
464+
fi
465+
442466
# Track per-database result
443-
if [ "$HTTP_CODE" = "200" ]; then
444-
echo "PASSED: ${{ matrix.cfengine }} + ${db}"
467+
if [ "$HTTP_CODE" = "200" ] && [ "$SPECS_OK" = true ]; then
468+
echo "PASSED: ${{ matrix.cfengine }} + ${db} (${TOTAL_SPECS} testcases)"
445469
DB_STATUS="pass"
446470
else
447-
echo "FAILED: ${{ matrix.cfengine }} + ${db} (HTTP ${HTTP_CODE})"
471+
if [ "$HTTP_CODE" = "200" ]; then
472+
echo "FAILED: ${{ matrix.cfengine }} + ${db} (HTTP 200 but zero-test guard tripped)"
473+
else
474+
echo "FAILED: ${{ matrix.cfengine }} + ${db} (HTTP ${HTTP_CODE})"
475+
fi
448476
DB_STATUS="fail"
449477
if echo "$SOFT_FAIL_DBS" | grep -qw "$db"; then
450478
echo "::warning::${db} tests failed but marked as soft-fail (non-blocking)"
@@ -486,6 +514,8 @@ jobs:
486514
echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY
487515
488516
SOFT_FAIL_DBS="oracle"
517+
# Keep in sync with MIN_SPECS in the run-tests step (#3302).
518+
MIN_SPECS=4000
489519
IFS=',' read -ra DBS <<< "${{ steps.db-list.outputs.databases }}"
490520
for db in "${DBS[@]}"; do
491521
RESULT_FILE="/tmp/test-results/${{ matrix.cfengine }}-${db}-result.txt"
@@ -494,18 +524,22 @@ jobs:
494524
IS_SOFT_FAIL=true
495525
fi
496526
if [ -f "$RESULT_FILE" ]; then
497-
# Check JSON for failures
498-
FAIL_COUNT=$(python3 -c "
527+
# Check JSON for failures and testcase count (zero-test guard, #3302)
528+
STATS=$(python3 -c "
499529
import json, sys
500530
try:
501531
d = json.load(open('$RESULT_FILE'))
502-
print(d.get('totalFail', 0) + d.get('totalError', 0))
532+
print(int(d.get('totalFail', 0) + d.get('totalError', 0)), int(d.get('totalSpecs', 0)))
503533
except:
504-
print(-1)
505-
" 2>/dev/null || echo "-1")
534+
print(-1, -1)
535+
" 2>/dev/null || echo "-1 -1")
536+
FAIL_COUNT="${STATS% *}"
537+
SPEC_COUNT="${STATS#* }"
506538
507-
if [ "$FAIL_COUNT" = "0" ]; then
539+
if [ "$FAIL_COUNT" = "0" ] && [ "$SPEC_COUNT" -ge "$MIN_SPECS" ]; then
508540
echo "| ${db} | :white_check_mark: Pass |" >> $GITHUB_STEP_SUMMARY
541+
elif [ "$FAIL_COUNT" = "0" ]; then
542+
echo "| ${db} | :warning: ${SPEC_COUNT} tests (zero-test guard) |" >> "$GITHUB_STEP_SUMMARY"
509543
elif [ "$FAIL_COUNT" = "-1" ] && [ "$IS_SOFT_FAIL" = true ]; then
510544
echo "| ${db} | :warning: Error (soft-fail) |" >> $GITHUB_STEP_SUMMARY
511545
elif [ "$FAIL_COUNT" = "-1" ]; then
@@ -613,6 +647,12 @@ jobs:
613647
files: junit-results/**/*.xml
614648
check_name: "Wheels Test Results"
615649
comment_title: "Wheels Test Results"
650+
# Keep the aggregate check neutral (#3302): oracle soft-fail debt
651+
# otherwise pins a red "Wheels Test Results" check to whatever SHA
652+
# the matrix was dispatched on, marking innocent PRs UNSTABLE.
653+
# Leg pass/fail gating lives in the tests job (OVERALL_STATUS);
654+
# annotations, PR comments, and artifacts are unaffected by this.
655+
fail_on: nothing
616656
report_individual_runs: true
617657
report_suite_logs: any
618658
json_file: junit-results/test-results.json
@@ -647,27 +687,41 @@ jobs:
647687
MATRIX_MD="${MATRIX_MD}
648688
"
649689
MATRIX_MD="${MATRIX_MD}
650-
| Engine | MySQL | PostgreSQL | SQL Server | H2 | CockroachDB | Oracle | SQLite |"
690+
| Engine | MySQL | PostgreSQL | SQL Server | H2 | CockroachDB | Oracle (soft-fail) | SQLite |"
651691
MATRIX_MD="${MATRIX_MD}
652-
|--------|:-----:|:----------:|:----------:|:--:|:-----------:|:------:|:------:|"
692+
|--------|:-----:|:----------:|:----------:|:--:|:-----------:|:------------------:|:------:|"
693+
694+
# Keep in sync with SOFT_FAIL_DBS and MIN_SPECS in the tests job (#3302).
695+
SOFT_FAIL_DBS="oracle"
696+
MIN_SPECS=4000
653697
654698
for engine in lucee6 lucee7 adobe2023 adobe2025 boxlang; do
655699
ROW="| **${engine}** |"
656700
for db in mysql postgres sqlserver h2 cockroachdb oracle sqlite; do
657701
FILE="results/test-results-${engine}/${engine}-${db}-result.txt"
702+
IS_SOFT_FAIL=false
703+
if echo "$SOFT_FAIL_DBS" | grep -qw "$db"; then
704+
IS_SOFT_FAIL=true
705+
fi
658706
if [ -f "$FILE" ]; then
659-
FAIL=$(python3 -c "
707+
STATS=$(python3 -c "
660708
import json, sys
661709
try:
662710
d = json.load(open('$FILE'))
663-
print(int(d.get('totalFail', 0) + d.get('totalError', 0)))
711+
print(int(d.get('totalFail', 0) + d.get('totalError', 0)), int(d.get('totalSpecs', 0)))
664712
except:
665-
print(-1)
666-
" 2>/dev/null || echo "-1")
667-
if [ "$FAIL" = "0" ]; then
713+
print(-1, -1)
714+
" 2>/dev/null || echo "-1 -1")
715+
FAIL="${STATS% *}"
716+
SPECS="${STATS#* }"
717+
if [ "$FAIL" = "0" ] && [ "$SPECS" -ge "$MIN_SPECS" ]; then
668718
ROW="${ROW} :white_check_mark: |"
669719
elif [ "$FAIL" = "-1" ]; then
670720
ROW="${ROW} :warning: |"
721+
elif [ "$FAIL" = "0" ]; then
722+
ROW="${ROW} :warning: ${SPECS} tests |"
723+
elif [ "$IS_SOFT_FAIL" = true ]; then
724+
ROW="${ROW} :warning: ${FAIL} |"
671725
else
672726
ROW="${ROW} :x: ${FAIL} |"
673727
fi
@@ -681,6 +735,9 @@ jobs:
681735
682736
MATRIX_MD="${MATRIX_MD}
683737
738+
*Oracle is soft-fail (non-blocking, tracked in #2663) — :warning: cells in that column never gate the run.*
739+
*A ':warning: N tests' cell means the leg reported fewer than ${MIN_SPECS} testcases (suite likely compile-wiped, counted as failed).*
740+
684741
*Results for commit ${GITHUB_SHA:0:7}.*"
685742
686743
# Write to step summary

0 commit comments

Comments
 (0)