@@ -416,6 +416,9 @@ jobs:
416416 name : Check job status
417417 if : always()
418418 runs-on : ubuntu-latest
419+ permissions :
420+ actions : read
421+ contents : read
419422 needs :
420423 - should-skip
421424 - detect-changes
@@ -426,6 +429,99 @@ jobs:
426429 - test-windows
427430 - doc
428431 steps :
432+ - name : Report universally-skipped tests
433+ env :
434+ GH_TOKEN : ${{ github.token }}
435+ run : |
436+ set -euo pipefail
437+
438+ REPO="${GITHUB_REPOSITORY}"
439+ SHA="${GITHUB_SHA}"
440+ WORKDIR=$(mktemp -d)
441+ trap 'rm -rf "${WORKDIR}"' EXIT
442+
443+ # Fetch all workflow runs associated with this commit (up to 100)
444+ all_runs=$(gh api \
445+ "repos/${REPO}/actions/runs?head_sha=${SHA}&per_page=100" \
446+ --jq '.workflow_runs[]')
447+
448+ # Identify child runs by their workflow file path; test-wheel-linux.yml
449+ # covers both linux-64 and linux-aarch64 (two separate runs).
450+ TEST_WORKFLOW_PATHS=(
451+ ".github/workflows/test-sdist-linux.yml"
452+ ".github/workflows/test-sdist-windows.yml"
453+ ".github/workflows/test-wheel-linux.yml"
454+ ".github/workflows/test-wheel-windows.yml"
455+ )
456+
457+ mkdir -p "${WORKDIR}/configs"
458+ config_index=0
459+
460+ for wf_path in "${TEST_WORKFLOW_PATHS[@]}"; do
461+ run_ids=$(echo "${all_runs}" | jq -r \
462+ --arg p "${wf_path}" \
463+ 'select(.path == $p) | .id')
464+ for run_id in ${run_ids}; do
465+ run_name=$(echo "${all_runs}" | jq -r \
466+ --argjson id "${run_id}" 'select(.id == $id) | .name' | head -1)
467+ echo "Fetching logs for: ${run_name} (id=${run_id})"
468+ config_dir="${WORKDIR}/configs/${config_index}"
469+ mkdir -p "${config_dir}"
470+
471+ if gh api "repos/${REPO}/actions/runs/${run_id}/logs" \
472+ > "${config_dir}/logs.zip" 2>/dev/null; then
473+ unzip -q "${config_dir}/logs.zip" -d "${config_dir}/logs" 2>/dev/null || true
474+ # Extract test IDs from lines matching the pytest SKIPPED output format
475+ grep -rh ' SKIPPED' "${config_dir}/logs/" 2>/dev/null \
476+ | grep -oE '[^[:space:]]+\.py::[^[:space:]]+ SKIPPED' \
477+ | sed 's/ SKIPPED$//' \
478+ | sort -u > "${config_dir}/skipped.txt" || true
479+ echo " -> $(wc -l < "${config_dir}/skipped.txt") skipped tests"
480+ config_index=$((config_index + 1))
481+ else
482+ echo " -> could not download logs (run may be skipped or unavailable)" >&2
483+ rm -rf "${config_dir}"
484+ fi
485+ done
486+ done
487+
488+ {
489+ echo "## Universally-skipped tests"
490+ echo ""
491+ } >> "${GITHUB_STEP_SUMMARY}"
492+
493+ if [[ ${config_index} -eq 0 ]]; then
494+ echo "_No test run logs found._" >> "${GITHUB_STEP_SUMMARY}"
495+ exit 0
496+ fi
497+
498+ # Start the intersection from the first config and progressively
499+ # narrow it down to only tests that appear in every config's list.
500+ cp "${WORKDIR}/configs/0/skipped.txt" "${WORKDIR}/intersection.txt"
501+ for i in $(seq 1 $((config_index - 1))); do
502+ comm -12 \
503+ "${WORKDIR}/intersection.txt" \
504+ "${WORKDIR}/configs/${i}/skipped.txt" \
505+ > "${WORKDIR}/intersection_new.txt"
506+ mv "${WORKDIR}/intersection_new.txt" "${WORKDIR}/intersection.txt"
507+ done
508+
509+ count=$(wc -l < "${WORKDIR}/intersection.txt")
510+ {
511+ echo "Tests skipped across all ${config_index} test configuration(s):"
512+ echo ""
513+ if [[ ${count} -eq 0 ]]; then
514+ echo "_No tests were skipped in all configurations._"
515+ else
516+ echo "| Test |"
517+ echo "| --- |"
518+ while IFS= read -r test; do
519+ [[ -z "${test}" ]] && continue
520+ echo "| \`${test}\` |"
521+ done < "${WORKDIR}/intersection.txt"
522+ fi
523+ } >> "${GITHUB_STEP_SUMMARY}"
524+
429525 - name : Exit
430526 run : |
431527 # if any dependencies were cancelled or failed, that's a failure
0 commit comments