From 1f9d754f6116461a005a20fa61ff9fa24e6ee8b7 Mon Sep 17 00:00:00 2001 From: Joakim Olsson Date: Wed, 13 May 2026 11:10:44 +0000 Subject: [PATCH] fix(release): fetch file SHAs from base branch, not next-release (#24) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Why After #23, the workflow on `robotframework` failed with `CHANGELOG.md write failed after 5 attempts (422): {"message":"repository file already exists [path: CHANGELOG.md]"}`. Sequence from the log: - `POST /branches` → 201 (branch created). - `GET /branches/next-release` → 500, 500, then 200 (the readiness poll worked). - `fetch_sha` then queried `GET /contents/CHANGELOG.md?ref=next-release` immediately after — that endpoint was still propagating and didn't return the SHA, so `fetch_sha` came back empty. - `write_file` saw no SHA, used POST (create), and got HTTP 422 because the file genuinely existed on base (and therefore on the freshly forked `next-release`). Different Gitea API endpoints don't share a single readiness signal for a newly created branch — `/branches` can report ready while `/contents` is still 500/404. ## Changes - `fetch_sha` now queries `?ref=${BASE_BRANCH}` instead of `?ref=next-release`. Base is stable, and Gitea content writes are content-addressed by blob SHA, so a SHA fetched from main works for PUT on `next-release` (it was just forked from main, so the blob is identical). - Treat 404 as "file absent, no SHA" and retry other non-200 responses up to 5× with backoff. ## Test plan - [ ] Trigger Release.yml on `robotframework` (or another repo with an existing CHANGELOG.md on main). Confirm CHANGELOG.md and .version both write via PUT first try, and PR is created. - [ ] First-release repo (no CHANGELOG.md on main yet): `fetch_sha` returns empty after 404, `write_file` POSTs to create — confirm this path still works. Reviewed-on: https://gitea.unbound.se/unboundsoftware/shared-workflows/pulls/24 --- .gitea/workflows/Release.yml | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/.gitea/workflows/Release.yml b/.gitea/workflows/Release.yml index c963488..352149c 100644 --- a/.gitea/workflows/Release.yml +++ b/.gitea/workflows/Release.yml @@ -175,14 +175,29 @@ jobs: sleep 2 done - # Fetch file blob SHAs from next-release (inherited from base on creation) + # Fetch file blob SHA from BASE_BRANCH. next-release was just forked + # from base so the blob SHA matches; querying base avoids racing + # Gitea's per-endpoint propagation for the new branch (the /contents + # endpoint can still 500/404 after /branches reports 200). Returns + # empty only when the file genuinely does not exist on base. fetch_sha() { local path="$1" out meta code body - out=$(api_call GET "/contents/${path}?ref=next-release") - meta=$(meta_line "${out}"); code="${meta%%|*}"; body=$(body_lines "${out}") - if [ "${code}" = "200" ]; then - printf '%s' "${body}" | jq -r '.sha // empty' - fi + for i in $(seq 1 5); do + out=$(api_call GET "/contents/${path}?ref=${BASE_BRANCH}") + meta=$(meta_line "${out}"); code="${meta%%|*}"; body=$(body_lines "${out}") + if [ "${code}" = "200" ]; then + printf '%s' "${body}" | jq -r '.sha // empty' + return 0 + fi + if [ "${code}" = "404" ]; then + return 0 + fi + if [ "${i}" = "5" ]; then + echo "fetch_sha ${path} failed after 5 attempts (${meta}): ${body}" >&2 + return 0 + fi + sleep 2 + done } CHANGELOG_SHA=$(fetch_sha "CHANGELOG.md") VERSION_SHA=$(fetch_sha ".version")