ci: point the manifest at THIS build, and stop the dev release growing forever
Two halves of one mistake, both visible on the dev release right now: the manifest said 0.1.134 and pointed at ThoughtSync_0.1.132_amd64.AppImage. The rolling channel accumulates every build's assets, and the manifest picked its bundle by file extension with `head -1` — the OLDEST match. A client would have been told 0.1.134 was available, downloaded 0.1.132, installed it, and been offered 0.1.134 again. Forever. Signature verification could not have caught it. The old bundle's signature is perfectly valid for the old bundle; nothing about it says "this isn't the build the manifest claims". Selection is now matched on the build's own version string, so the manifest can only ever describe the binary it was written for. The accumulation is the other half. Nothing can reach a superseded build once the manifest moves on, and an AppImage is ~100 MB — three pushes had already left 300 MB of unreachable binaries on the Git host. A rolling channel now prunes everything but the current build once the manifest points at it. Versioned releases are untouched: that IS the archive, and the stable pointer's URLs aim into it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SreJkbxB4gx8pPsu8QbLPi
This commit is contained in:
@@ -336,6 +336,9 @@ jobs:
|
||||
if [ "${GITHUB_REF_NAME}" = "dev" ]; then
|
||||
export RELEASE_TAG=dev
|
||||
export RELEASE_NOTES="Development build from ${GITHUB_SHA}"
|
||||
# Rolling channel: drop the previous build's bundles once the manifest
|
||||
# points at this one. Nothing can reach them, and they're ~100 MB a push.
|
||||
export PRUNE_OLD_ASSETS=true
|
||||
APP_VERSION="$version" bash desktop/packaging/write-manifest.sh
|
||||
else
|
||||
export RELEASE_TAG="${GITHUB_REF_NAME}"
|
||||
|
||||
@@ -58,8 +58,18 @@ download_url() { printf '%s/%s/releases/download/%s/%s' "$GITHUB_SERVER_URL" "$G
|
||||
# install something it can't verify.
|
||||
platform_entry() {
|
||||
local target="$1" pattern="$2" bundle sig_name
|
||||
bundle="$(printf '%s\n' "$names" | grep -E "$pattern" | head -1 || true)"
|
||||
[ -n "$bundle" ] || { echo " no bundle matching $pattern — skipping $target" >&2; return; }
|
||||
# Matched on THIS build's version, not just the file extension.
|
||||
#
|
||||
# The rolling dev release accumulates every build's assets, and picking the first
|
||||
# extension match returned the OLDEST one — so the manifest advertised the new
|
||||
# version while pointing at an old binary. The client would install the older
|
||||
# build, still be told the newer version was available, and update forever. The
|
||||
# signature check couldn't catch it either: the old bundle's signature is
|
||||
# perfectly valid FOR THE OLD BUNDLE.
|
||||
bundle="$(printf '%s\n' "$names" | grep -F "_${APP_VERSION}_" | grep -E "$pattern" | head -1 || true)"
|
||||
# A hard failure, not a skip: reaching here means this platform's build didn't
|
||||
# upload, and the whole point is to never advertise a bundle that isn't there.
|
||||
[ -n "$bundle" ] || { echo " no $APP_VERSION bundle matching $pattern — skipping $target" >&2; return; }
|
||||
sig_name="$bundle.sig"
|
||||
if ! printf '%s\n' "$names" | grep -qxF "$sig_name"; then
|
||||
echo " $bundle has no $sig_name — skipping $target (was the build signed?)" >&2
|
||||
@@ -140,3 +150,31 @@ curl -fsS -X POST "${AUTH[@]}" "$API/releases/$target_id/assets?name=latest.json
|
||||
-F "attachment=@$work/latest.json" >/dev/null
|
||||
|
||||
echo "==> Done. $MANIFEST_TAG now advertises $APP_VERSION for ${#entries[@]} platform(s)."
|
||||
|
||||
# --- prune superseded builds from a rolling channel ---------------------------
|
||||
#
|
||||
# The dev release is republished on every push and its assets otherwise accumulate
|
||||
# forever — an AppImage alone is ~100 MB, so a week of pushes is gigabytes on the
|
||||
# Git host for builds nobody can reach (the manifest only ever names the newest).
|
||||
#
|
||||
# Only for a rolling channel. A versioned release must keep its assets: that IS the
|
||||
# archive, and the stable pointer's URLs aim at it.
|
||||
if [ "${PRUNE_OLD_ASSETS:-false}" = "true" ]; then
|
||||
echo "==> Pruning superseded assets from $RELEASE_TAG"
|
||||
# Re-read: the manifest upload above changed the asset list.
|
||||
current="$(curl -sS "${AUTH[@]}" "$API/releases/$release_id/assets")"
|
||||
printf '%s' "$current" \
|
||||
| grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+[^}]*"name"[[:space:]]*:[[:space:]]*"[^"]+"' \
|
||||
| while IFS= read -r row; do
|
||||
asset_id="$(printf '%s' "$row" | grep -oE '[0-9]+' | head -1)"
|
||||
asset_name="$(printf '%s' "$row" | sed -E 's/.*"name"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')"
|
||||
# Keep the manifest itself and everything belonging to the current build.
|
||||
case "$asset_name" in
|
||||
latest.json) continue ;;
|
||||
*"$APP_VERSION"*) continue ;;
|
||||
esac
|
||||
echo " removing $asset_name"
|
||||
curl -fsS -X DELETE "${AUTH[@]}" "$API/releases/$release_id/assets/$asset_id" >/dev/null || \
|
||||
echo " (couldn't remove $asset_name — leaving it)" >&2
|
||||
done
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user