CI: render a test report table in the GitHub job summary #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| # 每次 push 到 main 或開 PR 時,自動跑 repo 內所有 Makefile 的測試。 | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| workflow_dispatch: | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| # 安裝 uv(Python 測試用 `uv run python` 跑,符合專案慣例) | |
| # 專案沒有 uv.lock / requirements,關掉 cache 避免無效快取警告 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: false | |
| # gcc / g++ 在 ubuntu-latest 已預裝;顯示版本方便除錯 | |
| - name: Show toolchain versions | |
| run: | | |
| g++ --version | |
| gcc --version | |
| make --version | head -1 | |
| uv --version | |
| # 掃描每個 Makefile,挑最適合的 target(有 test 就 make test;否則 run;再否則 make), | |
| # 解析每個套件的「All N tests passed」,寫成 Markdown 表格到 Job Summary。 | |
| - name: Run all Makefile tests | |
| run: | | |
| set -uo pipefail | |
| summary="${GITHUB_STEP_SUMMARY:-/dev/stdout}" | |
| { | |
| echo "## 🧪 Test Report" | |
| echo "" | |
| echo "| Suite | Target | Result | Status |" | |
| echo "|-------|--------|--------|--------|" | |
| } >> "$summary" | |
| overall=0; total_tests=0; total_suites=0; found=0 | |
| while IFS= read -r mk; do | |
| found=1 | |
| dir=$(dirname "$mk"); dir=${dir#./} | |
| if grep -qE '^test:' "$mk"; then target=test | |
| elif grep -qE '^run:' "$mk"; then target=run | |
| else target=build; fi | |
| echo "::group::$dir ($target)" | |
| if [ "$target" = build ]; then | |
| out=$(make -C "$dir" 2>&1); rc=$? | |
| else | |
| out=$(make -C "$dir" "$target" 2>&1); rc=$? | |
| fi | |
| echo "$out" | |
| echo "::endgroup::" | |
| [ "$rc" -ne 0 ] && overall=1 | |
| label=""; ran_any=0 | |
| while IFS= read -r line; do | |
| if [[ "$line" =~ ^===\ (.+)\ ===$ ]]; then | |
| label="${BASH_REMATCH[1]}" | |
| elif [[ "$line" =~ ^\./([^\ ]+) ]]; then | |
| [ -z "$label" ] && label="$dir → ${BASH_REMATCH[1]}" | |
| elif [[ "$line" =~ ^All\ ([0-9]+)\ tests\ passed$ ]]; then | |
| n="${BASH_REMATCH[1]}"; lbl="${label:-$dir}" | |
| echo "| \`$lbl\` | $target | $n passed | ✅ |" >> "$summary" | |
| label=""; ran_any=1 | |
| total_tests=$((total_tests + n)); total_suites=$((total_suites + 1)) | |
| fi | |
| done <<< "$out" | |
| if [ "$ran_any" -eq 0 ]; then | |
| if [ "$rc" -eq 0 ]; then | |
| echo "| \`$dir\` | $target | built & ran (smoke) | ✅ |" >> "$summary" | |
| else | |
| echo "| \`$dir\` | $target | FAILED | ❌ |" >> "$summary" | |
| fi | |
| total_suites=$((total_suites + 1)) | |
| elif [ "$rc" -ne 0 ]; then | |
| echo "| \`$dir\` | $target | make failed | ❌ |" >> "$summary" | |
| fi | |
| done < <(find . -name Makefile -not -path '*/node_modules/*' | sort) | |
| { | |
| echo "" | |
| if [ "$overall" -eq 0 ]; then | |
| echo "**Total: $total_tests tests across $total_suites suites — ✅ all passed**" | |
| else | |
| echo "**Total: $total_tests tests across $total_suites suites — ❌ failures above**" | |
| fi | |
| } >> "$summary" | |
| if [ "$found" -eq 0 ]; then echo "No Makefile found" >&2; exit 1; fi | |
| exit $overall |