Second attempt at releasing 0.2.1. The first one (#24) reached main but its
build died, and the reason turned out to be the runner itself.
New since then:
fix: keep the daemon alive when a job report fails (#28) — a rejected log
update no longer ends the daemon and every job it is running. This is what
killed the previous release build after it had pushed the runner image but
before the job image existed;
ci: cache round-trip without the cache sub-actions (#27) — the compatibility
suite stops failing on the entrypoint guard and goes back to testing the cache
API. The guard itself is #26.
Merge after run 300 on develop is green, so we know the fixed daemon
builds and publishes before main depends on it.
Sequence afterwards, unchanged: the main build publishes main, latest and
the commit sha, and only then does tagging v0.2.1 make sense. Tagging earlier
would promote the current mutable runner-job:ubuntu-24.04, which still points
at sha256:c7e6ace... from the previous release — the promote step copies
manifests without rebuilding, so nothing would go red.
One risk worth naming: the production runner still runs the 0.2.0 image, so this
build executes on a daemon that carries the very bug #28 fixes. If it dies
again, the answer is to repin the runner host to the fixed image first rather
than to keep retrying.
Second attempt at releasing 0.2.1. The first one (#24) reached `main` but its
build died, and the reason turned out to be the runner itself.
New since then:
- `fix: keep the daemon alive when a job report fails` (#28) — a rejected log
update no longer ends the daemon and every job it is running. This is what
killed the previous release build after it had pushed the runner image but
before the job image existed;
- `ci: cache round-trip without the cache sub-actions` (#27) — the compatibility
suite stops failing on the entrypoint guard and goes back to testing the cache
API. The guard itself is #26.
**Merge after run 300 on `develop` is green**, so we know the fixed daemon
builds and publishes before `main` depends on it.
Sequence afterwards, unchanged: the main build publishes `main`, `latest` and
the commit sha, and only then does tagging `v0.2.1` make sense. Tagging earlier
would promote the current mutable `runner-job:ubuntu-24.04`, which still points
at `sha256:c7e6ace...` from the previous release — the promote step copies
manifests without rebuilding, so nothing would go red.
One risk worth naming: the production runner still runs the 0.2.0 image, so this
build executes on a daemon that carries the very bug #28 fixes. If it dies
again, the answer is to repin the runner host to the fixed image first rather
than to keep retrying.
The suite failed on the guard that rejects `..` in an action entrypoint, not
on the cache API it was written to exercise. The top-level action stays inside
its own directory and saves in its post step, so the round trip now spans two
jobs. #26 covers the guard itself.
A rejected log update ended the whole runner. `finish_job` propagated
`ReporterError` out of the agent loop, so `run()` returned `Err`, the process
exited and compose restarted it — taking every other job on the runner with it.
On the production runner this happened three times on 2026-08-03 and killed the
0.2.1 release build after it had already pushed the runner image.
Reporting now fails the job it belongs to and is written to stderr, the way a
failed poll already is. A join failure stays fatal: it means the task itself
never produced a result.
The group carried no branch, and a run waiting in a group is cancelled by the
next run regardless of cancel-in-progress. A push to develop could therefore
drop a queued main build without a single red light — the same defect the forge
repository fixed in fa52916.
Branch builds now cancel their predecessor: a superseded image has no consumer,
and both branches publish mutable tags that the next build overwrites. Tag
builds still run to completion, because promote copies two manifests and a
half-finished release is not something the next build repairs.
The job image was rebuilt on every push, although its inputs — the image
Dockerfile, the bundled assets and the pinned base — changed three times in the
history of this repository. Worse, each rebuild produced a new digest for
identical content, because SOURCE_DATE_EPOCH tracked HEAD and rewrite-timestamp
faithfully applied it. Three consecutive builds published three digests of the
same image, and every runner host pulled a gigabyte to get what it already had.
The image is now named after the content of its inputs and built only when that
name is absent from the registry. Release tags point at it with imagetools.
Its epoch is fixed, so identical inputs produce an identical digest.
The runner image builds on the host builder instead of one created per run.
Cargo cache mounts live in the builder and are never part of a registry cache
export, so destroying the builder each run discarded exactly the state that
makes a Rust rebuild cheap. The host daemon runs the containerd snapshotter, so
it builds both platforms directly.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Second attempt at releasing 0.2.1. The first one (#24) reached
mainbut itsbuild died, and the reason turned out to be the runner itself.
New since then:
fix: keep the daemon alive when a job report fails(#28) — a rejected logupdate no longer ends the daemon and every job it is running. This is what
killed the previous release build after it had pushed the runner image but
before the job image existed;
ci: cache round-trip without the cache sub-actions(#27) — the compatibilitysuite stops failing on the entrypoint guard and goes back to testing the cache
API. The guard itself is #26.
Merge after run 300 on
developis green, so we know the fixed daemonbuilds and publishes before
maindepends on it.Sequence afterwards, unchanged: the main build publishes
main,latestandthe commit sha, and only then does tagging
v0.2.1make sense. Tagging earlierwould promote the current mutable
runner-job:ubuntu-24.04, which still pointsat
sha256:c7e6ace...from the previous release — the promote step copiesmanifests without rebuilding, so nothing would go red.
One risk worth naming: the production runner still runs the 0.2.0 image, so this
build executes on a daemon that carries the very bug #28 fixes. If it dies
again, the answer is to repin the runner host to the fixed image first rather
than to keep retrying.