Context
#263 and the layered-image follow-up exposed a class of bug we don't currently detect: an artifact at <release_tag>/<asset> can be re-uploaded with different bytes, leaving the hardcoded SHA in published.py out of sync with the live file. Users hit ImageError: SHA-256 mismatch at runtime, not in CI.
#280 removed the default --clobber from both upload workflows — re-runs against an existing tag now fail loud at the upload step unless the dispatcher explicitly passes force_overwrite=true. That eliminates the most common drift source (accidental rebake on push), but several remain:
- Intentional
force_overwrite=true workflow_dispatch runs (the rebake escape hatch — by design).
- Manual asset edits via the GitHub Releases UI (delete + re-add).
- Copy-paste errors when populating SHAs in
published.py during a tag-bump PR — the SHAs in source and the bytes at the URL are written in two different places by two different actors and nothing currently compares them.
- Future regressions to the friction logic itself.
A cheap, independent SHA-verification gate catches all of these.
What
A new workflow — smoke-manifest-shas.yml — that:
- Imports
BASE_KERNELS and MANIFEST from smolvm.images.published.
- For each unique
(url, sha256) pair, downloads the asset and verifies the SHA-256 matches.
- Fails loudly with a clear diff if any drift is detected.
Triggers:
- On push to
main when src/smolvm/images/published.py changes (catches stale SHAs from typos or copy-paste errors during bump PRs).
- Nightly via
schedule: cron (catches manual GitHub UI edits and intentional force-overwrites whose SHA wasn't resynced).
workflow_dispatch for ad-hoc verification.
Not to be confused with smoke-published-images.yml
That existing workflow boots QEMU with the kernel + each rootfs and waits for SSH — it's a boot smoke. This issue asks for a cheaper SHA-only smoke, no VM launched. The two are complementary: boot smoke catches "kernel doesn't boot the rootfs," SHA smoke catches "the bytes the manifest pins no longer exist at the URL."
Acceptance criteria
- New workflow runs green when
BASE_KERNELS and MANIFEST SHAs match live bytes.
- Workflow fails with a clear diff when any URL's live SHA differs from the recorded one (e.g.
expected ab12…, got cd34…).
- Nightly schedule catches manual GitHub Releases edits within 24h.
Related
- #263 — layered build infrastructure that surfaced the drift class.
- #264 — Alpine flavor (independent).
- #280 — removed default
--clobber; reduced but did not eliminate drift surface.
Context
#263 and the layered-image follow-up exposed a class of bug we don't currently detect: an artifact at
<release_tag>/<asset>can be re-uploaded with different bytes, leaving the hardcoded SHA in published.py out of sync with the live file. Users hitImageError: SHA-256 mismatchat runtime, not in CI.#280 removed the default
--clobberfrom both upload workflows — re-runs against an existing tag now fail loud at the upload step unless the dispatcher explicitly passesforce_overwrite=true. That eliminates the most common drift source (accidental rebake on push), but several remain:force_overwrite=trueworkflow_dispatch runs (the rebake escape hatch — by design).published.pyduring a tag-bump PR — the SHAs in source and the bytes at the URL are written in two different places by two different actors and nothing currently compares them.A cheap, independent SHA-verification gate catches all of these.
What
A new workflow —
smoke-manifest-shas.yml— that:BASE_KERNELSandMANIFESTfromsmolvm.images.published.(url, sha256)pair, downloads the asset and verifies the SHA-256 matches.Triggers:
mainwhensrc/smolvm/images/published.pychanges (catches stale SHAs from typos or copy-paste errors during bump PRs).schedule:cron (catches manual GitHub UI edits and intentional force-overwrites whose SHA wasn't resynced).workflow_dispatchfor ad-hoc verification.Not to be confused with
smoke-published-images.ymlThat existing workflow boots QEMU with the kernel + each rootfs and waits for SSH — it's a boot smoke. This issue asks for a cheaper SHA-only smoke, no VM launched. The two are complementary: boot smoke catches "kernel doesn't boot the rootfs," SHA smoke catches "the bytes the manifest pins no longer exist at the URL."
Acceptance criteria
BASE_KERNELSandMANIFESTSHAs match live bytes.expected ab12…, got cd34…).Related
--clobber; reduced but did not eliminate drift surface.