Add tea to the base, and a slop-generator variant carrying claude #9

Closed
geusebio wants to merge 1 commit from feature/slop-generator-variant-with-claude into main
Owner

The claude-* pipelines in Someones.Computer fetch a pinned claude (~270 MB) and a pinned tea (~29 MB) on every job. This bakes both in. Measured against run 1967 over there — a review at 189s wall clock, 45s of it the tools-plus-gates window — that is worth 25–35s a run.

Two binaries, two places

They are different sizes of favour, so they land differently:

Where Why
tea the runner base — every tag gets it 29 MB, statically linked, no libc dependency. Every workflow in that repo which touches the tracker or a PR shells out to it.
claude a variant, php8.5-slop-generator 270 MB, and only the pipelines writing prose for a human to read have any use for it.

The variant is a stage on top of runner, not a second base, so PHP, node, go, docker and tea are the same build and the same bytes as php8.5 — claude is the only difference. One non-matrix bake target rather than one per PHP version, because php8.5 is the only tag anything dispatches against.

tea is pinned per architecture (both checksums lifted from the release's checksums.txt) and builds on amd64 and arm64. The claude stage is amd64 only even on a multiarch main build: the pinned asset is linux-x64-musl and the caller pins the same slug, so an arm64 variant means a second pin. It waits until something dispatches on arm64 — and until then the stage refuses to build on another arch rather than baking a binary that cannot run.

Both are verified against a checksum literal, so a republished release fails the build rather than shipping quietly, and both are then run. That last part is not ceremony: this base is musl, the glibc claude build dies at runtime with Error relocating …claude: unsupported relocation type 37, and that only surfaces once the binary executes. Running it here turns a failed job downstream into a failed image build.

Verified

Each block built standalone against the published php8.5 image, so the proof exercises the real downloads and checksums without an emulated rebuild of PHP/go/node:

Case Result
tea, linux/amd64 pin OK, Version: 0.15.1
tea, linux/arm64 pin OK, Version: 0.15.1 — native, exercises the new arm64 pin
claude, linux/amd64 claude.partial: OK, 2.1.220 (Claude Code) under musl
claude, linux/arm64 refused: The slop-generator stage pins an amd64 claude; aarch64 is not supported.
tea with a deliberately wrong pin FAILED / computed checksum did NOT match, build dies

And against the resulting image, the check the consumer actually gates on:

SKIP: claude 2.1.220 already on PATH at /usr/local/bin/claude
SKIP: tea 0.15.1 already on PATH at /usr/local/bin/tea
--- drift fallback (pretend the action pins a newer claude) ---
FALLS BACK TO DOWNLOAD, as intended

That last line is the safety property worth stating plainly: the consumer gates its download on the reported version, not on presence, so an image whose pins drift from a caller's costs the speedup and nothing else. The worst outcome is losing the saving, never running an unpinned binary — which is also why bumping claude_version over there does not have to wait for an image rebuild.

docker buildx bake --print resolves the default group to ["runner", "slop-generator"], so the existing build job publishes the new tag with no workflow change.

hadolint reports the same SC3040/DL4006 pair on the two new heredoc RUNs that the existing OpenTofu block already produces — it parses heredocs as POSIX sh and ignores the SHELL ["/bin/bash", …] above them. No new finding class.

Follow-up, elsewhere

The container: bump that consumes this is a separate PR in Someones.Computer, and it is held as a draft until this merges and php8.5-slop-generator exists — until then those jobs would fail to pull.

The claude-* pipelines in [Someones.Computer](https://git.grey.ooo/Grey.ooo/Someones.Computer/issues/544) fetch a pinned `claude` (~270 MB) and a pinned `tea` (~29 MB) on **every job**. This bakes both in. Measured against run 1967 over there — a review at 189s wall clock, 45s of it the tools-plus-gates window — that is worth 25–35s a run. ## Two binaries, two places They are different sizes of favour, so they land differently: | | Where | Why | |---|---|---| | `tea` | the `runner` **base** — every tag gets it | 29 MB, statically linked, no libc dependency. Every workflow in that repo which touches the tracker or a PR shells out to it. | | `claude` | a **variant**, `php8.5-slop-generator` | 270 MB, and only the pipelines writing prose for a human to read have any use for it. | The variant is a stage on top of `runner`, **not a second base**, so PHP, node, go, docker and tea are the same build and the same bytes as `php8.5` — claude is the only difference. One non-matrix bake target rather than one per PHP version, because php8.5 is the only tag anything dispatches against. `tea` is pinned per architecture (both checksums lifted from the release's `checksums.txt`) and builds on amd64 and arm64. The claude stage is **amd64 only even on a multiarch main build**: the pinned asset is `linux-x64-musl` and the caller pins the same slug, so an arm64 variant means a second pin. It waits until something dispatches on arm64 — and until then the stage *refuses to build* on another arch rather than baking a binary that cannot run. Both are verified against a checksum literal, so a republished release fails the build rather than shipping quietly, and both are then **run**. That last part is not ceremony: this base is musl, the glibc claude build dies at runtime with `Error relocating …claude: unsupported relocation type 37`, and that only surfaces once the binary executes. Running it here turns a failed job downstream into a failed image build. ## Verified Each block built standalone against the published `php8.5` image, so the proof exercises the real downloads and checksums without an emulated rebuild of PHP/go/node: | Case | Result | |---|---| | tea, `linux/amd64` | pin OK, `Version: 0.15.1` | | tea, `linux/arm64` | pin OK, `Version: 0.15.1` — native, exercises the new arm64 pin | | claude, `linux/amd64` | `claude.partial: OK`, `2.1.220 (Claude Code)` under musl | | claude, `linux/arm64` | refused: `The slop-generator stage pins an amd64 claude; aarch64 is not supported.` | | tea with a deliberately wrong pin | `FAILED` / `computed checksum did NOT match`, build dies | And against the resulting image, the check the consumer actually gates on: ``` SKIP: claude 2.1.220 already on PATH at /usr/local/bin/claude SKIP: tea 0.15.1 already on PATH at /usr/local/bin/tea --- drift fallback (pretend the action pins a newer claude) --- FALLS BACK TO DOWNLOAD, as intended ``` That last line is the safety property worth stating plainly: the consumer gates its download on the reported **version**, not on presence, so an image whose pins drift from a caller's costs the speedup and nothing else. The worst outcome is losing the saving, never running an unpinned binary — which is also why bumping `claude_version` over there does not have to wait for an image rebuild. `docker buildx bake --print` resolves the default group to `["runner", "slop-generator"]`, so the existing build job publishes the new tag with no workflow change. hadolint reports the same `SC3040`/`DL4006` pair on the two new heredoc `RUN`s that the existing OpenTofu block already produces — it parses heredocs as POSIX sh and ignores the `SHELL ["/bin/bash", …]` above them. No new finding class. ## Follow-up, elsewhere The `container:` bump that consumes this is [a separate PR in Someones.Computer](https://git.grey.ooo/Grey.ooo/Someones.Computer/issues/544), and it is held as a draft until this merges and `php8.5-slop-generator` exists — until then those jobs would fail to pull.
Add tea to the base, and a slop-generator variant carrying claude
All checks were successful
Build / Build Builder (push) Successful in 6m36s
2451a21d81
The claude-* pipelines in Someones.Computer fetch a pinned claude (~270 MB) and
a pinned tea (~29 MB) on every job. Baking both removes the fetch: measured
against run 1967 there, that window is worth 25-35s a run.

The two land in different places because they are different sizes of favour.
tea is 29 MB, statically linked, and every workflow in that repo which touches
the tracker or a PR shells out to it, so it goes in the base and every tag gets
it. claude is 270 MB and only the pipelines writing prose for a human to read
have any use for it, so it is a variant: `slop-generator`, published as
php8.5-slop-generator.

The variant is a stage on top of `runner`, not a second base, so PHP, node, go,
docker and tea are the same build and the same bytes as php8.5 — claude is the
only difference. One non-matrix bake target rather than one per PHP version,
because php8.5 is the only tag anything dispatches against, and amd64 only even
on a multiarch main build, because the pinned claude asset and the caller's
platform slug are both amd64; the stage refuses to build on anything else
rather than baking a binary that cannot run. tea is pinned per architecture and
does build on both.

Both are verified against a checksum literal, so a republished release fails
the build rather than shipping quietly, and both are then run: this base is
musl, the glibc claude build dies at runtime with `unsupported relocation type
37`, and a version check is how callers decide to skip their own download.

Verified by building each block against the published php8.5 image: tea's pins
pass on amd64 and arm64 and it reports 0.15.1 on both; claude passes on amd64
and reports 2.1.220 under musl; the arm64 claude build refuses with the message
above instead of producing a broken image; and a deliberately wrong pin fails
the build. The caller's skip condition then fires against the result, and falls
back to downloading when the pin is made to drift.
geusebio closed this pull request 2026-09-01 10:26:16 +00:00
All checks were successful
Build / Build Builder (push) Successful in 6m36s

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
actions/Github-Actions-Runner!9
No description provided.