name: Release # 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 # maintainer reviews, commits, and tags *before* pushing the tag (see that # 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/). 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 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). on: push: tags: - "v*.*.*" 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 Gitea Release needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Download built packages uses: actions/download-artifact@v3 with: name: ${{ needs.build.outputs.artifact-name }} path: dist - name: Re-verify checksums run: scripts/checksums.sh dist - name: Verify plugin/podman.plg matches these artifacts # scripts/release.sh should already have been run locally, and its # resulting podman.plg changes committed as part of this tag, before # the tag was pushed. This step fails the release loudly if that # didn't happen, instead of publishing a release whose plg points at # MD5s that don't match the .txz files actually attached below. run: | set -eu for f in dist/*.txz.md5; do expected_md5=$(awk '{print $1}' "$f") txz_name=$(basename "${f%.md5}") if ! grep -qF "$expected_md5" plugin/podman.plg; then echo "!! $txz_name's checksum ($expected_md5) is not referenced in plugin/podman.plg." >&2 echo "!! Did you forget to run scripts/release.sh and commit its changes before tagging?" >&2 exit 1 fi done echo "All package checksums are referenced in plugin/podman.plg — OK." - name: Extract version from tag id: version run: echo "value=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" - name: Extract changelog section for this version id: changelog run: | awk -v ver="${{ steps.version.outputs.value }}" ' $0 ~ "^## \\[" ver "\\]" { found=1; print; next } found && /^## \[/ { exit } found { print } ' CHANGELOG.md > /tmp/release-notes.md echo "path=/tmp/release-notes.md" >> "$GITHUB_OUTPUT" - 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}" # Every release is a normal release, not a "pre-release" — the # earlier 0.x-is-always-prerelease default didn't match what # this project actually wants published (v0.1.3 was explicitly # corrected off "pre-release" after the fact). prerelease=false # 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}"