diff --git a/.github/workflows/coverage-refresh.yml b/.github/workflows/coverage-refresh.yml index 19000c23f6..88deff5a76 100644 --- a/.github/workflows/coverage-refresh.yml +++ b/.github/workflows/coverage-refresh.yml @@ -34,7 +34,10 @@ jobs: git config user.name "mfc-bot" git config user.email "mfc-bot@users.noreply.github.com" git add tests/coverage_map.json.gz - git commit -m "test: refresh coverage map [skip ci]" + # --no-verify: this bot commit stages only the binary coverage map; it + # must not run the repo pre-commit hook (./mfc.sh precheck/spelling), + # which is for source changes and aborts the commit on the runner. + git commit --no-verify -m "test: refresh coverage map [skip ci]" # Push to protected master via CACHE_PUSH_TOKEN (a PAT/App token with # contents:write + branch-protection bypass), mirroring deploy-tap.yml's # x-access-token push. The default GITHUB_TOKEN is rejected by protection. diff --git a/toolchain/mfc/test/test.py b/toolchain/mfc/test/test.py index 7d9dfbbb3a..f312a7cf49 100644 --- a/toolchain/mfc/test/test.py +++ b/toolchain/mfc/test/test.py @@ -230,7 +230,18 @@ def test(): if ARG("build_coverage_map"): from .coverage_build import build_coverage_map - all_cases = [b.to_case() for b in cases] + # Convergence tests are order-of-accuracy checks driven by convergence.py, + # which fills in grid resolution and patch geometry per refinement level at + # runtime. Their base params are skeletons (m=n=p=0, no geometry) that cannot + # run standalone, so the direct-invocation collector cannot map them. Exclude + # them: absent from the map, select_tests conservatively always-runs them + # (rung 5), which is the desired behavior for convergence checks anyway. + convergence = [b for b in cases if getattr(b, "kind", "golden") == "convergence"] + coverage_cases = [b for b in cases if getattr(b, "kind", "golden") != "convergence"] + if convergence: + cons.print(f"[yellow]Excluding {len(convergence)} convergence tests from the coverage map (always-run by design).[/yellow]") + + all_cases = [b.to_case() for b in coverage_cases] unique = set() for case, code in itertools.product(all_cases, [PRE_PROCESS, SIMULATION, POST_PROCESS]): slug = code.get_slug(case.to_input_file())