#!/bin/bash # Cleanup-old: löscht alle EdgeGuard-Versionen im Gitea Package # Registry außer den letzten N (default 10) — pro Kanal (Komponente). # # Wird vom Makefile/release.sh direkt nach erfolgreichem Upload # aufgerufen. Reihenfolge ist wichtig: ERST der neue Build hochladen, # DANN die ältesten wegschmeißen — sonst riskieren wir bei Cleanup-vor- # Upload eine Lücke. # # Stable-Schutz: Versionen, die als Git-Tag `v` im Repo stehen, # werden im stable-Kanal NIE gelöscht (analog enconf STABLE_PROTECT) — # ein Kunde, der genau diese Version installiert hat, muss sie über # apt-get weiterhin ziehen können. # # Voraussetzungen: # - ~/.gitea-token mit write-Package-Scope # - jq + curl # # Aufruf: # ./cleanup-old.sh # Kanal stable, KEEP=10 (default) # ./cleanup-old.sh testing # Kanal testing # KEEP=20 ./cleanup-old.sh stable # mehr behalten set -euo pipefail KEEP="${KEEP:-10}" OWNER="projekte" DIST="trixie" COMPONENT="${1:-stable}" case "$COMPONENT" in stable|testing) ;; *) echo "cleanup-old: unknown channel '$COMPONENT' (expected stable or testing)" >&2; exit 2 ;; esac BASE="https://git.netcell-it.de" # Geschützte Versionen (nur relevant im stable-Kanal): jeder vorhandene # Git-Tag `v*` im Repo-Root. Leer wenn nicht im Repo ausgeführt oder im # testing-Kanal (dort gibt es keine Tags/keinen Schutz). PROTECTED_VERSIONS="" if [ "$COMPONENT" = "stable" ]; then REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" PROTECTED_VERSIONS="$(git -C "$REPO_ROOT" tag --list 'v*' 2>/dev/null | sed 's/^v//' || true)" fi is_protected() { local v="$1" [ -z "$PROTECTED_VERSIONS" ] && return 1 printf '%s\n' "$PROTECTED_VERSIONS" | grep -qx "$v" } if [ -z "${GITEA_TOKEN:-}" ]; then if [ -r "$HOME/.gitea-token" ]; then GITEA_TOKEN="$(tr -d '\n' < "$HOME/.gitea-token")" else echo "cleanup-old: missing ~/.gitea-token and GITEA_TOKEN env" >&2 exit 1 fi fi TOK="$GITEA_TOKEN" # Pkg-Spec: "name:arch". arch="all" für noarch-Pakete (meta + UI), # "amd64" für edgeguard-api. Mehrere arch je name = mehrere Zeilen. PKGS=( "edgeguard:all" "edgeguard-api:amd64" "edgeguard-api:arm64" "edgeguard-ui:all" ) cleanup_pkg() { local pkg="$1" local arch="$2" # Versionen sammeln. Gitea Package-API liefert flache Liste über ALLE # Kanäle hinweg: /api/v1/packages/{owner}?type=debian&q={name} # Wir filtern client-seitig auf name (exact-match — Gitea-Query ist # leider substring-fuzzy) UND auf das Versionsformat des aktuellen # Kanals — stable=Semver (X.Y.Z), testing=datumsbasiert (YYYY.MM.DD.NN). # Die beiden Formate überlappen nie, das hält testing- und stable- # Versionen sauber getrennt, obwohl Gitea (Name,Version) global dedupliziert. local raw raw="$(curl -fsS -H "Authorization: token $TOK" \ "$BASE/api/v1/packages/$OWNER?type=debian&q=$pkg&limit=1000")" local ver_pattern if [ "$COMPONENT" = "stable" ]; then ver_pattern='^[0-9]+\.[0-9]+\.[0-9]+$' else ver_pattern='^[0-9]{4}\.[0-9]{2}\.[0-9]{2}\.[0-9]+$' fi local versions versions="$(printf '%s' "$raw" | jq -r --arg n "$pkg" \ '.[] | select(.name==$n) | .version' | grep -E "$ver_pattern" | sort -V -r | awk '!seen[$0]++')" if [ -z "$versions" ]; then echo " $pkg ($arch): no $COMPONENT versions found, skip" return 0 fi local count count="$(printf '%s\n' "$versions" | wc -l)" if [ "$count" -le "$KEEP" ]; then echo " $pkg ($arch): $count $COMPONENT versions, ≤ keep=$KEEP, nothing to delete" return 0 fi local to_delete to_delete="$(printf '%s\n' "$versions" | tail -n +$((KEEP+1)))" local kept_count=$((count - $(printf '%s\n' "$to_delete" | wc -l))) echo " $pkg ($arch): $count $COMPONENT versions total, keeping $kept_count newest, considering $(printf '%s\n' "$to_delete" | wc -l) for deletion" while IFS= read -r v; do [ -z "$v" ] && continue if is_protected "$v"; then echo " skip $pkg $v $arch (protected — git tag v$v exists)" continue fi # DELETE-Endpoint für Debian-Pakete: # /api/packages/{owner}/debian/pool/{dist}/{comp}/{name}/{version}/{arch} local url="$BASE/api/packages/$OWNER/debian/pool/$DIST/$COMPONENT/$pkg/$v/$arch" local http http="$(curl -sS -o /dev/null -w '%{http_code}' \ -X DELETE -H "Authorization: token $TOK" "$url")" case "$http" in 204|404) echo " delete $pkg $v $arch -> $http" ;; *) echo " delete $pkg $v $arch -> $http (failed)" ;; esac done <<< "$to_delete" } for spec in "${PKGS[@]}"; do IFS=':' read -r pkg arch <<< "$spec" cleanup_pkg "$pkg" "$arch" done