Compare commits

..

22 Commits

Author SHA1 Message Date
renovate bb12bac945 chore(deps): update actions/checkout action to v7 (#26)
This PR contains the following updates:

| Package | Type | Update | Change | Pending |
|---|---|---|---|---|
| [actions/checkout](https://github.com/actions/checkout) | action | major | `v6` → `v7` | `v7.0.0` |

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

### [`v7.0.0`](https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v700)

[Compare Source](https://github.com/actions/checkout/compare/v7.0.0...v7.0.0)

- Block checking out fork PR for pull\_request\_target and workflow\_run by [@&#8203;aiqiaoy](https://github.com/aiqiaoy) in [#&#8203;2454](https://github.com/actions/checkout/pull/2454)
- Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the minor-actions-dependencies group across 1 directory by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2458](https://github.com/actions/checkout/pull/2458)
- Bump flatted from 3.3.1 to 3.4.2 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2460](https://github.com/actions/checkout/pull/2460)
- Bump js-yaml from 4.1.0 to 4.2.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2461](https://github.com/actions/checkout/pull/2461)
- Bump [@&#8203;actions/core](https://github.com/actions/core) and [@&#8203;actions/tool-cache](https://github.com/actions/tool-cache) and Remove uuid by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2459](https://github.com/actions/checkout/pull/2459)
- upgrade module to esm and update dependencies by [@&#8203;aiqiaoy](https://github.com/aiqiaoy) in [#&#8203;2463](https://github.com/actions/checkout/pull/2463)
- Bump the minor-npm-dependencies group across 1 directory with 3 updates by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2462](https://github.com/actions/checkout/pull/2462)

### [`v7`](https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v700)

[Compare Source](https://github.com/actions/checkout/compare/v6.0.3...v7.0.0)

- Block checking out fork PR for pull\_request\_target and workflow\_run by [@&#8203;aiqiaoy](https://github.com/aiqiaoy) in [#&#8203;2454](https://github.com/actions/checkout/pull/2454)
- Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the minor-actions-dependencies group across 1 directory by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2458](https://github.com/actions/checkout/pull/2458)
- Bump flatted from 3.3.1 to 3.4.2 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2460](https://github.com/actions/checkout/pull/2460)
- Bump js-yaml from 4.1.0 to 4.2.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2461](https://github.com/actions/checkout/pull/2461)
- Bump [@&#8203;actions/core](https://github.com/actions/core) and [@&#8203;actions/tool-cache](https://github.com/actions/tool-cache) and Remove uuid by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2459](https://github.com/actions/checkout/pull/2459)
- upgrade module to esm and update dependencies by [@&#8203;aiqiaoy](https://github.com/aiqiaoy) in [#&#8203;2463](https://github.com/actions/checkout/pull/2463)
- Bump the minor-npm-dependencies group across 1 directory with 3 updates by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2462](https://github.com/actions/checkout/pull/2462)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIyMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: #26
Co-authored-by: Renovate Bot <renovate@unbound.se>
Co-committed-by: Renovate Bot <renovate@unbound.se>
2026-06-20 18:38:27 +00:00
renovate 8f0e3978b9 chore(config): migrate Renovate config (#25)
The Renovate config in this repository needs migrating. Typically this is because one or more configuration options you are using have been renamed.

  You don't need to merge this PR right away, because Renovate will continue to migrate these fields internally each time it runs. But later some of these fields may be fully deprecated and the migrations removed. So it's a good idea to merge this migration PR soon.

🔕 **Ignore**: Close this PR and you won't be reminded about config migration again, but one day your current config may no longer be valid.

 Got questions? Does something look wrong to you? Please don't hesitate to [request help here](https://github.com/renovatebot/renovate/discussions).

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).

Reviewed-on: #25
Co-authored-by: Renovate Bot <renovate@unbound.se>
Co-committed-by: Renovate Bot <renovate@unbound.se>
2026-05-25 10:35:28 +00:00
argoyle 1f9d754f61 fix(release): fetch file SHAs from base branch, not next-release (#24)
## 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
2026-05-13 11:10:44 +00:00
argoyle 51b3b980a3 fix(release): make Release.yml robust to curl exit codes (#23)
## 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
2026-05-13 10:53:38 +00:00
argoyle c39f11fda7 fix(release): poll branch readiness before .version write (#22)
## 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
2026-05-12 13:19:00 +00:00
renovate 0a42bcebe0 chore(deps): update dependency orhun/git-cliff to v2.13.1 (#21) 2026-04-29 11:10:38 +00:00
renovate ac96359966 chore(deps): update dependency orhun/git-cliff to v2.13.1 (#21) 2026-04-29 11:10:36 +00:00
renovate 3bc3f4790d chore(deps): update dependency orhun/git-cliff to v2.13.0 (#20) 2026-04-29 10:10:31 +00:00
argoyle e3c17ceaa0 fix: make release PR creation robust against race conditions (#19)
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
2026-03-23 15:52:25 +00:00
argoyle 068c6ef686 Merge pull request 'fix(release): add retry and delay for PR creation to handle Gitea API race condition' (#18) from fix-release-pr-race-condition into main
Reviewed-on: #18
2026-02-23 13:13:23 +00:00
argoyle d5623bdf9c fix(release): add retry and delay for PR creation to handle Gitea API race condition
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>
2026-02-23 14:12:43 +01:00
argoyle e3f1ba4e0a Merge pull request 'fix(release): replace rebase with branch recreation to prevent PR merge conflicts' (#17) from fix-release-pr-conflicts into main
Reviewed-on: #17
2026-02-12 11:02:43 +00:00
argoyle 4688810928 fix(release): replace rebase with branch recreation to prevent PR merge conflicts
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>
2026-02-12 12:02:01 +01:00
renovate 646d0e4e0c chore(deps): update dependency orhun/git-cliff to v2.12.0 (#16) 2026-01-20 17:38:12 +00:00
argoyle c564063d20 Merge pull request 'fix(release): add retry logic to curl API calls' (#15) from fix-curl-retry into main
Reviewed-on: #15
2026-01-14 14:14:24 +00:00
argoyle a9458d03dd fix(release): add retry logic to curl API calls
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>
2026-01-14 15:08:17 +01:00
argoyle 7802e99a9c Merge pull request 'feat(release): rebase PR branch before updating changelog' (#14) from feat-rebase-pr into main
Reviewed-on: #14
2026-01-09 20:10:09 +00:00
argoyle dafe37343f feat(release): rebase PR branch before updating changelog
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>
2026-01-09 21:09:21 +01:00
argoyle 33b839e26e Merge pull request 'feat(release): enhance release workflow with improvements' (#13) from fix-workflow-gitea-compat into main
Reviewed-on: #13
2026-01-09 06:39:11 +00:00
argoyle 4b25f5864d feat(release): enhance release workflow with improvements
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.
2026-01-09 07:38:33 +01:00
argoyle 91f60440e8 Merge pull request 'chore(deps): update dependency orhun/git-cliff to v2.11.0' (#10) from renovate/orhun-git-cliff-2.x into main
Reviewed-on: #10
2026-01-09 06:09:49 +00:00
renovate ce44701d56 chore(deps): update dependency orhun/git-cliff to v2.11.0 2026-01-09 04:13:22 +00:00
3 changed files with 185 additions and 136 deletions
+5 -1
View File
@@ -2,7 +2,11 @@
"permissions": { "permissions": {
"allow": [ "allow": [
"Bash(but --help:*)", "Bash(but --help:*)",
"Bash(but rub --help:*)" "Bash(but rub --help:*)",
"WebSearch",
"WebFetch(domain:docs.gitea.com)",
"WebFetch(domain:gitea.com)",
"Bash(but status:*)"
] ]
} }
} }
+177 -134
View File
@@ -9,10 +9,14 @@ on:
default: false default: false
type: boolean type: boolean
concurrency:
group: release-${{ github.repository }}
cancel-in-progress: false
env: env:
GITEA_URL: http://gitea-http.gitea.svc.cluster.local:3000 GITEA_URL: http://gitea-http.gitea.svc.cluster.local:3000
RELEASE_TOKEN_FILE: /runner-secrets/release-token RELEASE_TOKEN_FILE: /runner-secrets/release-token
GIT_CLIFF_VERSION: "2.10.1" GIT_CLIFF_VERSION: "2.13.1"
jobs: jobs:
preconditions: preconditions:
@@ -39,7 +43,7 @@ jobs:
if: github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch if: github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v7
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -83,144 +87,184 @@ jobs:
OWNER=$(echo "${REPOSITORY}" | cut -d'/' -f1) OWNER=$(echo "${REPOSITORY}" | cut -d'/' -f1)
REPO=$(echo "${REPOSITORY}" | cut -d'/' -f2) REPO=$(echo "${REPOSITORY}" | cut -d'/' -f2)
API_URL="${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}" API_URL="${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}"
BASE_BRANCH="${DEFAULT_BRANCH:-main}"
echo "Using base branch: ${BASE_BRANCH}"
TITLE="chore(release): prepare for ${VERSION}" TITLE="chore(release): prepare for ${VERSION}"
# Read CHANGES.md and escape for JSON CHANGES_CONTENT=$(cat CHANGES.md)
DESCRIPTION=$(cat CHANGES.md | jq -Rs .) PR_NOTE="**Note:** Please use **Squash Merge** when merging this PR."
DESCRIPTION="${DESCRIPTION:1:-1}" # Remove surrounding quotes from jq DESCRIPTION="${CHANGES_CONTENT}"$'\n\n---\n\n'"${PR_NOTE}"
# Add squash merge reminder
DESCRIPTION="${DESCRIPTION}
---
**Note:** Please use **Squash Merge** when merging this PR."
echo "Checking for existing release PRs..."
PRS=$(curl -sf \
-H "Authorization: token ${TOKEN}" \
"${API_URL}/pulls?state=open" | jq '[.[] | select(.head.ref == "next-release")]')
PR_INDEX=$(echo "${PRS}" | jq -r '.[0].number // empty')
echo "Checking for existing next-release branch..."
BRANCH_EXISTS=$(curl -sf \
-H "Authorization: token ${TOKEN}" \
"${API_URL}/branches/next-release" 2>/dev/null && echo "true" || echo "false")
# Prepare CHANGELOG.md content
CHANGELOG_CONTENT=$(base64 -w0 < CHANGELOG.md) CHANGELOG_CONTENT=$(base64 -w0 < CHANGELOG.md)
VERSION_CONTENT=$(jq -n --arg v "${VERSION}" '{"version":$v}' | base64 -w0)
# Prepare .version content # api_call METHOD PATH [JSON_BODY]
VERSION_JSON=$(jq -n --arg v "${VERSION}" '{"version":$v}') # Stdout: first line "<http_code>|<curl_rc>", then response body.
VERSION_CONTENT=$(echo "${VERSION_JSON}" | base64 -w0) # Never returns non-zero so callers must inspect http_code; this
# prevents curl exit codes (e.g. CURLE_WRITE_ERROR / 23) from
if [ "${BRANCH_EXISTS}" = "true" ]; then # killing the script via `set -e` inside command substitutions.
echo "Updating existing next-release branch..." api_call() {
local method="$1" path="$2" data="${3:-}"
# Get SHA of existing CHANGELOG.md local body_file http_code rc=0
CHANGELOG_SHA=$(curl -sf \ body_file=$(mktemp)
-H "Authorization: token ${TOKEN}" \ local args=(-sS --retry 3 --retry-delay 2 --retry-all-errors
"${API_URL}/contents/CHANGELOG.md?ref=next-release" | jq -r '.sha // empty') -w '%{http_code}'
-o "${body_file}"
# Update or create CHANGELOG.md -X "${method}"
if [ -n "${CHANGELOG_SHA}" ]; then -H "Authorization: token ${TOKEN}")
curl -sf -X PUT \ if [ -n "${data}" ]; then
-H "Authorization: token ${TOKEN}" \ args+=(-H "Content-Type: application/json" --data "${data}")
-H "Content-Type: application/json" \
--data "$(jq -n \
--arg content "${CHANGELOG_CONTENT}" \
--arg sha "${CHANGELOG_SHA}" \
--arg message "${TITLE}" \
--arg branch "next-release" \
'{content: $content, sha: $sha, message: $message, branch: $branch}')" \
"${API_URL}/contents/CHANGELOG.md"
else
curl -sf -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
--data "$(jq -n \
--arg content "${CHANGELOG_CONTENT}" \
--arg message "${TITLE}" \
--arg branch "next-release" \
'{content: $content, message: $message, branch: $branch, new_branch: $branch}')" \
"${API_URL}/contents/CHANGELOG.md"
fi fi
http_code=$(curl "${args[@]}" "${API_URL}${path}" 2>/dev/null) || rc=$?
printf '%s|%s\n' "${http_code:-000}" "${rc}"
cat "${body_file}"
rm -f "${body_file}"
return 0
}
# Get SHA of existing .version # Extract first-line meta and remaining body from api_call output.
VERSION_SHA=$(curl -sf \ meta_line() { printf '%s\n' "$1" | head -n1; }
-H "Authorization: token ${TOKEN}" \ body_lines() { printf '%s\n' "$1" | tail -n +2; }
"${API_URL}/contents/.version?ref=next-release" | jq -r '.sha // empty') http_of() { local m; m=$(meta_line "$1"); printf '%s' "${m%%|*}"; }
ok_code() { [ -n "$1" ] && [ "$1" -ge 200 ] 2>/dev/null && [ "$1" -lt 400 ]; }
# Update or create .version # Delete existing next-release branch if it exists (auto-closes any open PR)
if [ -n "${VERSION_SHA}" ]; then echo "Checking for existing next-release branch..."
curl -sf -X PUT \ OUT=$(api_call GET "/branches/next-release")
-H "Authorization: token ${TOKEN}" \ CODE=$(http_of "${OUT}")
-H "Content-Type: application/json" \ if [ "${CODE}" = "200" ]; then
--data "$(jq -n \ echo "Deleting existing next-release branch..."
--arg content "${VERSION_CONTENT}" \ OUT=$(api_call DELETE "/branches/next-release")
--arg sha "${VERSION_SHA}" \ echo " delete result: $(meta_line "${OUT}")"
--arg message "${TITLE}" \
--arg branch "next-release" \
'{content: $content, sha: $sha, message: $message, branch: $branch}')" \
"${API_URL}/contents/.version"
else
curl -sf -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
--data "$(jq -n \
--arg content "${VERSION_CONTENT}" \
--arg message "${TITLE}" \
--arg branch "next-release" \
'{content: $content, message: $message, branch: $branch}')" \
"${API_URL}/contents/.version"
fi
else else
echo "Creating new next-release branch with CHANGELOG.md..." echo " no existing branch (HTTP ${CODE})"
curl -sf -X POST \ fi
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
--data "$(jq -n \
--arg content "${CHANGELOG_CONTENT}" \
--arg message "${TITLE}" \
--arg branch "${DEFAULT_BRANCH}" \
--arg new_branch "next-release" \
'{content: $content, message: $message, branch: $branch, new_branch: $new_branch}')" \
"${API_URL}/contents/CHANGELOG.md"
echo "Adding .version to next-release branch..." # Explicitly create next-release branch from base
curl -sf -X POST \ echo "Creating next-release branch from ${BASE_BRANCH}..."
-H "Authorization: token ${TOKEN}" \ BRANCH_PAYLOAD=$(jq -n --arg new "next-release" --arg old "${BASE_BRANCH}" \
-H "Content-Type: application/json" \ '{new_branch_name: $new, old_branch_name: $old}')
--data "$(jq -n \ for i in $(seq 1 5); do
--arg content "${VERSION_CONTENT}" \ OUT=$(api_call POST "/branches" "${BRANCH_PAYLOAD}")
META=$(meta_line "${OUT}"); BODY=$(body_lines "${OUT}"); CODE="${META%%|*}"
if ok_code "${CODE}"; then
echo "Branch created (${META})"
break
fi
if [ "${i}" = "5" ]; then
echo "Branch create failed after 5 attempts (${META}): ${BODY}"
exit 1
fi
echo " attempt ${i}/5 (${META}): ${BODY} — retrying..."
sleep 3
done
# Poll until branch is readable
echo "Waiting for branch readiness..."
for i in $(seq 1 10); do
OUT=$(api_call GET "/branches/next-release")
META=$(meta_line "${OUT}"); CODE="${META%%|*}"
if [ "${CODE}" = "200" ]; then
echo "Branch ready after ${i} attempt(s)"
break
fi
if [ "${i}" = "10" ]; then
echo "Branch not ready after 10 attempts (last: ${META})"
exit 1
fi
echo " attempt ${i}/10 (${META}) — waiting..."
sleep 2
done
# 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
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")
# Write file with retry. Args: PATH CONTENT_B64 [SHA]
write_file() {
local path="$1" content="$2" sha="${3:-}"
local method payload out meta body code
if [ -n "${sha}" ]; then
method=PUT
payload=$(jq -n \
--arg content "${content}" \
--arg sha "${sha}" \
--arg message "${TITLE}" \ --arg message "${TITLE}" \
--arg branch "next-release" \ --arg branch "next-release" \
'{content: $content, message: $message, branch: $branch}')" \ '{content: $content, sha: $sha, message: $message, branch: $branch}')
"${API_URL}/contents/.version" else
fi method=POST
payload=$(jq -n \
--arg content "${content}" \
--arg message "${TITLE}" \
--arg branch "next-release" \
'{content: $content, message: $message, branch: $branch}')
fi
for i in $(seq 1 5); do
out=$(api_call "${method}" "/contents/${path}" "${payload}")
meta=$(meta_line "${out}"); body=$(body_lines "${out}"); code="${meta%%|*}"
if ok_code "${code}"; then
echo "${path} write succeeded (${meta})"
return 0
fi
if [ "${i}" = "5" ]; then
echo "${path} write failed after 5 attempts (${meta}): ${body}"
return 1
fi
echo " ${path} attempt ${i}/5 (${meta}): ${body} — retrying..."
sleep 3
done
}
if [ -n "${PR_INDEX}" ]; then echo "Writing CHANGELOG.md to next-release..."
echo "Updating existing PR #${PR_INDEX}..." write_file "CHANGELOG.md" "${CHANGELOG_CONTENT}" "${CHANGELOG_SHA}"
curl -sf -X PATCH \ echo "Writing .version to next-release..."
-H "Authorization: token ${TOKEN}" \ write_file ".version" "${VERSION_CONTENT}" "${VERSION_SHA}"
-H "Content-Type: application/json" \
--data "$(jq -n \ # Create PR
--arg title "${TITLE}" \ echo "Creating PR..."
--arg body "${DESCRIPTION}" \ PR_DATA=$(jq -n \
'{title: $title, body: $body}')" \ --arg title "${TITLE}" \
"${API_URL}/pulls/${PR_INDEX}" --arg body "${DESCRIPTION}" \
else --arg head "next-release" \
echo "Creating new PR..." --arg base "${BASE_BRANCH}" \
curl -sf -X POST \ '{title: $title, body: $body, head: $head, base: $base}')
-H "Authorization: token ${TOKEN}" \ for i in $(seq 1 5); do
-H "Content-Type: application/json" \ OUT=$(api_call POST "/pulls" "${PR_DATA}")
--data "$(jq -n \ META=$(meta_line "${OUT}"); BODY=$(body_lines "${OUT}"); CODE="${META%%|*}"
--arg title "${TITLE}" \ if ok_code "${CODE}"; then
--arg body "${DESCRIPTION}" \ echo "PR created (${META})"
--arg head "next-release" \ break
--arg base "${DEFAULT_BRANCH}" \ fi
'{title: $title, body: $body, head: $head, base: $base}')" \ if [ "${i}" = "5" ]; then
"${API_URL}/pulls" echo "PR creation failed after 5 attempts (${META}): ${BODY}"
fi exit 1
fi
echo " PR attempt ${i}/5 (${META}): ${BODY} — retrying..."
sleep 3
done
create-release: create-release:
name: Create Release name: Create Release
@@ -232,7 +276,7 @@ jobs:
inputs.tag_only != true inputs.tag_only != true
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v7
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -275,11 +319,10 @@ jobs:
REPO=$(echo "${REPOSITORY}" | cut -d'/' -f2) REPO=$(echo "${REPOSITORY}" | cut -d'/' -f2)
API_URL="${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}" API_URL="${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}"
MESSAGE=$(cat CHANGES.md | jq -Rs .) MESSAGE=$(cat CHANGES.md)
MESSAGE="${MESSAGE:1:-1}" # Remove surrounding quotes
echo "Creating release ${VERSION}..." echo "Creating release ${VERSION}..."
curl -sf -X POST \ curl -sf --retry 3 --retry-delay 2 --retry-connrefused -X POST \
-H "Authorization: token ${TOKEN}" \ -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
--data "$(jq -n \ --data "$(jq -n \
@@ -300,7 +343,7 @@ jobs:
inputs.tag_only == true inputs.tag_only == true
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v7
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -341,7 +384,7 @@ jobs:
API_URL="${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}" API_URL="${GITEA_URL}/api/v1/repos/${OWNER}/${REPO}"
echo "Creating tag ${VERSION}..." echo "Creating tag ${VERSION}..."
curl -sf -X POST \ curl -sf --retry 3 --retry-delay 2 --retry-connrefused -X POST \
-H "Authorization: token ${TOKEN}" \ -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
--data "$(jq -n \ --data "$(jq -n \
+3 -1
View File
@@ -6,7 +6,9 @@
"customManagers": [ "customManagers": [
{ {
"customType": "regex", "customType": "regex",
"fileMatch": ["^\\.gitea/workflows/.*\\.ya?ml$"], "managerFilePatterns": [
"/^\\.gitea/workflows/.*\\.ya?ml$/"
],
"matchStrings": [ "matchStrings": [
"GIT_CLIFF_VERSION:\\s*[\"']?(?<currentValue>[^\"'\\s]+)[\"']?" "GIT_CLIFF_VERSION:\\s*[\"']?(?<currentValue>[^\"'\\s]+)[\"']?"
], ],