## 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: #24
## Why
After #22 moved the branch-readiness poll before `.version` write, the workflow started failing **every run** with `exitcode '23'` and no error output. Exit 23 = `CURLE_WRITE_ERROR` from curl in the wait loop's `BRANCH_STATUS=$(curl ...)`. With `set -e`, any non-zero status from a command substitution aborts the script before the retry/echo path runs — so the failure was both deterministic and silent.
## Changes
- Introduce an `api_call` helper that wraps curl with `|| rc=$?` and emits `<http_code>|<curl_rc>` plus the response body. Curl exit codes can no longer kill the script via `set -e`.
- Create the `next-release` branch explicitly via `POST /branches` instead of relying on the `new_branch` parameter of the CHANGELOG.md PUT. Eliminates the race between branch creation and subsequent file writes.
- Poll branch readiness after explicit creation.
- Fetch file blob SHAs from `next-release` directly (not base), so writes always carry the correct SHA.
- Every API call (branch create, CHANGELOG.md, .version, PR) now retries 5× with HTTP code, curl exit code, and response body logged on failure.
## Test plan
- [ ] Trigger Release.yml on a repo with a pending changelog entry; confirm branch is created, both files written, and PR opened.
- [ ] On transient errors, log shows HTTP code + curl rc + body on each retry.
Reviewed-on: #23
## Why
Release workflow intermittently failed at the `.version` write step with `exit 22` and no diagnostic output. The CHANGELOG.md PUT creates the `next-release` branch via the `new_branch` parameter, then the `.version` PUT fires ~2s later — racing Gitea's branch indexing. Because the call used `curl -sf` (fail-silent), 404/409 responses produced exit 22 with no body, leaving logs unhelpful.
## Changes
- Move the existing branch-readiness poll to run **right after** the CHANGELOG.md commit, before `.version` is written.
- Replace the silent `.version` write with a 5-attempt retry loop that logs HTTP code and body on failure (same pattern already used for PR creation).
## Test plan
- [ ] Trigger Release.yml on a repo with a pending changelog entry; confirm `.version` write succeeds first try and PR is created.
- [ ] If a transient failure happens, log now shows HTTP code + body.
Reviewed-on: #22
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: #19
The PR creation curl immediately follows branch creation via the Contents
API, but Gitea may not have fully indexed the new branch for pull request
operations yet. This causes intermittent HTTP errors on the first run.
- Add sleep 3 before PR creation to allow Gitea to process the new branch
- Use --retry-all-errors so curl retries on HTTP 4xx/5xx (not just
connection failures)
- Capture and display the actual HTTP error code and response body on
failure for easier debugging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delete and recreate the next-release branch from base on each run instead of
rebasing, which caused 409 conflicts on CHANGELOG.md. Add concurrency group
to prevent parallel workflow runs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add --retry 3 --retry-delay 2 --retry-connrefused to all Gitea API
curl calls to handle transient connection failures. This addresses
intermittent exit code 7 (connection refused) errors when the K8s
internal service briefly drops connections.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When updating an existing release PR, the workflow now rebases
the next-release branch onto the base branch using Gitea's PR
update API with style=rebase. This keeps the PR up to date with
main without force-pushing or deleting the branch.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds fallback to main branch if DEFAULT_BRANCH is empty and updates
the way CHANGELOG.md and .version files are handled in the release
process. Refactors checks for existing branches and includes
detailed logging for transparency. This improves the robustness of
the release workflow and ensures relevant files are created or
updated correctly.
- Run directly on ubuntu-latest instead of custom containers
- Download git-cliff binary from GitHub releases
- Merge changelog and handle-pr into single job
- Make create-release and create-tag self-contained
- Remove upload-artifact and download-artifact (not supported on GHES/Gitea)
- Add Renovate custom manager for automatic git-cliff updates
- Run directly on ubuntu-latest instead of custom containers
- Download git-cliff binary from GitHub releases
- Add Renovate custom manager for automatic git-cliff updates