Refreshing the pins by hand meant checking five mirrors and hand-building
URLs to confirm them, which is how Fedora and Alpine drifted two releases
behind without anyone noticing. This does the lookup and the checking.
Prefers each distribution's own metadata over scraping where it exists:
Ubuntu from changelogs.ubuntu.com/meta-release, the same file
do-release-upgrade reads, filtered to supported LTS; Debian from the stable
suite's Release file, so it follows Debian's own definition of stable rather
than guessing from directory names. Fedora, AlmaLinux and Alpine have no such
feed and are read from mirror listings.
Alpine turns out to be automatable after all. latest-stable is a symlink to
the current branch, so the filename there yields the branch, the patch level
and the prefix together, and reading the prefix rather than assuming it is
what would have caught the nocloud_ rename.
Two properties matter more than the lookups:
Candidate URLs are derived by evaluating the pin block and the case statement
out of build-cloudinit-template.sh itself, not by repeating its URL templates
here. A second copy would eventually disagree with the builder and verify
something the builder never downloads.
Nothing is written until the image has been confirmed to serve qcow2 magic,
not merely a 200. Mirrors answer for a deleted image with an HTML error page
under a 200, which would otherwise be pinned as good and fail at build time.
A distro that fails verification keeps its old pin and does not hold up the
others.
Dry run by default. Exit 3 distinguishes "pins are stale" from success, so it
can run as a periodic staleness check, and 2 means a lookup or verification
failed.
The template is read by anchor, so a restructured pin block or case statement
is detected and refused rather than silently producing URLs from unset
variables.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>