From bcfa770b5391dcc4edbe462389fee3065a27b7e8 Mon Sep 17 00:00:00 2001 From: Calvin Bascom Date: Tue, 13 Oct 2026 13:07:17 -0400 Subject: [PATCH 1/2] Make the required Test check report on every PR The branch ruleset requires a status check named Test, but nothing emitted one: the workflow's only checks were the matrix jobs (protobuf 5.29.5, 6.31.1, ...), and the pull_request trigger was path-filtered, so a PR touching only config (e.g. renovate.json) ran no workflow at all. Either way the required check never reported and the PR hung. Add an aggregate job named Test that runs on every PR and passes only when the protobuf matrix passes, and drop the pull_request path filter so it always reports. The matrix stays path-filtered on push. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/test.yml | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a651de9..d3c2971 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,13 +10,6 @@ on: - "src/**" - "tests/**" pull_request: - paths: - - ".github/workflows/test.yml" - - "examples/**" - - "pyproject.toml" - - "scripts/**" - - "src/**" - - "tests/**" workflow_dispatch: concurrency: @@ -63,3 +56,22 @@ jobs: - name: Test run: python ${{ matrix.warning_args }} -m pytest + + # Aggregate gate: this job's name is the required status check ("Test"). It + # runs on every pull request (the matrix above is path-filtered on push, but + # a required check has to report on every PR or the PR hangs forever), and it + # passes only if the protobuf matrix passed. + test: + name: Test + runs-on: tenki-standard-small-2c-4g + needs: protobuf-compatibility + if: always() + steps: + - name: Require the protobuf matrix to pass + run: | + result="${{ needs.protobuf-compatibility.result }}" + echo "protobuf-compatibility result: ${result}" + if [ "${result}" != "success" ]; then + echo "::error::protobuf compatibility matrix did not pass" + exit 1 + fi From 4cdb879d6c419fe85b55ebf70d14b4bb329b46ad Mon Sep 17 00:00:00 2001 From: Calvin Bascom Date: Tue, 13 Oct 2026 13:11:36 -0400 Subject: [PATCH 2/2] Path-gate the matrix behind a change-detection job Keep the required Test check reporting on every PR, but stop running the 4-way protobuf matrix on PRs that touch no test-relevant files. A small changes job diffs the PR against its base with plain git (no third-party changed-files action) and the matrix runs only when src/tests/packaging files changed. The Test gate passes automatically when the matrix is skipped, and otherwise only when it succeeds. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/test.yml | 68 +++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d3c2971..e82be0e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,6 +9,7 @@ on: - "scripts/**" - "src/**" - "tests/**" + - "uv.lock" pull_request: workflow_dispatch: @@ -20,8 +21,49 @@ permissions: contents: read jobs: + # Decide whether the matrix needs to run. On push the trigger is already + # path-filtered, so this is only meaningful for pull_request, where the + # workflow must run on every PR (so the required Test check always reports) + # but the expensive matrix should only run when test-relevant files change. + # Uses plain git rather than a third-party changed-files action. + changes: + name: changes + runs-on: tenki-standard-small-2c-4g + outputs: + code: ${{ steps.filter.outputs.code }} + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + + - name: Detect test-relevant changes + id: filter + run: | + set -euo pipefail + base='${{ github.event.pull_request.base.sha }}' + head='${{ github.event.pull_request.head.sha }}' + if [ -z "${base}" ]; then + # Not a pull_request (push / workflow_dispatch): the push trigger is + # already path-filtered, so run the matrix. + echo "code=true" >> "${GITHUB_OUTPUT}" + exit 0 + fi + changed=$(git diff --name-only "${base}...${head}" -- \ + .github/workflows/test.yml examples pyproject.toml scripts src tests uv.lock) + if [ -n "${changed}" ]; then + echo "Test-relevant files changed:" + echo "${changed}" + echo "code=true" >> "${GITHUB_OUTPUT}" + else + echo "No test-relevant files changed." + echo "code=false" >> "${GITHUB_OUTPUT}" + fi + protobuf-compatibility: name: protobuf ${{ matrix.protobuf }} + needs: changes + if: ${{ needs.changes.outputs.code == 'true' }} runs-on: tenki-standard-small-2c-4g strategy: fail-fast: false @@ -58,20 +100,30 @@ jobs: run: python ${{ matrix.warning_args }} -m pytest # Aggregate gate: this job's name is the required status check ("Test"). It - # runs on every pull request (the matrix above is path-filtered on push, but - # a required check has to report on every PR or the PR hangs forever), and it - # passes only if the protobuf matrix passed. + # runs on every PR and reports once. It passes when no test-relevant files + # changed (the matrix was skipped) and otherwise only when the matrix passed. test: name: Test runs-on: tenki-standard-small-2c-4g - needs: protobuf-compatibility + needs: [changes, protobuf-compatibility] if: always() steps: - - name: Require the protobuf matrix to pass + - name: Require the matrix to pass when it ran run: | - result="${{ needs.protobuf-compatibility.result }}" - echo "protobuf-compatibility result: ${result}" - if [ "${result}" != "success" ]; then + set -euo pipefail + changes_result='${{ needs.changes.result }}' + code='${{ needs.changes.outputs.code }}' + matrix_result='${{ needs.protobuf-compatibility.result }}' + echo "changes=${changes_result} code=${code} matrix=${matrix_result}" + if [ "${changes_result}" != "success" ]; then + echo "::error::change detection did not succeed" + exit 1 + fi + if [ "${code}" != "true" ]; then + echo "No test-relevant files changed; nothing to test." + exit 0 + fi + if [ "${matrix_result}" != "success" ]; then echo "::error::protobuf compatibility matrix did not pass" exit 1 fi