Skip to content

The toolchain tag is the content hash of everything the tarball's bytes depend on - #395

Merged
Japabu merged 4 commits into
mainfrom
toolchain-for-consumers
Sep 3, 2026
Merged

Japabu merged 4 commits into
mainfrom
toolchain-for-consumers

Conversation

@Japabu

@Japabu Japabu commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

#392 landed at 6ac57dc2 before this was written, so it goes on its own pull
request. Without it, nothing #392 added to the tarball ever reaches a
consumer.

The gap

toolchain.yml's have step turns an existing content release into
build=no, which skips publish. The key was the four sysroot trees, and #392
moved none of them — it changed the packaging (toyos-ld and TOOLCHAIN go
into the tar) and the linker's install path. So on main today:

old key, at this branch's HEAD:  d8dbd61f8ae95241   → a published release
new key, at this branch's HEAD:  81577c6cac7f8a85   → "release not found"

toolchain-linux-x86_64-d8dbd61f8ae95241 is what every run resolves to, it was
built before #392, and it carries no toyos-ld and no TOOLCHAIN. The
consumer's first ask would have stayed unmet until one of the four trees
happened to move.

The fix

The key becomes the content hash of everything the tarball's bytes depend on:
the four trees plus HEAD:toyos-ld/src, HEAD:toyos-ld/Cargo.toml and
HEAD:.github/workflows/toolchain.yml. Stated at the site, with its price:
a one-line change to the linker or to the packaging mints a new release and so
costs the whole hour-long bootstrap. That is what a content-addressed release
costs and it is the right side to err on — the wrong side ships a tarball whose
contents nobody built.

Eight copies, held identical

The expression cannot be reduced to one place: .github/install-toolchain.sh
runs before there is anything to read it from. Eight copies exist, across
toolchain.yml (which mints the tag), install-toolchain.sh, ci.yml (four),
gate-a.yml and probe-green.yml. A copy left behind asks for a tag nothing
published, and every job in CI installs its toolchain by that tag
— so
src/ci.rs::every_toolchain_key_names_the_same_trees holds them: each site's
HEAD: list must equal toolchain.yml's, and a ninth copy anywhere under
.github must join KEY_SITES or red.

Negative control — one copy reverted to the four-tree list:

thread 'ci::tests::every_toolchain_key_names_the_same_trees' panicked at src/ci.rs:553:17:
assertion `left == right` failed: .github/workflows/gate-a.yml names other trees than toolchain.yml does
  left: ["rust", "toyos-abi/src", "toyos/src", "userland/libc/src"]
 right: ["rust", "toyos-abi/src", "toyos/src", "userland/libc/src", "toyos-ld/src", "toyos-ld/Cargo.toml", ".github/workflows/toolchain.yml"]
test result: FAILED. 0 passed; 1 failed

green with all eight moved. The scan states the spelling it closes in its own
doc: git rev-parse … | sha256sum written within 300 characters, which is every
copy the tree has; toolchain.yml's manifest step reads HEAD:rust on its own
and is correctly not matched.

Gates

cargo test --lib          EXIT=0   249 passed; 0 failed; 1 ignored
cargo run -- --clippy     EXIT=0   clippy: 5 invocations clean
cargo run -- --build-only EXIT=0   Boot image: target/bootable.img
cargo run -- --pr         EXIT=0   +14 comment lines against +60 code lines (allowance 15)

src/prose-ledger: src/ci.rs 123 → 137, for the gate above.

`have` turns an existing content release into `build=no`, so a tag that named
only the four sysroot trees answered "already published" for a tree whose
tarball nobody has built. This branch is exactly that case: it puts `toyos-ld`
and `TOOLCHAIN` inside the tarball and moves none of the four, so after it lands
`toolchain-linux-x86_64-d8dbd61f8ae95241` still answers and no consumer ever
gets a tarball carrying the linker — until one of those four happens to move.

    old key, this branch:  d8dbd61f8ae95241   (the release that already exists)
    new key, this branch:  <the one this commit mints>

So the key gains `HEAD:toyos-ld/src`, `HEAD:toyos-ld/Cargo.toml` and
`HEAD:.github/workflows/toolchain.yml` — the linker that ships beside the
compiler, and the packaging that decides what goes in. The price is stated at
the site and accepted: a one-line change to either mints a new release and costs
the whole hour-long bootstrap.

**Eight copies of that expression exist** and they cannot be reduced to one —
`install-toolchain.sh` runs before there is anything to read it from. A copy
left behind asks for a tag nothing published, and every job in CI installs its
toolchain by that tag, so `src/ci.rs::every_toolchain_key_names_the_same_trees`
holds them: each of the five files' lists must equal `toolchain.yml`'s, and a
ninth copy anywhere in `.github` must join `KEY_SITES`.

Negative control, one copy reverted to the four-tree list:

    thread 'ci::tests::every_toolchain_key_names_the_same_trees' panicked at src/ci.rs:553:17:
    assertion `left == right` failed: .github/workflows/gate-a.yml names other trees than toolchain.yml does
      left: ["rust", "toyos-abi/src", "toyos/src", "userland/libc/src"]
     right: ["rust", "toyos-abi/src", "toyos/src", "userland/libc/src", "toyos-ld/src", "toyos-ld/Cargo.toml", ".github/workflows/toolchain.yml"]
    test result: FAILED. 0 passed; 1 failed

green with all eight moved.
The commit before this left the new key as a placeholder; both, computed at that
commit with the committed step's own expression:

    old key (the four sysroot trees):  d8dbd61f8ae95241
    new key (plus linker and packaging): 81577c6cac7f8a85

`toolchain-linux-x86_64-d8dbd61f8ae95241` is a published release, which is why
`have` was about to skip the build; `gh release view
toolchain-linux-x86_64-81577c6cac7f8a85` answers "release not found", so the
first publish-capable run after this lands builds and publishes a tarball that
carries `toyos-ld` and `TOOLCHAIN`.
The required checks are strict, so GitHub refuses the merge button until this branch contains main — which also makes the checks that run on this head checks on the merged result.
@Japabu
Japabu marked this pull request as ready for review September 3, 2026 19:09
@Japabu
Japabu enabled auto-merge September 3, 2026 19:09
#393 took the T14 out of CI: `route.yml` is gone and the four workflows that
carried the toolchain key name `ubuntu-24.04` directly. The key expression and
the runner line are independent lines in each of those files, so all eight
copies auto-merged and none of them lived in a step #393 deleted — eight copies
across five files, unchanged, and
`every_toolchain_key_names_the_same_trees` holds over them.

The one conflict was `src/prose-ledger`: both sides moved `src/ci.rs`'s row —
#393 cut prose (137 → 103, and the dated line with it), this branch added the
key gate. Resolved by recount rather than by choosing a side: 117 0, which is
what prosegate names.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4GoStX2JxXUq6ujSt4Rw1
@Japabu
Japabu added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit e10f438 Sep 3, 2026
24 checks passed
@Japabu
Japabu deleted the toolchain-for-consumers branch September 28, 2026 09:46
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