diff --git a/.asf.yaml b/.asf.yaml index 66d317fc..ba8f297d 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -161,16 +161,16 @@ github: # the PR. The daily schedule run still catches drift on # files the PR did not touch. - "lychee" - # Per-project pytest matrix from tests.yml. Mirrors the - # `matrix.project[].name` list there; keep these two - # lists in sync when projects are added or renamed. - - "pytest (oauth-draft)" - - "pytest (generate-cve-json)" - - "pytest (skill-validator)" - - "pytest (privacy-llm-checker)" - - "pytest (privacy-llm-redactor)" - - "pytest (vulnogram-oauth-api)" - - "pytest (sandbox-lint)" + # Per-project pytest matrix from tests.yml. Required via + # the single `tests-ok` umbrella job rather than the + # individual `pytest ()` matrix entries — branch + # protection and rulesets both require exact-match status + # check names, so listing matrix entries here would force + # an `.asf.yaml` change on every matrix add / rename / + # removal. `tests-ok` `needs:` every matrix entry and + # fails unless all succeed, so the gate semantics are the + # same. + - "tests-ok" # `required_pull_request_reviews:` deliberately omitted — see # the TEMPORARY POSTURE note above. Re-add at PMC formation. # diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8908be90..b3a2ca4a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -83,3 +83,31 @@ jobs: # needs because each project's `pyproject.toml` declares # `testpaths = ["tests"]` relative to its own root. run: uv run --directory ${{ matrix.project.path }} --group dev pytest --color=yes + + # Umbrella status check. `.asf.yaml`'s `required_status_checks` + # cannot use patterns or wildcards (GitHub's branch-protection and + # rulesets APIs both require exact context names), so a matrix job + # with N entries would otherwise force N `.asf.yaml` lines that + # must be kept in lock-step with the matrix. This single + # `tests-ok` job is the only pytest-related context required by + # branch protection — it passes iff every entry in the `pytest` + # matrix above passed. Adding, renaming, or removing matrix + # entries no longer touches `.asf.yaml`. + tests-ok: + name: tests-ok + runs-on: ubuntu-latest + needs: pytest + # `always()` — without it, this job would be skipped (not + # failed) when an upstream matrix entry fails, and a skipped + # required-check is treated as missing by branch protection, + # which leaves the PR mergeable. Run unconditionally and assert + # on the result instead. + if: always() + steps: + - name: Assert all pytest matrix entries succeeded + run: | + if [ "${{ needs.pytest.result }}" != "success" ]; then + echo "pytest matrix result: ${{ needs.pytest.result }}" + exit 1 + fi + echo "all pytest matrix entries passed"