Fix Release workflow: publish to Gitea's own API, not GitHub's
Lint / ShellCheck (push) Successful in 10s
Lint / Validate .plg XML (push) Successful in 9s
Lint / EditorConfig (push) Successful in 5s

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 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 22:57:21 +00:00
co-authored by Claude Sonnet 5
parent 7f6fcb9166
commit 5fb7376b64
+74 -20
View File
@@ -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 <version>`, 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}"