feat(update): Testing/Stable-Update-Kanäle wie enconf (Suite=trixie, Komponente=Kanal)
Installer (EDGEGUARD_CHANNEL), Kanal-Lesen/-Schreiben ohne DB-State (sources.list ist Quelle der Wahrheit), Cluster-Endpoints für Kanalwechsel mit mTLS-Peer-Propagation + Drift-Erkennung, --allow-downgrades für testing→stable-Downgrades über den bestehenden sicheren Rolling-Update- Flow, Settings-UI mit Bestätigung, neues scripts/release.sh (Testing-Push datumsbasiert YYYY.MM.DD.NN, Stable-Promotion mit Verify-Gate + Git-Tag), publish.sh/cleanup-old.sh kanalfähig mit Stable-Tag-Schutz. Migriert Bestandsnodes automatisch von der alten "main"-Komponente auf "stable" (postinst, idempotent) — ohne das würden vor diesem Release installierte Nodes stillschweigend keine Updates mehr sehen, sobald main nicht mehr bespielt wird. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,27 +1,49 @@
|
||||
#!/bin/bash
|
||||
# Cleanup-old: löscht alle EdgeGuard-Versionen im Gitea Package
|
||||
# Registry außer den letzten N (default 10).
|
||||
# Registry außer den letzten N (default 10) — pro Kanal (Komponente).
|
||||
#
|
||||
# Wird vom Makefile direkt nach erfolgreichem Upload aufgerufen. Reihen-
|
||||
# folge ist wichtig: ERST der neue Build hochladen, DANN die ältesten
|
||||
# wegschmeißen — sonst riskieren wir bei Cleanup-vor-Upload eine Lücke.
|
||||
# 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<version>` 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 # KEEP=10 (default)
|
||||
# KEEP=20 ./cleanup-old.sh # mehr behalten
|
||||
# ./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="main"
|
||||
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")"
|
||||
@@ -37,6 +59,7 @@ TOK="$GITEA_TOKEN"
|
||||
PKGS=(
|
||||
"edgeguard:all"
|
||||
"edgeguard-api:amd64"
|
||||
"edgeguard-api:arm64"
|
||||
"edgeguard-ui:all"
|
||||
)
|
||||
|
||||
@@ -44,27 +67,37 @@ cleanup_pkg() {
|
||||
local pkg="$1"
|
||||
local arch="$2"
|
||||
|
||||
# Versionen sammeln. Gitea Package-API liefert flache Liste:
|
||||
# /api/v1/packages/{owner}?type=debian&q={name}
|
||||
# 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 sort -V (semver) absteigend.
|
||||
# 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' | sort -V -r | awk '!seen[$0]++')"
|
||||
'.[] | select(.name==$n) | .version' | grep -E "$ver_pattern" | sort -V -r | awk '!seen[$0]++')"
|
||||
|
||||
if [ -z "$versions" ]; then
|
||||
echo " $pkg ($arch): no versions found, skip"
|
||||
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 versions, ≤ keep=$KEEP, nothing to delete"
|
||||
echo " $pkg ($arch): $count $COMPONENT versions, ≤ keep=$KEEP, nothing to delete"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -72,10 +105,14 @@ cleanup_pkg() {
|
||||
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 versions total, keeping $kept_count newest, deleting $(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"
|
||||
|
||||
Reference in New Issue
Block a user