Keep the manifests an index is made of - #127
Merged
Merged
Conversation
The tidy up in the image workflow deleted the per architecture manifests that every published image is built out of, which left fifteen indexes resolving and then pointing at nothing. Every tag in the package pulls as manifest unknown right now, which is why gdb and tier1 fail on #125. The retention rule kept three kinds of version: the newest few hundred, anything tagged, and anything a release named. A manifest inside an index is none of those. It never gets a tag, because the tag goes on the index, and it is never in the lockfile, because the lockfile records index digests. The build is fully cached against a fixed commit so the same manifest keeps the same digest week after week and its age never moves, and one Monday it falls past the floor and goes. So close the protected set over membership before comparing anything against it. cpybuild expand starts from every tagged digest and every digest a release named, asks the registry what each one lists, and walks until nothing new turns up. It refuses to print at all if it found no parts anywhere, because with fifteen indexes in the package that means Docker is missing rather than that there is nothing to keep. The content never changed and the layer blobs are still there, so the rebuild this commit triggers re pushes the same manifests under the same digests and repairs the pinned index in place. Closes #126
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every image in the package is unpullable.
:debug,:release,:jitand the digest the lockfile pins all saymanifest unknown, which is whygdbandtier1fail on #125 and would fail on everything after it. It passes locally only because the images are already in the local Docker cache.The index is still in the registry. What is gone is what it is made of:
We deleted them ourselves, in the
tidyjob ofcpython-images. From this morning's run:Those eighteen are the halves the fifteen protected indexes are built out of.
Why the rule missed them
retention.doomedkeeps the newestkeep, anything tagged, and anything a release named. A per architecture manifest is none of the three. The tag goes on the index, not on the half. The lockfile records index digests, not halves. And because the build is fully cached against a fixed commit, a half keeps the same digest week after week, so its age never moves and it eventually drops past the floor of 120 and is deleted, breaking every index that lists it including the one published four minutes earlier in the same run.What this does
retention.anchorssays where the keeping starts, which is every tagged version plus everything a release named.retention.reachablewalks from there through whatever each digest lists, breadth first, until nothing new turns up. Both are pure and take the membership lookup as an argument, so the interesting half is tested against a dictionary rather than a registry.cpybuild expandis the command that joins them to the real thing. It reads the version list and the protected file the tidy job already produces, asksdocker buildx imagetools inspect --rawwhat each digest lists, and prints the closure.--rawrather than the readable output, because the readable output resolves an index into a table of platforms and silently drops the attestation rows, and the attestations are versions too.Two ways this could quietly turn back into the bug, and what stops each. A digest that will not resolve is reported on stderr and treated as holding nothing, because some of them genuinely do not resolve any more and refusing outright would mean the tidy up never runs again. And on top of that,
expandexits non zero without printing anything if the whole walk found no parts at all, since with fifteen indexes in the package zero means Docker is not there or the login did not take, and the thing not to do with an answer that is probably wrong is hand it to something that deletes images.Run against the real registry it turns the fifteen protected digests into thirty, and both halves that went missing this morning are in the thirty.
Getting the images back
Nothing about the content changed and the layer blobs are still in the registry, so a rebuild re pushes the same per architecture manifests under the same digests. That repairs the currently pinned
de0d69b1index in place, with no lockfile change and no new digest to write anywhere. This pull request touchestools/cpybuild/**, which is already a path trigger forcpython-images, so merging it rebuilds, republishes and then runs the fixed tidy up in one go.Closes #126