From 26da114e0e0c10184e24e6b03b6750444ff36c84 Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 20 Jul 2026 15:29:54 +0200 Subject: [PATCH] fix: use curl+jq instead of Python for release creation Eliminates potential Python/heredoc issues in Gitea Actions runner. Full clone guarantees git history is available for changelog. --- .gitea/workflows/release.yaml | 111 ++++++++++++++-------------------- 1 file changed, 45 insertions(+), 66 deletions(-) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index fc835774..de052bb4 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -14,28 +14,28 @@ jobs: GITEA_REPO: ${{ gitea.repository }} run: | set -e + exec 2>&1 + + echo "=== VERSION=${VERSION} ===" + echo "=== API=${GITEA_API} ===" + echo "=== REPO=${GITEA_REPO} ===" SRC="/tmp/epicnext-release" rm -rf "$SRC" - - # Full clone for changelog + build (local bare repo = instant) git clone --branch "${VERSION}" \ /docker/gitea/gitea/git/repositories/remco/epicnext-cms.git \ - "$SRC" + "$SRC" 2>&1 cd "$SRC" + echo "=== Cloned ===" - # Generate changelog PREV_TAG="$(git tag --sort=-creatordate | head -2 | tail -1 || echo '')" echo "=== Tags ===" git tag --sort=-creatordate - echo "=== Version=${VERSION} Previous=${PREV_TAG} ===" + echo "=== Previous=${PREV_TAG} ===" if [ -n "$PREV_TAG" ] && [ "$PREV_TAG" != "$VERSION" ]; then - RANGE="${PREV_TAG}..${VERSION}" - echo "=== Range: ${RANGE} ===" - git log --oneline --no-decorate "${RANGE}" > /tmp/changelog.txt + git log --oneline --no-decorate "${PREV_TAG}..${VERSION}" > /tmp/changelog.txt else - echo "=== First release, showing all commits ===" git log --oneline --no-decorate "${VERSION}" > /tmp/changelog.txt fi @@ -43,74 +43,53 @@ jobs: cat /tmp/changelog.txt echo "=== End ===" - # Build if [ -f /var/www/atom-nexst/.env ]; then cp /var/www/atom-nexst/.env "$SRC/.env" fi - pnpm install --frozen-lockfile - pnpm prisma:generate + pnpm install --frozen-lockfile 2>&1 + pnpm prisma:generate 2>&1 export SKIP_ENV_VALIDATION=1 - pnpm build + pnpm build 2>&1 - # Create release via API - python3 << 'PYEOF' -import json, os, urllib.request, urllib.error + echo "=== Creating release ===" + NOTES="$(cat /tmp/changelog.txt)" + [ -z "$NOTES" ] && NOTES="Initial release" -version = os.environ["VERSION"] -api = os.environ["GITEA_API"] -repo = os.environ["GITEA_REPO"] -token = "${{ secrets.GITEA_TOKEN }}" - -with open("/tmp/changelog.txt") as f: - notes = f.read().strip() or "Initial release" - -print(f"Changelog: {len(notes)} chars") - -body = f"""## EpicNext-CMS {version} + # Build JSON with jq, send with curl + BODY="## EpicNext-CMS ${VERSION} ### Changes -{notes} +${NOTES} --- *Automated release from Gitea Actions* -""" +" -payload = json.dumps({ - "tag_name": version, - "name": version, - "body": body, - "draft": False, - "prerelease": False, -}).encode("utf-8") + PAYLOAD="$(echo "$BODY" | jq -Rs '{tag_name: $v, name: $v, body: ., draft: false, prerelease: false}' --arg v "${VERSION}")" + echo "Payload length: ${#PAYLOAD}" -def api_call(method, path, data=None): - url = f"{api}/repos/{repo}/{path}" - print(f"{method} {url}") - req = urllib.request.Request( - url, data=data, - headers={ - "Authorization": f"token {token}", - "Content-Type": "application/json", - }, - method=method, - ) - resp = urllib.request.urlopen(req) - return json.loads(resp.read().decode("utf-8")) + RESP="$(curl -s -w '\n%{http_code}' -X POST \ + "${GITEA_API}/repos/${GITEA_REPO}/releases" \ + -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \ + -H "Content-Type: application/json" \ + -d "$PAYLOAD")" + HTTP_CODE="$(echo "$RESP" | tail -1)" + RESP_BODY="$(echo "$RESP" | head -n -1)" + echo "HTTP ${HTTP_CODE}: ${RESP_BODY:0:200}" -try: - result = api_call("POST", "releases", payload) - print(f"OK: {result.get('html_url', result.get('id', '?'))}") -except urllib.error.HTTPError as e: - err_body = e.read().decode("utf-8") - print(f"POST {e.code}") - if e.code == 409: - releases = api_call("GET", "releases") - for rel in releases: - if rel["tag_name"] == version: - result = api_call("PATCH", f"releases/{rel['id']}", payload) - print(f"Updated: {result.get('html_url', result.get('id', '?'))}") - break - else: - print(f"API ERROR: {err_body}") - raise -PYEOF + if [ "$HTTP_CODE" = "409" ] || [ "$HTTP_CODE" = "409" ]; then + # Release exists — update it + RELEASES="$(curl -sf "${GITEA_API}/repos/${GITEA_REPO}/releases" \ + -H "Authorization: token ${{ secrets.GITEA_TOKEN }}")" + REL_ID="$(echo "$RELEASES" | jq -r ".[] | select(.tag_name==\"${VERSION}\") | .id")" + if [ -n "$REL_ID" ] && [ "$REL_ID" != "null" ]; then + RESP2="$(curl -s -w '\n%{http_code}' -X PATCH \ + "${GITEA_API}/repos/${GITEA_REPO}/releases/${REL_ID}" \ + -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \ + -H "Content-Type: application/json" \ + -d "$PAYLOAD")" + echo "PATCH result: $(echo "$RESP2" | tail -1)" + fi + fi + + echo "=== Done ==="