Merge pull request 'The release-rebuild prune called a helper that cannot exist in a release rebuild' (#110) from worktree-arch-rebuild-prune into main
apple / swift (push) Successful in 1m30s
ci / bun-nix (push) Successful in 19s
ci / web (push) Successful in 1m40s
ci / docs-site (push) Successful in 3m12s
ci / rust-arm64 (push) Successful in 6m8s
apple / screenshots (push) Successful in 6m19s
android / android (push) Successful in 10m12s
arch / build-publish (push) Successful in 9m5s
decky / build-publish (push) Successful in 55s
deb / build-publish-client-arm64 (push) Successful in 1m58s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 18s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 15s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 52s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 32s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 11s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 28s
deb / build-publish (push) Successful in 9m25s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m28s
deb / build-publish-host (push) Successful in 7m54s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 3m3s
docker / builders-arm64cross (push) Successful in 14s
ci / rust (push) Successful in 17m40s
docker / deploy-docs (push) Failing after 3m46s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m52s
apple / swift (push) Successful in 1m30s
ci / bun-nix (push) Successful in 19s
ci / web (push) Successful in 1m40s
ci / docs-site (push) Successful in 3m12s
ci / rust-arm64 (push) Successful in 6m8s
apple / screenshots (push) Successful in 6m19s
android / android (push) Successful in 10m12s
arch / build-publish (push) Successful in 9m5s
decky / build-publish (push) Successful in 55s
deb / build-publish-client-arm64 (push) Successful in 1m58s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 18s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 15s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 52s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 32s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 11s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 28s
deb / build-publish (push) Successful in 9m25s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m28s
deb / build-publish-host (push) Successful in 7m54s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 3m3s
docker / builders-arm64cross (push) Successful in 14s
ci / rust (push) Successful in 17m40s
docker / deploy-docs (push) Failing after 3m46s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m52s
Reviewed-on: #110
This commit was merged in pull request #110.
This commit is contained in:
@@ -420,10 +420,29 @@ jobs:
|
||||
# A rebuild bumps pkgrel, so its FILENAMES differ from the ones already attached, and
|
||||
# upsert_asset only replaces by name — the superseded set would survive untouched.
|
||||
# Drop every pacman asset (and .sha256 sidecar) this upload did not just write.
|
||||
#
|
||||
# ⚠⚠ THIS MUST LIVE IN THE WORKFLOW, NOT IN scripts/ci/gitea-release.sh. The sourced
|
||||
# script comes from the CHECKED-OUT TREE, which on a release rebuild is the OLD TAG —
|
||||
# so it can only ever offer the helpers that existed when that tag was cut. A helper
|
||||
# added for this feature is therefore guaranteed ABSENT in the one code path that
|
||||
# calls it: the first attempt failed with `prune_release_assets: command not found`
|
||||
# after publishing perfectly. Only the workflow file itself is taken from the ref you
|
||||
# dispatch. Same reason a packaging fix made after a tag does NOT reach a rebuild of
|
||||
# that tag — the PKGBUILD is the tag's too.
|
||||
if [ -n "${RELEASE_TAG:-}" ]; then
|
||||
KEEP="$(cd dist && printf '%s ' *.pkg.tar.zst)"
|
||||
# An UNMATCHED glob would come through literally and match nothing in the keep set —
|
||||
# i.e. "delete every pacman asset on the release". Empty out instead; prune refuses.
|
||||
# i.e. "delete every pacman asset on the release". Skip entirely instead.
|
||||
case "$KEEP" in *'*'*) KEEP="" ;; esac
|
||||
prune_release_assets "$RID" .pkg.tar.zst "$KEEP"
|
||||
API="$GITHUB_SERVER_URL/api/v1/repos/$GITHUB_REPOSITORY"
|
||||
if [ -n "$KEEP" ]; then
|
||||
curl -fsS "$API/releases/$RID/assets" -H "Authorization: token $GITEA_TOKEN" \
|
||||
| python3 -c "import json,sys;k=set(sys.argv[1].split());k|={n+'.sha256' for n in k};print('\n'.join('%s %s'%(a['id'],a['name']) for a in json.load(sys.stdin) if a.get('name','').endswith(('.pkg.tar.zst','.pkg.tar.zst.sha256')) and a['name'] not in k))" "$KEEP" \
|
||||
| while read -r id name; do
|
||||
[ -n "$id" ] || continue
|
||||
echo "dropping superseded release asset: $name"
|
||||
curl -fsS -o /dev/null -X DELETE "$API/releases/$RID/assets/$id" \
|
||||
-H "Authorization: token $GITEA_TOKEN" || true
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -38,18 +38,11 @@ for a in json.load(sys.stdin):
|
||||
print(a.get("id",""));break' "$1" 2>/dev/null
|
||||
}
|
||||
_urlencode() { python3 -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1],safe=""))' "$1"; }
|
||||
# _json_stale_asset_ids SUFFIX KEEP_NAMES (assets JSON on stdin) -> "<id> <name>" lines
|
||||
# The assets matching SUFFIX (or its .sha256 sidecar) that are NOT in the whitespace-separated
|
||||
# KEEP_NAMES. See prune_release_assets.
|
||||
_json_stale_asset_ids() {
|
||||
python3 -c 'import json,sys
|
||||
suffix, keep = sys.argv[1], set(sys.argv[2].split())
|
||||
keep |= {n + ".sha256" for n in keep}
|
||||
for a in json.load(sys.stdin):
|
||||
n = a.get("name", "")
|
||||
if n.endswith((suffix, suffix + ".sha256")) and n not in keep:
|
||||
print(a.get("id", ""), n)' "$1" "$2" 2>/dev/null
|
||||
}
|
||||
# ⚠ Do NOT add helpers here for a workflow step that runs against a CHECKED-OUT RELEASE TAG
|
||||
# (arch.yml's release-rebuild dispatch). Callers source this file from the working tree, so such a
|
||||
# step gets the version of this file that shipped in that tag — never the one you just wrote. That
|
||||
# logic belongs in the workflow, which is always read from the dispatched ref. Cost this once
|
||||
# already: `prune_release_assets: command not found`, after the packages published fine.
|
||||
|
||||
# _release_notes_path TAG
|
||||
# Print the path of the in-repo release notes for TAG (docs/releases/<TAG>.md) IFF it exists,
|
||||
@@ -177,32 +170,6 @@ upsert_asset() {
|
||||
if _put_asset "$rid" "$sums" "$name.sha256"; then rm -f "$sums"; else rm -f "$sums"; return 1; fi
|
||||
}
|
||||
|
||||
# prune_release_assets RELEASE_ID SUFFIX KEEP_NAMES
|
||||
# Delete every asset of the release whose name ends in SUFFIX (or SUFFIX.sha256) and is not one
|
||||
# of KEEP_NAMES (whitespace-separated).
|
||||
#
|
||||
# WHY: upsert_asset replaces an asset BY NAME, which is idempotent only while the filename is
|
||||
# stable. A REBUILD of an already-published release is exactly the case where it is not — a
|
||||
# distro moved under the release, the artifact is rebuilt at a higher pkgrel, and
|
||||
# `punktfunk-host-0.25.0-2-x86_64.pkg.tar.zst` collides with nothing, so the -1 build stays
|
||||
# attached. A superseded package on a release page is not clutter; it is a live download of the
|
||||
# very build the rebuild exists to replace. Scoped by SUFFIX because a release object is shared
|
||||
# by ~8 packaging workflows running concurrently — each leg may only ever prune names it owns.
|
||||
prune_release_assets() {
|
||||
local rid="${1:?release id}" suffix="${2:?suffix}" keep="${3:-}"
|
||||
local api
|
||||
# An empty keep list means "delete every asset matching SUFFIX", which is never what a caller
|
||||
# wants and is exactly what a mis-expanded glob looks like. Refuse rather than clear a release.
|
||||
[ -n "$keep" ] || { echo "gitea-release: prune_release_assets got an empty keep list — refusing" >&2; return 0; }
|
||||
api="$(_gitea_api)"
|
||||
curl -fsS "$api/releases/$rid/assets" -H "Authorization: token ${GITEA_TOKEN:?}" \
|
||||
| _json_stale_asset_ids "$suffix" "$keep" \
|
||||
| while read -r id name; do
|
||||
echo "gitea-release: dropping superseded asset '$name'"
|
||||
curl -fsS -o /dev/null -X DELETE "$api/releases/$rid/assets/$id" \
|
||||
-H "Authorization: token ${GITEA_TOKEN:?}" || true
|
||||
done
|
||||
}
|
||||
|
||||
# apply_release_notes RELEASE_ID TAG
|
||||
# Force the release body to match docs/releases/<TAG>.md (the source of truth), if that file
|
||||
|
||||
Reference in New Issue
Block a user