fix(ci): publish tag builds to the release, where they can be fetched back

Run artifacts upload fine, but this Gitea reports zero artifacts for every run
through its REST API, and the web download route answers "Not found." under
token, bearer and basic auth alike. A signed build was therefore unreachable
from anywhere except the browser session that produced it.

Release assets do work: create, upload, list and download all round-trip with
an ordinary token, so tag builds now attach their output to the tag's release
as well as to the run. Retrieval must use browser_download_url; the asset-id
API path returns the asset's JSON metadata even when asked for octet-stream.

The step is fail-safe on purpose. With no token, no resolvable release, or a
non-201 upload it explains itself and exits 0 rather than turning a green
build red. The macOS upload also gains if-no-files-found, without which an
empty publish passes silently.
This commit is contained in:
jwinterm
2026-09-13 13:18:22 -04:00
parent ce84b1d062
commit a43e9fe122
2 changed files with 82 additions and 0 deletions
+38
View File
@@ -154,3 +154,41 @@ jobs:
name: wowlet-x86_64-linux-AppImage
path: wowlet-x86_64.AppImage
if-no-files-found: error
- name: publish the AppImage to the tag's release
# The artifact above uploads fine but this Gitea's REST listing reports
# zero artifacts for every run, so a tag build's output cannot be fetched
# back through the API. Release assets can, so publish there as well.
# Fail-safe by design: with no usable token this says why and exits 0,
# it never turns a green build red.
if: startsWith(github.ref, 'refs/tags/')
env:
RELEASE_TOKEN: ${{ github.token }}
run: |
set -eu
FILE=wowlet-x86_64.AppImage
TAG="${GITHUB_REF#refs/tags/}"
API="${GITHUB_SERVER_URL:-https://git.such.software}/api/v1/repos/$GITHUB_REPOSITORY"
if [ -z "${RELEASE_TOKEN:-}" ]; then
echo "no token available to this runner, skipping the release upload" >&2
exit 0
fi
H="Authorization: token $RELEASE_TOKEN"
# Single-line python on purpose: a continuation line at column 0 would
# end this block scalar and break the workflow's YAML. `|| true` keeps
# a malformed response from aborting the step under `set -e`.
rid=$(curl -sS -H "$H" "$API/releases/tags/$TAG" | python3 -c "import json,sys;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
if [ -z "$rid" ]; then
rid=$(curl -sS -H "$H" -H "Content-Type: application/json" -X POST \
-d "{\"tag_name\":\"$TAG\",\"name\":\"wowlet $TAG\"}" "$API/releases" | python3 -c "import json,sys;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
fi
if [ -z "$rid" ]; then
echo "could not resolve or create a release for $TAG, skipping the upload" >&2
exit 0
fi
code=$(curl -sS -H "$H" -o /dev/null -w '%{http_code}' -X POST \
-F "attachment=@$FILE" "$API/releases/$rid/assets?name=$(basename "$FILE")")
echo "release asset upload returned HTTP $code"
if [ "$code" != "201" ]; then
echo "the release upload did not return 201; the run artifact still holds the build" >&2
fi
+44
View File
@@ -247,3 +247,47 @@ jobs:
name: wowlet-macos
path: build/wowlet-macos-*.zip
retention-days: 14
# Without this an empty upload passes silently, which is how a signed
# build can appear to publish while shipping nothing.
if-no-files-found: error
- name: publish the signed zip to the tag's release
# Same reason as the Linux job: run artifacts upload but this Gitea's
# REST listing returns zero for every run, so the notarized zip cannot
# be fetched back through the API. Release assets can be. Fail-safe:
# with no usable token this says why and exits 0.
if: startsWith(github.ref, 'refs/tags/')
env:
RELEASE_TOKEN: ${{ github.token }}
run: |
set -eu
FILE=$(ls build/wowlet-macos-*.zip 2>/dev/null | head -1)
if [ -z "$FILE" ]; then
echo "no macOS zip to publish; the packaging step should have failed first" >&2
exit 0
fi
TAG="${GITHUB_REF#refs/tags/}"
API="${GITHUB_SERVER_URL:-https://git.such.software}/api/v1/repos/$GITHUB_REPOSITORY"
if [ -z "${RELEASE_TOKEN:-}" ]; then
echo "no token available to this runner, skipping the release upload" >&2
exit 0
fi
H="Authorization: token $RELEASE_TOKEN"
# Single-line python on purpose: a continuation line at column 0 would
# end this block scalar and break the workflow's YAML. `|| true` keeps
# a malformed response from aborting the step under `set -e`.
rid=$(curl -sS -H "$H" "$API/releases/tags/$TAG" | python3 -c "import json,sys;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
if [ -z "$rid" ]; then
rid=$(curl -sS -H "$H" -H "Content-Type: application/json" -X POST \
-d "{\"tag_name\":\"$TAG\",\"name\":\"wowlet $TAG\"}" "$API/releases" | python3 -c "import json,sys;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
fi
if [ -z "$rid" ]; then
echo "could not resolve or create a release for $TAG, skipping the upload" >&2
exit 0
fi
code=$(curl -sS -H "$H" -o /dev/null -w '%{http_code}' -X POST \
-F "attachment=@$FILE" "$API/releases/$rid/assets?name=$(basename "$FILE")")
echo "release asset upload returned HTTP $code"
if [ "$code" != "201" ]; then
echo "the release upload did not return 201; the run artifact still holds the build" >&2
fi