Skip to content

ci: install qemu-user, and resolve the emulator this matrix names - #36

Merged
tannevaled merged 1 commit into
mainfrom
ci-qemu-ubuntu26
Oct 26, 2026
Merged

tannevaled merged 1 commit into
mainfrom
ci-qemu-ubuntu26

Conversation

@tannevaled

@tannevaled tannevaled commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

What broke, and why nothing was committed

ubuntu-latest became Ubuntu 26.04 on 2026-10-19. There qemu-user-static is a virtual package and apt refuses to choose between its two providers:

E: Package 'qemu-user-static' has no installation candidate
Package qemu-user-static is a virtual package provided by:
  qemu-user-binfmt-hwe 1:10.2.1+ds-1ubuntu4.4
  qemu-user-binfmt     1:10.2.1+ds-1ubuntu3.3

The step exits 100 in about twenty seconds. 333 repositories in 258 organisations of this account carried the same line; this is part of that sweep.

⛔ This repository's main is green because the lane has not run since the migration, not because it works. A green tick here means "has not run".

Two things that are not the fix

  • ⚠ Installing a provider. qemu-user-binfmt registers binfmt handlers; it does not ship the qemu-<arch>-static binaries this lane invokes. A lane given only a provider takes its command -v branch and goes green while testing nothing — worse than red. qemu-user ships the dynamic qemu-<arch>, which is all go test -exec needs, so both packages are installed and both binary names are accepted at run time.
  • ⛔ Skipping when the emulator is missing. A missing emulator now fails this lane, and the lane prints which emulator it ran (running s390x under qemu-s390x). Without that line, "ran under emulation" and "skipped" are indistinguishable from a green tick. Check that line in the lane's log, not the tick.

⚠ The native lane, which is why this file needed a shape of its own

This job's matrix carries the whole flag (exec: "-exec=qemu-riscv64-static"), and one of its lanes carries the empty string: 386 runs with no emulator on purpose, because a 386 ELF executes directly on the x86-64 runner and qemu-i386 was measured to lose the guest's floating-point state across the signal Go delivers for asynchronous preemption — five failures in eight runs, zero native.

So the rewrite branches on an empty exec and runs that lane natively (running 386 natively) instead of failing it for having no emulator. A fix that did not would have turned a correct lane red while claiming to repair it.

The matrix itself is untouched: the -static name there is the first candidate, not the defect.

Why the sweep's tool refused this file at first

It reported "step at line 75 has no run: key". That was true of the enclosing list item and beside the point: line 75 is a matrix datum, and the - { … } around it is not a step that runs anything. A command lives at or after its step's run:; anything before it is data. Fixed in qemufix with a shape of its own and a test for the native lane.

What did not change

Nothing but the package names and the emulator lookup. The test command keeps every other token it had, and the matrix keeps every lane it had.

How it was written

By qemufix v0.40.0 (go-fleettools/fleettools#131): a tested Go tool that recognises seven workflow shapes, refuses by name anything else rather than guessing, and is idempotent — an already-fixed file comes back byte-identical and is reported already-fixed. Its tests assert the three invariants per shape, with a control that runs the invariant checkers against the unfixed input (so checkers that pass on everything cannot pass the suite), and a planted positive for the idempotence claim.

Verified on the first merged lane of this campaign: the log reads running <arch> under <emulator> and the packages pass under emulation (see go-tex/engine#645).

🤖 Generated with Claude Code

`ubuntu-latest` became Ubuntu 26.04 on 2026-10-19, where `qemu-user-static` is
a VIRTUAL package and apt refuses to choose between its two providers:

  E: Package 'qemu-user-static' has no installation candidate

The step exits 100 in about twenty seconds. This lane's `main` is green only
because it has not run since the migration; 333 repositories of this account
carried the same line.

⚠ Installing a provider is NOT the fix. `qemu-user-binfmt` registers binfmt
handlers, it does not ship the `qemu-<arch>-static` binaries this lane invokes.
`qemu-user` ships the dynamic `qemu-<arch>`, which is all `go test -exec`
needs, so both packages are installed and BOTH NAMES are accepted at run time.

⛔ A missing emulator now FAILS this lane, and the lane PRINTS which emulator it
ran (`running s390x under qemu-s390x`). Without that line, "ran under
emulation" and "skipped" are indistinguishable from a green tick -- which is
how a fix for this looks like it worked while testing nothing.

⚠ The matrix is left exactly as written: the `-static` name there is the FIRST
candidate, not the defect. And the rewrite branches on an EMPTY `matrix.exec`
instead of failing it: a lane with no emulator runs NATIVELY on purpose -- a
386 ELF executes directly on the x86-64 runner, and qemu-i386 was measured to
lose the guest's floating-point state across the signal Go delivers for
asynchronous preemption (five failures in eight runs, zero native). Nine of the
eleven repositories in this family carry such a lane, and reading an empty exec
as "no emulator found" would have turned a correct one red.

Written by qemufix v0.40.0 (go-fleettools/fleettools), which refuses by name
anything it does not recognise and is idempotent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 7968ed9 into main Oct 26, 2026
9 checks passed
@tannevaled
tannevaled deleted the ci-qemu-ubuntu26 branch October 26, 2026 00:22
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