image reader waits out a registry 429 and tries again (3 tries); 08 + changelog: the dry-run measurement of the Docker Hub change (0 refused), two runners = two tag caches (R-1334)

This commit is contained in:
admin committed 2026-10-28 13:08:33 +01:00
1 parent fe677bae94
commit 8644450db2
7 files changed
+877 -9

No files matched your search

+35
View File
@@ -134,6 +134,40 @@ def wheel_checks():
sys.modules.pop("zstandard", None)
def retry_checks():
"""A registry 429 (ghcr.io refused blob reads in two back-to-back CI dry runs, 2026-10-28) is waited out and tried
again; the answer is a refusal only after the last try."""
import io, time, urllib.error, urllib.request
calls, slept = [], []
real_open, real_sleep = urllib.request.urlopen, time.sleep
class Resp(io.BytesIO):
status = 200
headers = {}
def fake(answers):
def op(req, timeout=60):
calls.append(req.full_url)
a = answers.pop(0) if len(answers) > 1 else answers[0]
if a == 429:
raise urllib.error.HTTPError(req.full_url, 429, "Too Many Requests", {"Retry-After": "3"}, io.BytesIO(b""))
return Resp(b"ok")
return op
try:
time.sleep = lambda s: slept.append(s)
urllib.request.urlopen = fake([429, 200])
st, _h, body = ir._get("https://ghcr.io/v2/x/blobs/sha256:a")
check("retry: a 429 then 200 -> the 200, after waiting its Retry-After", st == 200 and body == b"ok" and
len(calls) == 2 and 3 in slept, (st, calls, slept))
calls.clear()
urllib.request.urlopen = fake([429])
st, _h, body = ir._get("https://ghcr.io/v2/x/blobs/sha256:a")
check("retry: a 429 on every try -> 429 after %d tries, never a pass" % ir.RETRY_TRIES, st == 429 and
len(calls) == ir.RETRY_TRIES, (st, len(calls)))
finally:
urllib.request.urlopen, time.sleep = real_open, real_sleep
def main():
apk = ir.parse_apk("P:musl\nV:1.2.5-r10\n\nP:nodejs\nV:24.18.1-r0\n\nP:brotli-libs\nV:1.2.0-r1\n")
check("apk database -> nodejs and brotli-libs", apk.get("nodejs") == "24.18.1-r0" and apk.get("brotli-libs") == "1.2.0-r1", apk)
@@ -163,6 +197,7 @@ def main():
"size": 10}], budget=0)
check("a layer over the byte budget is a NOTE, never a silent pass", notes and ("budget" in notes[0] or "zstd" in notes[0]), notes)
zstd_checks()
retry_checks()
wheel_checks()
d = tempfile.mkdtemp()
open(os.path.join(d, "a.yaml"), "w").write("spec:\n containers:\n - image: rommapp/romm:5.4.0\n name: x\n"