Skip to content

Build the pull request through the path that publishes - #173

Merged
frangarcj merged 3 commits into
masterfrom
next-single-matrix
Aug 26, 2026
Merged

Build the pull request through the path that publishes#173
frangarcj merged 3 commits into
masterfrom
next-single-matrix

Conversation

@frangarcj

@frangarcj frangarcj commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

The hosts are declared twice.

cmake/hosts.json is what describe turns into a lock, what build-sdk.yml matrixes over, and what scripts/ci/build-host.sh builds. That is the route autobuilds takes to a published snapshot.

Alongside it, build.yml carried its own matrix — 513 lines of hand-written stage 1 / stage 2 / stage 2-musl / stage 3 jobs, reaching the same hosts by running cmake straight from the job.

Twice the runners is the cheap half of the cost. The expensive half is that a pull request goes green having exercised the route nobody publishes:

db4d1a593 merged green with the Intel Mac host broken — its macOS leg never ran build-host.sh, so nothing cross-compiled and an arm64 SDK shipped under the Intel name (#171)
buildscripts#168 every macOS leg of the executor dying on run[@]: unbound variable, after a complete and valid build, with out/ empty — invisible to a CI that does not call the executor
#161/db4d1a593 the stage-3 recipe for x86_64-apple-darwin removed and restored without either CI noticing

Three times this month, one shape: green by the path that is not the one.

What this does

build.yml describes the revision under review and hands the lock to build-sdk.yml:

  describe:
    steps:
    - uses: actions/checkout@v7
      with:
        ref: ${{ github.event.pull_request.head.sha || github.sha }}
        fetch-depth: 0
    - id: describe
      run: ./buildscripts-ci describe --profile vita --output lock.json

  build:
    needs: describe
    uses: ./.github/workflows/build-sdk.yml
    with:
      lock: ${{ needs.describe.outputs.lock }}

Called by path, so a pull request that changes the reusable workflow is tested by its own build. The head commit and not the merge commit, because the lock names a revision the build legs check out again.

Two jobs disappear rather than move:

  • pacman-client-package — every packaged host now builds a core package, and create-core-package.sh already validates every package it writes (scripts/create-core-package.sh:192). A separate job to build one host's package and validate it again was the old matrix's way of reaching a thing the lock reaches everywhere.
  • the packaging tests get a job of their own after the build. Two of the three are fixtures all the way down; the third configures a staged cross, and the staged build refuses a toolchain configure without a stage-1 SDK. It takes the stage-1 the build already made -- found by stage and not by host name, because which host produces stage 1 is the lock's to say -- instead of building a second SDK to reach it, which is what the removed job did.

What the CI covers now

Ten legs against the old twelve jobs, and it verifies more, because build-host.sh does things the hand-written matrix never did:

  • the toolchain contract and the bootstrap smoke test on every host that can run its own output — the old CI ran the contract on three hosts and the smoke test on none
  • smoke-windows-bootstrap on a real windows-2025 runner
  • the release tree grouped and uploaded, which no pull request had ever produced
  • provenance written per leg, and the packaged-family completeness check

i686-w64-mingw32 goes with it, in its own commit. describe prunes it — packaged: false, and no packaged stage-3 host uses it as a build machine — so it has been out of every lock for as long as the lock has existed, and no snapshot has ever carried it: forty releases of vitasdk/autobuilds, none with an i686 asset. What kept building it was this matrix, which uploaded vitasdk-windows-i686 and then had no job download it. The lock is ten hosts before that commit and ten after; what goes is a row, a toolchain file and a build recipe that describe stopped honouring a while ago. scripts/build-core-in-container.sh also has no caller left, and I have left it alone.

Test

tests/ci/test-single-matrix.sh guards the property, not the file:

  • something is built through build-sdk.yml, and it is called by path
  • what it is handed is the lock describe produced
  • no job declares a strategy — the matrix comes from the lock
  • build.yml names no host from cmake/hosts.json, no runner that only exists to build one, and no cmake/toolchains/ file

That last group is the one that matters over time: a second matrix does not come back all at once, it comes back one row at a time.

Against master it fails at the first question. All 9 CI tests, 6 protocol tests and 7 cmake scripts pass on this branch; actionlint is clean.


AI tools were used in preparing this PR (Claude Opus 5, Anthropic).

The hosts were declared twice. cmake/hosts.json is what describe turns
into a lock, what build-sdk.yml matrixes over, and what build-host.sh
builds -- the route autobuilds takes to a published snapshot. Alongside
it, build.yml carried a hand-written matrix that reached the same hosts
by running cmake straight from the job.

Twice the runners was the cheap half of the cost. The expensive half is
that a pull request went green having exercised the route nobody
publishes: db4d1a5 merged with the Intel Mac host broken because its
macOS leg had never run build-host.sh, and buildscripts#168 was the same
shape. Third time this month.

So build.yml describes the revision under review and hands the lock to
build-sdk.yml, called by path so a change to the reusable workflow is
tested by its own pull request. The packaging tests move to checks,
where they belong -- they run against fixtures, not a built SDK -- and
the core package needs no job of its own, because create-core-package.sh
validates every package it writes and every packaged host now builds
one.

The pruned lock is ten legs against the old twelve jobs, and it verifies
more: the toolchain contract and the bootstrap smoke test now run on
every host that can run its own output, the Windows bootstrap gets a
real Windows runner, and the release tree is grouped. What it no longer
builds is i686-w64-mingw32, which describe prunes because nothing
publishes it. scripts/build-core-in-container.sh has no caller left.
tests/package looked like fixtures all the way down, and two of the
three are. The third configures a staged cross to check that no
build-machine project survives it, and the staged build refuses a
toolchain configure without a stage-1 SDK: "Cross building needs a
stage-1 SDK", straight out of BuildGccFinal.cmake. Moving the three into
checks ran it without one.

So they get a job after the build, taking the stage-1 the build already
made -- found by stage rather than by host name, because which host
produces stage 1 is the lock's to say. The job the previous commit
removed built its own stage-2 SDK to reach the same place.
i686-w64-mingw32 was declared `packaged: false`, which is describe's way
of saying it does not go in a release, and it is nobody's build machine
either -- so prune_hosts has been leaving it out of every lock since the
lock existed. No snapshot has ever carried it: forty releases of
vitasdk/autobuilds, none with an i686 asset.

What kept building it was the hand-written matrix, which uploaded
vitasdk-windows-i686 and then had no job download it. It expired
fourteen days later, every run, unread.

So this is not a host being retired; it is a row, a toolchain file and a
build recipe that describe stopped honouring a while ago. The lock is
ten hosts before this commit and ten after.
@frangarcj
frangarcj merged commit 93a4d9a into master Aug 26, 2026
17 of 20 checks passed
@frangarcj
frangarcj deleted the next-single-matrix branch August 26, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant