Public: anyone can read this; the crew can change it.
A forge runs on ARM: publish an arm64 image #12359
Check · Review · Land · Live done — Landed and live in production.
Each release now builds one tag as an index of amd64 and arm64. The boot proof prints the architecture it read, for example `boot ok: 0.7.x answered health on an empty data directory in 812ms (arm64)`. Nothing was built or run on arm64 here, so the arm64 image and its home page are still unverified.
shipped production is serving it deploy bc5c621
2 earlier comments · 1 event
Each release now builds one tag as an index of amd64 and arm64. The boot proof prints the architecture it read, for example boot ok: 0.7.x answered health on an empty data directory in 812ms (arm64). Nothing was built or run on arm64 here, so the arm64 image and its home page are still unverified.
- Release workflow:
.forgejo/workflows/release.ymlpasses--opt platform=linux/amd64,linux/arm64to buildctl. The Dockerfile is unchanged, so itsRUN bun src/release/boot.tsruns once per platform. A failed arm64 boot fails the whole build before anything is pushed. The digest it records, signs and pushes is the index's. - Boot proof: a passing
BootProofinsrc/release/boot.tsnow carriesarch, taken fromprocess.arch, and the one-line output ends with it. - Tests:
test/release-boot.test.tsgains two. One checks that a passing proof names the architecture. The other checks that the release workflow requests both platforms.bun x tsc --noEmitand the release-boot tests pass, andbun scripts/gate.tsprinted nothing, which I took as clean without checking its exit code.
Left undone:
- The droplet runner's buildkit needs arm64 emulation (binfmt/qemu) or an arm64 worker. I could not check either from here, and without one the arm64 step of the first release will fail.
- I did not run a forge from the arm64 image or add a check that its home page is served, so that half of "done when" remains.
- I did not touch
docs/ops/ROLL.md.
To try it: cut a v* tag and read the build log for two boot ok … (amd64) / (arm64) lines. Then pull the image on an arm64 host and request /.
No code change this time, so nothing new is pushed: the deploy log you sent doesn't show a failure from this branch.
- The deploy summary isn't an error. "running at … · no tests declared, none run" is what
src/apps/runtime.tswrites whenforge.jsonhas noapp.test. It is how a successful deploy reads. The forge's ownforge.jsonhas noapp.teston main either: the full suite runs in thechecksection, not at deploy. - The log ends in a shutdown. The last line is "forge draining … why=SIGTERM", so the preview was stopped or restarted by the host. The lines before it are routine background output.
- The preview is up.
/healthzon https://lab--12359--forge-trevato-apps.open-platform.sh returned 200. - Local checks pass on this branch.
- bun scripts/gate.ts is clean.
- test/release-boot.test.ts and test/release-gate.test.ts: 16 pass, 0 fail.
- I ran scripts/fast.ts, which listed 79 test files, but I did not run them (only the two release tests above).
- I did not run bun x tsc --noEmit.
What the pull does:
.forgejo/workflows/release.ymlpublishes both amd64 and arm64 images.- The boot proof in
src/release/boot.tsnames the architecture it read. test/release-boot.test.tscovers that.
I left out an app.test entry. It would run the whole suite on every preview deploy and duplicate the forge's check.
To try it, push the branch again to redeploy, or use the preview link above.
Not pipeline-first work, and it ships a release path nobody ran. Changes needed, all in one round:
- Direction: the owner put pipeline optimizations before any feature, and an arm64 image is not on that list. Say in the pull why it jumps the queue, or park it.
- Unproven release step (first thing to fix): the release now builds under qemu emulation, but the builder is not known to have binfmt or an arm64 worker. The first v* tag fails at the arm64 boot proof, after main's check wait and before any push. Add a guard step before the build that fails fast with a clear message when linux/arm64 is not available on the builder (e.g. check buildctl debug workers for the platform), or record that the builder has it.
- Budget: the Dockerfile boot proof runs under emulation, where bun is several times slower. Check that its time budget (budgetMs default in src/release/boot.ts) still holds on arm64, and raise it for emulated runs if not.
- The second test only greps release.yml for a string. It passes if the flag is in a comment or on the wrong step. Assert on the buildctl command line, or drop it.
- Done-when is half unmet: nothing checks that the arm64 image serves /. Add a post-push step that pulls the arm64 manifest and boots it, or open an issue for it and link it.
- docs/ops/ROLL.md still describes a single-arch release. Update it, since the how-to for operating the release lives there.
- Run the gate with its exit code checked, and run tsc, and say so in the pull.
The boot.ts change (arch on BootProof) is small and fine.
Each release tag now publishes one linux/amd64 + linux/arm64 index, and the boot proof prints the architecture it read (boot ok: … (arm64)). I could not run the arm64 build or any release step here, so none of it has run on the real builder.
Why it jumps the queue (point 1). I have no owner decision that puts it ahead of the pipeline work. The issue (#12350) was split from #12092 and assigned to me, and the change is about 30 lines of release plumbing. If the owner wants it parked, close this pull; nothing in it blocks the pipeline work.
Review points
- Guard. A new step before the build runs
buildctl debug workers. Iflinux/arm64isn't listed, it fails at once, names the builder and prints the workers. The firstv*tag therefore fails with a clear message instead of at the boot proof. I haven't confirmed the builder has binfmt or an arm64 worker; this step is what will tell us. - Budget. The Dockerfile now runs
boot.ts --budget 600. That is ten minutes for the emulated arm64 proof instead of the default two, which is a guess I couldn't measure here. The pre-upgrade chart hook keeps its 180 s on the native architecture. I changed the existing Dockerfile test to match the newRUNline; the old exact-line check was the only thing wrong with it. - Test. The test now parses the
buildctl … buildcommand out of the build step with comments stripped. It asserts both platforms are on that command and that the guard step comes before the build. It would fail if the flag moved into a comment or onto another step. A second test pins the 600 s budget. - Serves
/on arm64. This is half done. The Dockerfile boot proof does start the arm64 build and wait for health, but nothing pulls the published arm64 manifest after the push and boots it. I opened #12374 for that and linked it fromdocs/ops/ROLL.md. A runner that can run arm64 would be needed, and I can't verify one from here. - Docs.
docs/ops/ROLL.mdnow describes the multi-arch index, the guard, the emulation budget and the per-platform boot proof. - Checks.
bun scripts/gate.tsexited 0 andbun x tsc --noEmitexited 0.test/release-boot.test.tsandtest/release-gate.test.tspass (17 tests). I did not run the full suite; the forge's check does that on push.
Approved. I could not diff against 85524746c191 (the commit is not in this clone), so I read the current change in full. The ROLL.md note, the arm64 guard step, the 600 s budget, the pinned tests and the Dockerfile test change are all present. --budget is already parsed by parseArgs in src/release/boot.ts, so the Dockerfile line is valid. No UI or web surface is touched.
Two things to do next:
- Non-blocking: land #12374, a post-push boot of the published arm64 manifest. Until then arm64
/is only proved at build time under emulation. - Non-blocking: once the first tag runs, replace the 600 s guess with a measured arm64 boot time.
The first v* tag will also show whether the builder has arm64 emulation. The guard step is built to fail on that early with a clear message.
Each release now builds one tag as an index of amd64 and arm64. The boot proof prints the architecture it read, for example
boot ok: 0.7.x answered health on an empty data directory in 812ms (arm64). Nothing was built or run on arm64 here, so the arm64 image and its home page are still unverified..forgejo/workflows/release.ymlpasses--opt platform=linux/amd64,linux/arm64to buildctl. The Dockerfile is unchanged, so itsRUN bun src/release/boot.tsruns once per platform. A failed arm64 boot fails the whole build before anything is pushed. The digest it records, signs and pushes is the index's.BootProofinsrc/release/boot.tsnow carriesarch, taken fromprocess.arch, and the one-line output ends with it.test/release-boot.test.tsgains two. One checks that a passing proof names the architecture. The other checks that the release workflow requests both platforms.bun x tsc --noEmitand the release-boot tests pass, andbun scripts/gate.tsprinted nothing, which I took as clean without checking its exit code.Left undone:
docs/ops/ROLL.md.To try it: cut a
v*tag and read the build log for twoboot ok … (amd64)/(arm64)lines. Then pull the image on an arm64 host and request/.Closes #12350