From 777eba301660343210203854b73f1f58166c422b Mon Sep 17 00:00:00 2001 From: fujibee Date: Fri, 11 Sep 2026 15:34:07 -0700 Subject: [PATCH] =?UTF-8?q?ci(tests):=20shard=20the=20bats=20suite=205=20w?= =?UTF-8?q?ays,=20not=204=20=E2=80=94=20the=20main=20twin=20of=20the=20#11?= =?UTF-8?q?07=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same change already landed on the terminal-driver integration branch; this is the main-targeted twin so main PRs stop hitting the macOS 30-min cap that the 4-shard split reaches on this suite too. shard-tests.sh seeds each pinned file at one shard's average share (total_tests/total), which grows with the suite while the pinned files do not, over-reserving the two pin shards and pushing the real load onto the non-pinned ones. main is 1742 @tests, so the worst-case non-pinned shard total*(N+2)/N^2 drops from 653 (N=4) to 488 (N=5), back under the cap with margin. Five, not six, because the account runs at most five macOS jobs at once (the concurrency header). test_ci_workflow.bats reads SHARD_TOTAL and the matrix and follows the /N name; it is green at 5. This does not fix the scaling property (pin_seed still grows with the suite); that re-fit is #847. --- .github/workflows/tests.yml | 20 +++++++++++++++++--- tests/test_ci_workflow.bats | 4 ++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 544c5896..3aee94eb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -104,7 +104,21 @@ concurrency: env: # Number of parallel bats shards per OS. The matrix and the shard helper must # stay in lockstep; the stable summary job below verifies that they do. - SHARD_TOTAL: 4 + # + # 4 -> 5 (#1107). Same change already on the terminal-driver integration branch; + # this is the main-targeted twin so main PRs stop hitting the same macOS cap. + # shard-tests.sh seeds each pinned file at one shard's AVERAGE share + # (total_tests/total), which grows with the suite while the pinned files do not, + # over-reserving the two pin shards and pushing the real load onto the non-pin + # ones. main is 1742 @tests here, so the worst-case non-pin shard + # (total*(N+2)/N^2) is 653 at N=4 and 488 at N=5 -- and a 4-shard macOS leg was + # already reaching the 30-min cap while still passing tests (a slow shard, not a + # hang: the workflow's own #848/#857 note). Five, not six, because the account + # runs at most FIVE macOS jobs at once (the concurrency header): a sixth would + # queue behind the other five of its own run. This does NOT fix the scaling + # property (pin_seed still grows, count still under-values wait-dominant files); + # that re-fit is #847. + SHARD_TOTAL: 5 # The Windows legs' sqlite3, pinned three ways (#824). # # This comment used to end "one trip to chocolatey, which is the only time @@ -249,7 +263,7 @@ jobs: # the required contexts are `bats` (the aggregate) and the Windows install # leg, and neither is renamed, so branch protection sees exactly what it # saw. `needs` is one of the contexts a job name may read. - name: bats (${{ matrix.os }} ${{ matrix.shard }}/4)${{ needs.changes.outputs.docs_only == 'true' && ' — docs-only, suite skipped' || '' }} + name: bats (${{ matrix.os }} ${{ matrix.shard }}/5)${{ needs.changes.outputs.docs_only == 'true' && ' — docs-only, suite skipped' || '' }} needs: changes # Run even if `changes` somehow failed/was skipped — fail open to the full # suite rather than leaving this REQUIRED check unreported (which would @@ -283,7 +297,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - shard: [1, 2, 3, 4] + shard: [1, 2, 3, 4, 5] steps: - uses: actions/checkout@v4 diff --git a/tests/test_ci_workflow.bats b/tests/test_ci_workflow.bats index 87fa6fc3..88edbc1a 100644 --- a/tests/test_ci_workflow.bats +++ b/tests/test_ci_workflow.bats @@ -50,7 +50,7 @@ local workflow="$BATS_TEST_DIRNAME/../.github/workflows/tests.yml" # 1. The shard job's name carries the marker, keyed on the docs_only output. # Shard checks are not required contexts, so the name may vary. - grep -Fq "name: bats (\${{ matrix.os }} \${{ matrix.shard }}/4)\${{ needs.changes.outputs.docs_only == 'true' && ' — docs-only, suite skipped' || '' }}" "$workflow" + grep -Fq "name: bats (\${{ matrix.os }} \${{ matrix.shard }}/5)\${{ needs.changes.outputs.docs_only == 'true' && ' — docs-only, suite skipped' || '' }}" "$workflow" # 2. The aggregate -- the required context -- keeps its exact name, once, # unconditionally. [ "$(grep -c '^ name: bats$' "$workflow")" -eq 1 ] @@ -72,7 +72,7 @@ # The mutation took: the marker is gone from the copy. if grep -Fq "docs-only, suite skipped' || ''" "$mutant"; then false; fi # ...and the name pin no longer matches it. - if grep -Fq "name: bats (\${{ matrix.os }} \${{ matrix.shard }}/4)\${{ needs.changes.outputs.docs_only == 'true' && ' — docs-only, suite skipped' || '' }}" "$mutant"; then false; fi + if grep -Fq "name: bats (\${{ matrix.os }} \${{ matrix.shard }}/5)\${{ needs.changes.outputs.docs_only == 'true' && ' — docs-only, suite skipped' || '' }}" "$mutant"; then false; fi } # The suite has to run on the shape that actually gets dogfooded. A PR is only