feat(install): default installers to the latest release via releases/latest

The on-device and Raspberry Pi installers hardcoded the release version, which
had to be bumped on every release. Default VERSION to empty and resolve the
newest tag by following GitHub's documented stable redirect
(https://github.com/<repo>/releases/latest -> .../releases/tag/vX.Y.Z), reading
the effective URL. This avoids the GitHub API rate limit and needs no jq.

An explicit version (positional arg / VERSION= / --version) still pins a
release. If the lookup fails (offline, rate-limited, or a curl without -w
support), each script falls back to a pinned FALLBACK_VERSION so installs still
work. The Pi self_update path runs after resolution, so it fetches the resolved
tag's installer.

Docs updated to state the default installs the latest release; the pinned-version
examples remain as illustrations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-06-25 09:47:19 +02:00
co-authored by Claude Opus 4.8
parent 01ebbb102d
commit ea7f6f36ef
8 changed files with 133 additions and 17 deletions
+3 -1
View File
@@ -26,7 +26,9 @@ curl -fsSL -o install-player.sh \
sudo bash install-player.sh
```
Pass a version tag as the first argument to pin a specific release:
Both install the **latest release** by default (resolved from GitHub's
`releases/latest` redirect). Pass a version tag as the first argument to pin a
specific release:
```bash
sudo bash install.sh v0.111.3
+43 -3
View File
@@ -32,11 +32,16 @@ set -euo pipefail
# - Safe to re-run; it will update the binary, env file, and unit and restart.
# ==============================================================================
VERSION="${1:-${VERSION:-v0.111.3}}"
# Normalize version prefix
if [[ ! "$VERSION" =~ ^v ]]; then
# Release to install. Empty means "resolve the latest release" (see
# resolve_version). Pass a tag/number as $1 or VERSION=... to pin a release.
VERSION="${1:-${VERSION:-}}"
# Normalize version prefix for an explicitly provided version.
if [[ -n "$VERSION" && ! "$VERSION" =~ ^v ]]; then
VERSION="v${VERSION}"
fi
GH_REPO="${GH_REPO:-gesellix/Bose-SoundTouch}"
# Used only when the latest-release lookup fails (offline / rate-limited).
FALLBACK_VERSION="${FALLBACK_VERSION:-v0.111.3}"
SERVICE_NAME="${SERVICE_NAME:-soundtouch-player}"
BIN_PATH="${BIN_PATH:-/usr/local/bin/soundtouch-player}"
@@ -157,6 +162,40 @@ download_binary() {
log "Installed binary to ${BIN_PATH}"
}
resolve_version() {
# When no explicit version was given, resolve the latest release tag by
# following the documented stable redirect:
# https://github.com/<owner>/<repo>/releases/latest
# which 302-redirects to .../releases/tag/vX.Y.Z. We read the final URL and
# take the tag from it. Falls back to FALLBACK_VERSION on any failure
# (offline, rate-limited, no usable curl/wget).
if [[ -n "$VERSION" ]]; then
return
fi
local latest_url="https://github.com/${GH_REPO}/releases/latest"
log "Resolving latest release via ${latest_url}"
local effective="" tag=""
if command -v curl >/dev/null 2>&1; then
effective="$(curl -fsSLI -o /dev/null -w '%{url_effective}' "$latest_url" 2>/dev/null)" || true
else
# wget: don't follow the redirect, read the Location header instead.
effective="$(wget -S --max-redirect=0 -O /dev/null "$latest_url" 2>&1 \
| awk 'tolower($1) ~ /location:/ {print $2}' | tr -d '\r' | tail -1)" || true
fi
tag="${effective##*/}"
if [[ "$tag" =~ ^v?[0-9]+\.[0-9]+ ]]; then
[[ "$tag" =~ ^v ]] || tag="v${tag}"
VERSION="$tag"
log "Latest release is ${VERSION}"
else
VERSION="$FALLBACK_VERSION"
log "⚠️ Could not resolve latest release; falling back to ${VERSION}"
fi
}
self_update() {
if [[ "$IS_SELF_UPDATE" == "true" ]]; then
return
@@ -324,6 +363,7 @@ main() {
apt_install_if_missing curl
fi
resolve_version
self_update "$@"
ensure_user_group
+43 -3
View File
@@ -28,11 +28,16 @@ set -euo pipefail
# - Safe to re-run; it will update binary/config/unit and restart the service.
# ==============================================================================
VERSION="${1:-${VERSION:-v0.111.3}}"
# Normalize version prefix
if [[ ! "$VERSION" =~ ^v ]]; then
# Release to install. Empty means "resolve the latest release" (see
# resolve_version). Pass a tag/number as $1 or VERSION=... to pin a release.
VERSION="${1:-${VERSION:-}}"
# Normalize version prefix for an explicitly provided version.
if [[ -n "$VERSION" && ! "$VERSION" =~ ^v ]]; then
VERSION="v${VERSION}"
fi
GH_REPO="${GH_REPO:-gesellix/Bose-SoundTouch}"
# Used only when the latest-release lookup fails (offline / rate-limited).
FALLBACK_VERSION="${FALLBACK_VERSION:-v0.111.3}"
SERVICE_NAME="${SERVICE_NAME:-soundtouch-service}"
BIN_PATH="${BIN_PATH:-/usr/local/bin/soundtouch-service}"
@@ -176,6 +181,40 @@ download_binary() {
log "Installed binary to ${BIN_PATH}"
}
resolve_version() {
# When no explicit version was given, resolve the latest release tag by
# following the documented stable redirect:
# https://github.com/<owner>/<repo>/releases/latest
# which 302-redirects to .../releases/tag/vX.Y.Z. We read the final URL and
# take the tag from it. Falls back to FALLBACK_VERSION on any failure
# (offline, rate-limited, no usable curl/wget).
if [[ -n "$VERSION" ]]; then
return
fi
local latest_url="https://github.com/${GH_REPO}/releases/latest"
log "Resolving latest release via ${latest_url}"
local effective="" tag=""
if command -v curl >/dev/null 2>&1; then
effective="$(curl -fsSLI -o /dev/null -w '%{url_effective}' "$latest_url" 2>/dev/null)" || true
else
# wget: don't follow the redirect, read the Location header instead.
effective="$(wget -S --max-redirect=0 -O /dev/null "$latest_url" 2>&1 \
| awk 'tolower($1) ~ /location:/ {print $2}' | tr -d '\r' | tail -1)" || true
fi
tag="${effective##*/}"
if [[ "$tag" =~ ^v?[0-9]+\.[0-9]+ ]]; then
[[ "$tag" =~ ^v ]] || tag="v${tag}"
VERSION="$tag"
log "Latest release is ${VERSION}"
else
VERSION="$FALLBACK_VERSION"
log "⚠️ Could not resolve latest release; falling back to ${VERSION}"
fi
}
self_update() {
# If we are already a self-update re-exec, don't do it again
if [[ "$IS_SELF_UPDATE" == "true" ]]; then
@@ -364,6 +403,7 @@ main() {
apt_install_if_missing curl
fi
resolve_version
self_update "$@"
ensure_user_group