From f195739ee34e1fc0e6684f29a8f905a328d10259 Mon Sep 17 00:00:00 2001 From: sotashimozono Date: Tue, 4 Aug 2026 23:39:55 +0000 Subject: [PATCH] refactor(ci): the timing-history read becomes the action #69 added MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #69 restored the pre-#68 inline block to unbreak every consumer, and added `actions/read-history` in the same PR so that a workflow could name it — `uses: …@main` resolves against main, so the action had to be there first (measured: with both halves in one PR the run died at `Can't find 'action.yml' … @main` before any step executed). The action is on main now, so the duplicate goes. What is left is one copy of the read, in a file that `read-history.test.sh` runs unchanged, reachable from every caller because an action's own files are fetched with it. This repository cannot verify the consumer half of that — it is its own caller, which is the whole shape of #54 and #69 — so the check is deliberate rather than implied: a downstream PR (ParaLinearAlgebra.jl #426) is re-run against this immediately after the merge. --- .github/workflows/sharded-tests.yml | 60 ++++++++--------------------- Project.toml | 2 +- 2 files changed, 16 insertions(+), 46 deletions(-) diff --git a/.github/workflows/sharded-tests.yml b/.github/workflows/sharded-tests.yml index 56f50bd..285f7b8 100644 --- a/.github/workflows/sharded-tests.yml +++ b/.github/workflows/sharded-tests.yml @@ -281,52 +281,22 @@ jobs: with: submodules: ${{ inputs.submodules }} - # INLINE, and only until the next PR. #68 moved this into a file so that - # `read-history.test.sh` could put the SAME code in the states a consumer is in — the right - # idea, at a path that cannot work: a `run:` in a REUSABLE WORKFLOW executes in the CALLER's - # checkout, so `run: .github/scripts/read-history.sh` found the file in this repository's own - # CI and exited 127 on every consumer (ParaLinearAlgebra.jl run 30959798081: five jobs red, - # eight shards never started, six minutes after #68 merged). + # AN ACTION, not a `run:`, and the reason is where each one runs. #68 moved this into a + # file so `read-history.test.sh` could put the SAME code in the states a consumer is in — + # the no-history state cannot be reached from a run of this repository, which is how it + # shipped broken (#54) and surfaced on the first adopter. That part was right. # - # The fix is `actions/read-history`, added in this PR — an action's own files are fetched - # with it, so `${{ github.action_path }}` resolves for every caller. It cannot be USED here - # yet: `uses: …@main` resolves against main, where the action does not exist until this - # merges. So this step is the pre-#68 block again, which unbreaks every consumer on merge, - # and the switch to `uses:` is the immediate follow-up. The duplication is deliberate, is - # one PR long, and is the reason the follow-up is not optional. - - name: Read the timing history, once, for every shard - run: | - set -uo pipefail - # `ls-remote --exit-code` distinguishes the cases: 0 = branch exists, 2 = no matching - # ref, anything else = error. Measured. - # - # Captured through an `if`, and that is not style. A `run:` step's shell is - # `bash -e {0}`, so errexit is ON from the command line and `set -uo pipefail` does not - # take it off — it only ADDS options. A bare `out=$(...); rc=$?` therefore kills the - # step the moment ls-remote exits non-zero, BEFORE `rc` is read: a repository with no - # ci-timings branch yet died with exit 2 and no output, which is the one case this - # code was written to handle. An assignment inside an `if` condition is exempt from - # errexit however the shell was invoked. - if out=$(git ls-remote --exit-code --heads origin ci-timings 2>&1); then rc=0; else rc=$?; fi - if [ "$rc" -eq 0 ]; then - if ! git fetch --depth=1 origin ci-timings; then - echo "::error::The ci-timings branch exists but could not be fetched. Failing here, before any shard starts, rather than letting the shards disagree about the split." - exit 1 - fi - if git show FETCH_HEAD:timings.tsv > timings.tsv 2>/dev/null; then - echo "$(wc -l < timings.tsv) timing rows." - else - echo "ci-timings carries no timings.tsv yet — round-robin." - : > timings.tsv - fi - elif [ "$rc" -eq 2 ]; then - echo "No ci-timings branch yet — round-robin until the first push to the default branch." - : > timings.tsv - else - echo "::error::Could not tell whether the ci-timings branch exists (git ls-remote exit $rc). Failing rather than guessing: guessing wrong puts the shards on different assignments, which double-runs some units and skips others while every shard stays green." - echo "$out" - exit 1 - fi + # What could not work is a `run:`: a `run:` step in a REUSABLE WORKFLOW executes in the + # CALLER's checkout, so `run: .github/scripts/read-history.sh` found the file here and + # exited 127 on every consumer (#69: ParaLinearAlgebra.jl run 30959798081, five jobs red, + # eight shards never started). An action's own files are fetched WITH it, so + # `${{ github.action_path }}` resolves for every caller and nothing lands in the consumer's + # workspace — which a second `actions/checkout` of this repository would not manage, since + # its `src/*.jl` would then be inside the consumer's coverage sweep. + # + # Same split as `actions/upload-coverage`: the workflow owns what needs JOBS, an action owns + # what has to run from this repository's own tree. + - uses: QAtlasHub/TestShards.jl/actions/read-history@main - uses: actions/upload-artifact@v7 with: diff --git a/Project.toml b/Project.toml index c258183..9e7e916 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "TestShards" uuid = "acceef1d-f5e0-4fe4-a546-818dc56ce7b2" -version = "0.3.32" +version = "0.3.33" authors = ["sota shimozono "] [deps]