From bba536394f02065ddfccbaa86f3d4940e6dcc145 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Fri, 24 Jul 2026 22:22:52 +0200 Subject: [PATCH] ci(release): retry the Codeberg release create past the tag-settle 500 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Codeberg mirror step pushes the tag, then immediately POSTs the release for it — but Codeberg 500s when the release request outruns its indexing of the just-pushed ref, and with only one attempt that single 500 skipped the mirror every release (the same POST succeeds seconds later, as a manual retry confirmed for v2.16.0). Wrap the create/update in a backoff retry loop that PATCHes in place if a release already exists, so a transient 5xx no longer loses the mirror. Step stays best-effort (continue-on-error). Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/release.yaml | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index b1895af..bf0f83e 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -412,20 +412,31 @@ jobs: "prerelease": False, })) PY - # Upsert (re-run safe). POST also creates the tag at target_commitish - # if the push mirror hasn't synced it yet. - ID=$(curl -s -H "Authorization: token $TOKEN" "$API/releases/tags/$TAG" | jq -r '.id // empty') - if [ -n "$ID" ]; then - curl -s -o /dev/null -w "release PATCH HTTP %{http_code}\n" -X PATCH \ + # Create (or update) the release. Codeberg 500s on a POST/GET against a + # tag it has only just received — the release request outruns the + # indexing of the ref we pushed a moment ago — so a single attempt kept + # failing and skipping the mirror even though the very same call + # succeeds seconds later. Retry with backoff, and PATCH in place if a + # release already exists (re-run safe). A 5xx body still exits curl 0, + # so the loop, not `set -e`, controls the flow. + ID="" + for attempt in 1 2 3 4 5 6; do + EXIST=$(curl -s -H "Authorization: token $TOKEN" "$API/releases/tags/$TAG" | jq -r '.id // empty' 2>/dev/null || true) + if [ -n "$EXIST" ]; then + curl -s -o /dev/null -w "release PATCH HTTP %{http_code}\n" -X PATCH \ + -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ + -d @cb-payload.json "$API/releases/$EXIST" + ID="$EXIST"; break + fi + CODE=$(curl -s -o cb-response.json -w "%{http_code}" -X POST \ -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ - -d @cb-payload.json "$API/releases/$ID" - else - curl -s -o cb-response.json -w "release POST HTTP %{http_code}\n" -X POST \ - -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ - -d @cb-payload.json "$API/releases" + -d @cb-payload.json "$API/releases") + echo "release POST attempt $attempt HTTP $CODE" ID=$(jq -r '.id // empty' cb-response.json 2>/dev/null || true) - fi - if [ -z "$ID" ]; then echo "Could not resolve Codeberg release id." >&2; exit 1; fi + [ -n "$ID" ] && break + sleep $((attempt * 10)) + done + if [ -z "$ID" ]; then echo "Could not resolve Codeberg release id after retries." >&2; exit 1; fi # Attach APK + checksum, replacing any prior asset of the same name. for A in "$ASSET_APK" "$ASSET_SUM"; do