fix(android/ci): retry transient Play API failures in play-upload.py
apple / swift (push) Successful in 1m9s
apple / screenshots (push) Successful in 4m2s
android / android (push) Successful in 11m51s
ci / web (push) Successful in 1m0s
ci / docs-site (push) Successful in 1m13s
ci / rust (push) Successful in 4m30s
deb / build-publish (push) Successful in 3m35s
ci / bench (push) Successful in 4m47s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
decky / build-publish (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m59s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 10m3s
docker / deploy-docs (push) Successful in 20s

The uploader only caught HTTPError — a URLError (TLS "EOF occurred in
violation of protocol", the failure that dropped two release uploads on
2026-07-02) or a Google 5xx killed the job outright. Retry those with
3/9/27 s backoff; 4xx still fails fast. The edits API is transactional
until commit, so re-sending is safe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 23:05:27 +00:00
parent 6686fcdded
commit a3e1ea2b44
+24 -7
View File
@@ -37,13 +37,30 @@ def call(method, url, token=None, data=None, content_type=None, want_json=True):
headers["Authorization"] = f"Bearer {token}"
if content_type:
headers["Content-Type"] = content_type
req = urllib.request.Request(url, data=data, method=method, headers=headers)
try:
with urllib.request.urlopen(req, timeout=300) as r:
body = r.read()
except urllib.error.HTTPError as e:
raise ApiError(e.code, method, url, e.read().decode("utf-8", "replace"))
return json.loads(body) if (want_json and body) else body
# Transient-fault retries: googleapis.com occasionally drops the TLS session ("EOF
# occurred in violation of protocol" — failed two release uploads on 2026-07-02) or
# answers 5xx. Retry those with backoff; 4xx raises immediately (a real API error).
# The edits API is transactional until commit, so re-sending any of these is safe.
last = None
for attempt in range(4):
if attempt:
delay = 3**attempt
print(f"transient Play API failure ({last}); retry {attempt}/3 in {delay}s")
time.sleep(delay)
req = urllib.request.Request(url, data=data, method=method, headers=headers)
try:
with urllib.request.urlopen(req, timeout=300) as r:
body = r.read()
return json.loads(body) if (want_json and body) else body
except urllib.error.HTTPError as e:
if e.code >= 500:
last = f"HTTP {e.code}"
continue
raise ApiError(e.code, method, url, e.read().decode("utf-8", "replace"))
except urllib.error.URLError as e:
last = str(getattr(e, "reason", e))
continue
sys.exit(f"ERROR: {method} {url} still failing after retries: {last}")
def load_sa():