From 5fb7376b641309525c7674bc73352c3c9bef6ff0 Mon Sep 17 00:00:00 2001 From: magges Date: Sun, 12 Jul 2026 22:57:21 +0000 Subject: [PATCH] Fix Release workflow: publish to Gitea's own API, not GitHub's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit softprops/action-gh-release talks to GitHub's REST API — it cannot publish anywhere else, so this workflow could never have actually published a release on this Gitea-hosted repo, reproducibility bug aside. Replaced the publish step with plain curl against Gitea's own /api/v1/repos/.../releases endpoints, using the repo-scoped token Gitea Actions already injects as secrets.GITHUB_TOKEN (same env var name as GitHub Actions, for exactly this kind of drop-in compatibility). Idempotent: deletes and recreates the release if one already exists for the tag, so a re-run after a transient failure doesn't just error on a duplicate tag. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/release.yml | 94 +++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 20 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b86c0ac..aa4f1c4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,10 @@ name: Release -# Publishes a GitHub Release for a version tag (vX.Y.Z). +# Publishes a Gitea Release for a version tag (vX.Y.Z). This project lives +# on a self-hosted Gitea instance (git.mp-mueller.de), not GitHub — despite +# the .github/workflows/ path (kept there because Gitea Actions picks up +# workflows from that path too, verified live: lint.yml/build-packages.yml +# both already run from here without any .gitea/workflows/ copy). # # By design, this workflow does NOT bump versions or modify podman.plg # itself — that happens locally via `scripts/release.sh `, which a @@ -8,12 +12,25 @@ name: Release # script's own printed instructions). This workflow's only job is to: # 1. Rebuild all packages from the tagged commit in a clean Slackware # container (reproducibility check + provenance — we don't trust -# whatever a maintainer happened to have in their local dist/). +# whatever a maintainer happened to have in their local dist/). This +# only actually verifies anything because +# scripts/lib/slackbuild-common.sh's sb_make_package() pins +# SOURCE_DATE_EPOCH to the tagged commit's timestamp before calling +# makepkg — without that, two separate builds of the identical commit +# produce byte-different .txz files (different file mtimes baked into +# the tar archive) and this whole verify step fails on the first +# package it happens to check, every time (found live: aardvark-dns). # 2. Verify checksums match what's already committed in plugin/podman.plg # at this tag (catches a release.sh run that wasn't followed by a # matching commit — see the "Verify plg matches build" step). -# 3. Create the GitHub Release and attach the .txz packages, checksum -# manifests, and podman.plg. +# 3. Create the Gitea Release and attach the .txz packages, checksum +# manifests, and podman.plg, via Gitea's own REST API — NOT +# softprops/action-gh-release, which talks to GitHub's API and simply +# cannot publish anywhere else. Gitea Actions injects a real, +# repo-scoped API token as secrets.GITHUB_TOKEN (the same env var +# name GitHub Actions uses, for exactly this kind of drop-in +# compatibility) — permissions: contents: write above is what scopes +# that token to allow creating releases. # # See docs/ARCHITECTURE.md section 13 (Updates). @@ -25,13 +42,17 @@ on: permissions: contents: write +env: + GITEA_HOST: git.mp-mueller.de + GITEA_REPO: magges/unraid-podman + jobs: build: name: Build release packages uses: ./.github/workflows/build-packages.yml publish: - name: Publish GitHub Release + name: Publish Gitea Release needs: build runs-on: ubuntu-latest steps: @@ -79,18 +100,51 @@ jobs: ' CHANGELOG.md > /tmp/release-notes.md echo "path=/tmp/release-notes.md" >> "$GITHUB_OUTPUT" - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 - with: - name: "unraid-podman v${{ steps.version.outputs.value }}" - body_path: ${{ steps.changelog.outputs.path }} - # v0.x tags are treated as pre-releases until the plugin reaches a - # first stable 1.0.0 — see docs/ROADMAP.md. - prerelease: ${{ startsWith(steps.version.outputs.value, '0.') }} - files: | - dist/*.txz - dist/*.sha256 - dist/*.md5 - dist/CHECKSUMS.sha256 - dist/CHECKSUMS.md5 - plugin/podman.plg + - name: Publish Gitea Release + env: + GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ github.ref_name }} + run: | + set -eu + API="https://${GITEA_HOST}/api/v1/repos/${GITEA_REPO}" + case "${{ steps.version.outputs.value }}" in + 0.*) prerelease=true ;; + *) prerelease=false ;; + esac + + # Idempotent: if a release for this tag already exists (e.g. a + # re-run after a transient failure), delete it first rather than + # erroring on Gitea's own duplicate-tag conflict. + existing_id=$(curl -s -H "Authorization: token ${GITEA_TOKEN}" "${API}/releases/tags/${TAG}" | jq -r '.id // empty') + if [ -n "$existing_id" ]; then + echo "==> Deleting existing release id=$existing_id for tag $TAG" + curl -s -X DELETE -H "Authorization: token ${GITEA_TOKEN}" "${API}/releases/${existing_id}" + fi + + body_json=$(jq -Rs '.' < "${{ steps.changelog.outputs.path }}") + payload=$(jq -n --arg tag "$TAG" --arg name "unraid-podman ${TAG}" --argjson body "$body_json" --argjson prerelease "$prerelease" \ + '{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: $prerelease}') + + release_id=$(curl -s -X POST -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" \ + -d "$payload" "${API}/releases" | jq -r '.id') + if [ -z "$release_id" ] || [ "$release_id" = "null" ]; then + echo "!! Could not create release (no id in response)" >&2 + exit 1 + fi + echo "==> Created release id=$release_id, uploading assets..." + + for f in dist/*.txz dist/*.sha256 dist/*.md5 dist/CHECKSUMS.sha256 dist/CHECKSUMS.md5 plugin/podman.plg; do + name=$(basename "$f") + code=$(curl -s -o /tmp/upload_resp.json -w '%{http_code}' -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -F "attachment=@${f};filename=${name}" \ + "${API}/releases/${release_id}/assets?name=${name}") + if [ "$code" != "201" ]; then + echo "!! Upload failed ($code) for $name:" >&2 + cat /tmp/upload_resp.json >&2 + exit 1 + fi + echo " uploaded: $name" + done + + echo "==> Published: https://${GITEA_HOST}/${GITEA_REPO}/releases/tag/${TAG}"