After POST /branches reports 201 and GET /branches/next-release reports
200, the /contents/{path}?ref=next-release endpoint can still 500 or
404 transiently while Gitea finishes indexing the new branch. That
caused fetch_sha to return empty for files that actually existed on
base, so write_file fell back to POST (create) and got HTTP 422
"repository file already exists" five times before giving up.
Query base branch for the blob SHA instead. 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 (next-release was just forked from
main, so the blob is identical). Treat 404 as "file absent" and retry
other non-200 responses up to 5 times.
## 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