From e3c17ceaa0b01b2fab26ffb520e1feac3d8f4c83 Mon Sep 17 00:00:00 2001 From: Joakim Olsson Date: Mon, 23 Mar 2026 15:52:25 +0000 Subject: [PATCH] fix: make release PR creation robust against race conditions (#19) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes for intermittent release workflow failures: - **Use `BASE_BRANCH` instead of `DEFAULT_BRANCH`** for the PR `base` field — `BASE_BRANCH` has a `:-main` fallback, preventing an empty base from causing a 404 - **Replace fixed `sleep 3` with proper polling and retry** — polls for branch readiness (up to 10 attempts) before creating the PR, then retries PR creation (up to 5 attempts) with backoff Fixes the `Error creating PR (HTTP 404)` seen when Gitea hasn't fully indexed the `next-release` branch by the time the PR creation request fires. 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Reviewed-on: https://gitea.unbound.se/unboundsoftware/shared-workflows/pulls/19 --- .gitea/workflows/Release.yml | 64 +++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/.gitea/workflows/Release.yml b/.gitea/workflows/Release.yml index 72695cc..5a2e115 100644 --- a/.gitea/workflows/Release.yml +++ b/.gitea/workflows/Release.yml @@ -189,27 +189,51 @@ jobs: fi echo "Creating new PR..." - echo "Waiting for branch to be ready..." - sleep 3 + echo "Waiting for next-release branch to be ready..." + for i in $(seq 1 10); do + BRANCH_STATUS=$(curl -s --retry 3 --retry-delay 2 --retry-connrefused \ + -w "%{http_code}" -o /dev/null \ + -H "Authorization: token ${TOKEN}" \ + "${API_URL}/branches/next-release") + if [ "${BRANCH_STATUS}" = "200" ]; then + echo "Branch ready after ${i} attempt(s)" + break + fi + if [ "${i}" = "10" ]; then + echo "Branch next-release not found after 10 attempts, giving up" + exit 1 + fi + echo "Branch not ready yet (attempt ${i}/10), waiting..." + sleep 3 + done - RESPONSE=$(curl -s --retry 3 --retry-delay 3 --retry-all-errors --retry-connrefused \ - -w "\n%{http_code}" -X POST \ - -H "Authorization: token ${TOKEN}" \ - -H "Content-Type: application/json" \ - --data "$(jq -n \ - --arg title "${TITLE}" \ - --arg body "${DESCRIPTION}" \ - --arg head "next-release" \ - --arg base "${DEFAULT_BRANCH}" \ - '{title: $title, body: $body, head: $head, base: $base}')" \ - "${API_URL}/pulls") - HTTP_CODE=$(echo "${RESPONSE}" | tail -1) - BODY=$(echo "${RESPONSE}" | sed '$d') - if [ "${HTTP_CODE}" -ge 400 ]; then - echo "Error creating PR (HTTP ${HTTP_CODE}): ${BODY}" - exit 1 - fi - echo "PR created successfully" + PR_DATA=$(jq -n \ + --arg title "${TITLE}" \ + --arg body "${DESCRIPTION}" \ + --arg head "next-release" \ + --arg base "${BASE_BRANCH}" \ + '{title: $title, body: $body, head: $head, base: $base}') + + for i in $(seq 1 5); do + RESPONSE=$(curl -s --retry 3 --retry-delay 2 --retry-connrefused \ + -w "\n%{http_code}" -X POST \ + -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/json" \ + --data "${PR_DATA}" \ + "${API_URL}/pulls") + HTTP_CODE=$(echo "${RESPONSE}" | tail -1) + BODY=$(echo "${RESPONSE}" | sed '$d') + if [ "${HTTP_CODE}" -lt 400 ]; then + echo "PR created successfully" + break + fi + if [ "${i}" = "5" ]; then + echo "Error creating PR after 5 attempts (HTTP ${HTTP_CODE}): ${BODY}" + exit 1 + fi + echo "PR creation attempt ${i}/5 failed (HTTP ${HTTP_CODE}), retrying..." + sleep 3 + done create-release: name: Create Release