Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12cfca8b17 |
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# Maintains a rolling "latest" release whose AppImage always has the same
|
||||
# download URL, for updaters that poll a static URL (e.g. Shelly) instead of
|
||||
# understanding version tags:
|
||||
#
|
||||
# <server>/<owner>/<repo>/releases/download/latest/WhatsThatMusic-latest-linux-x86_64.AppImage
|
||||
#
|
||||
# Gitea serves ETag and Last-Modified on release assets, and replacing the
|
||||
# asset changes both, which is how those updaters detect a new build.
|
||||
# Gitea has no GitHub-style /releases/latest/download/ redirect, hence this.
|
||||
#
|
||||
# Marked as a pre-release so Gitea's own "latest release" stays the newest vX.Y.Z.
|
||||
#
|
||||
# Required env: TOKEN, API (…/api/v1/repos/<owner>/<repo>), GITHUB_REF_NAME, GITHUB_SHA
|
||||
# Optional env: ARTIFACTS_DIR (default: artifacts)
|
||||
set -euo pipefail
|
||||
|
||||
: "${TOKEN:?TOKEN is required}" "${API:?API is required}"
|
||||
: "${GITHUB_REF_NAME:?GITHUB_REF_NAME is required}" "${GITHUB_SHA:?GITHUB_SHA is required}"
|
||||
ARTIFACTS_DIR="${ARTIFACTS_DIR:-artifacts}"
|
||||
LATEST_TAG="latest"
|
||||
LATEST_NAME="WhatsThatMusic-latest-linux-x86_64.AppImage"
|
||||
|
||||
api() {
|
||||
local method="$1" path="$2"; shift 2
|
||||
local out code body
|
||||
out=$(curl -s -w '\n%{http_code}' -X "$method" -H "Authorization: token $TOKEN" "$API$path" "$@")
|
||||
code=$(printf '%s' "$out" | tail -n1)
|
||||
body=$(printf '%s' "$out" | sed '$d')
|
||||
if [ "$code" -ge 400 ]; then
|
||||
echo "$method $path -> HTTP $code" >&2
|
||||
echo "$body" >&2
|
||||
return 1
|
||||
fi
|
||||
printf '%s' "$body"
|
||||
}
|
||||
|
||||
appimage=$(find "$ARTIFACTS_DIR" -type f -name '*.AppImage' | sort | head -n1)
|
||||
if [ -z "$appimage" ]; then
|
||||
echo "No AppImage under $ARTIFACTS_DIR; cannot update the $LATEST_TAG release." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
body_json=$(node -e '
|
||||
console.log(JSON.stringify({
|
||||
body: "Rolling pointer to the newest AppImage, currently " + process.argv[1] + ". " +
|
||||
"The download URL for this asset never changes; versioned downloads are on each vX.Y.Z release.",
|
||||
}));' "$GITHUB_REF_NAME")
|
||||
|
||||
rolling_id=$(api GET "/releases/tags/$LATEST_TAG" 2>/dev/null \
|
||||
| node -pe "JSON.parse(require('fs').readFileSync(0,'utf8')).id" 2>/dev/null || true)
|
||||
|
||||
if [ -z "${rolling_id:-}" ]; then
|
||||
echo "No '$LATEST_TAG' release yet; creating it."
|
||||
create_json=$(node -e '
|
||||
console.log(JSON.stringify({
|
||||
tag_name: "latest", name: "Latest (rolling)", target_commitish: process.argv[1],
|
||||
prerelease: true, body: JSON.parse(process.argv[2]).body,
|
||||
}));' "$GITHUB_SHA" "$body_json")
|
||||
rolling_id=$(api POST "/releases" -H "Content-Type: application/json" -d "$create_json" \
|
||||
| node -pe "JSON.parse(require('fs').readFileSync(0,'utf8')).id")
|
||||
else
|
||||
api PATCH "/releases/$rolling_id" -H "Content-Type: application/json" -d "$body_json" >/dev/null
|
||||
fi
|
||||
|
||||
# Replace the asset: the new upload gets a new ETag and Last-Modified.
|
||||
old_id=$(api GET "/releases/$rolling_id/assets" \
|
||||
| node -pe "((JSON.parse(require('fs').readFileSync(0,'utf8'))).find(a => a.name === process.argv[1]) || {}).id || ''" "$LATEST_NAME")
|
||||
if [ -n "$old_id" ]; then
|
||||
api DELETE "/releases/$rolling_id/assets/$old_id" >/dev/null
|
||||
fi
|
||||
|
||||
echo "Uploading $LATEST_NAME from $(basename "$appimage") ($(du -h "$appimage" | cut -f1))"
|
||||
api POST "/releases/$rolling_id/assets?name=$LATEST_NAME" -F "attachment=@$appimage" >/dev/null
|
||||
echo "Updated '$LATEST_TAG' release ($rolling_id) to $GITHUB_REF_NAME"
|
||||
@@ -129,6 +129,9 @@ jobs:
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout first: it cleans the workspace, which would delete downloaded artifacts.
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: artifacts
|
||||
@@ -198,3 +201,12 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
echo "Attached $found artifacts to release $release_id"
|
||||
|
||||
# Constant-URL copy of the AppImage for updaters that poll a static URL
|
||||
# (e.g. Shelly). Runs after the versioned release exists, so a failure here
|
||||
# cannot leave a tag without its assets.
|
||||
- name: Update rolling "latest" AppImage
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITEA_TOKEN }}
|
||||
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
run: bash .gitea/scripts/update-latest.sh
|
||||
|
||||
Reference in New Issue
Block a user