Every product repository builds its image on release and workflow_dispatch only:
| Repo |
Triggers |
| FerrVault-Cloud, FerrTrack-Cloud, FerrGrowth-Cloud, FerrFleet-Cloud, FerrLens-Cloud, FerrGames-Cloud, FerrLabs-Cloud, LFSX |
release, workflow_dispatch |
So the Dockerfile is exercised for the first time after a version has been tagged, its changelog written, its crate published and its chart pushed with an appVersion naming an image that may not exist. The release does not roll back when the image build fails — it just leaves a hole.
This is not hypothetical. Recent release-time image failures:
- LFSX: 0.21.0, 0.22.0, 0.23.0, 0.23.1, 0.24.0 — five consecutive releases, no image. GHCR stops at 0.20.0. Cause: one
export VAR="$(cat ...)" tripping hadolint's SC2155 at --failure-threshold warning. A lint error, invisible for five versions.
- FerrTrack-Cloud:
api@v2.14.2 failed, latest Docker run failed
- FerrGrowth-Cloud:
app@v4.21.0 failed
- FerrGames-Cloud:
gameserver@v2026.8.3 failed
- FerrLabs-Cloud:
bff@v3.2.0 and auth@v6.1.0 failed
The consequence is not limited to a missing artefact. Homelab pinned the LFSX chart to 0.23.1, the pod could not pull ghcr.io/ferrlabs/lfsx:0.23.1, and the service was down for seventeen minutes until Flux gave up and rolled back — for a version that had been "released" hours earlier.
What to build
Make the image prove itself on the pull request that changes it.
LFSX already carries a hand-rolled version of this (FerrLabs/LFSX#84) and should drop it once the shared one lands.
Related
The same investigation turned up a syntax error in reusable-docker-build.yml that breaks every caller pinned past 30a2f74, fixed in #257 with a bash -n guard over every run block. That one is about the reusable being broken; this issue is about product repositories not finding out until it is too late.
Every product repository builds its image on
releaseandworkflow_dispatchonly:release,workflow_dispatchSo the Dockerfile is exercised for the first time after a version has been tagged, its changelog written, its crate published and its chart pushed with an
appVersionnaming an image that may not exist. The release does not roll back when the image build fails — it just leaves a hole.This is not hypothetical. Recent release-time image failures:
export VAR="$(cat ...)"tripping hadolint's SC2155 at--failure-threshold warning. A lint error, invisible for five versions.api@v2.14.2failed, latestDockerrun failedapp@v4.21.0failedgameserver@v2026.8.3failedbff@v3.2.0andauth@v6.1.0failedThe consequence is not limited to a missing artefact. Homelab pinned the LFSX chart to 0.23.1, the pod could not pull
ghcr.io/ferrlabs/lfsx:0.23.1, and the service was down for seventeen minutes until Flux gave up and rolled back — for a version that had been "released" hours earlier.What to build
Make the image prove itself on the pull request that changes it.
enable-docker-buildinput on the language reusables (reusable-ci-rust.ymlfirst, since every API is Rust), callingreusable-docker-build.ymlwithpush: falselinux/amd64) — the release keeps the multi-arch matrix. The point is proving the file, not the fan-outDockerfileor the build workflow, not on every PRLFSX already carries a hand-rolled version of this (FerrLabs/LFSX#84) and should drop it once the shared one lands.
Related
The same investigation turned up a syntax error in
reusable-docker-build.ymlthat breaks every caller pinned past 30a2f74, fixed in #257 with abash -nguard over every run block. That one is about the reusable being broken; this issue is about product repositories not finding out until it is too late.