Files
bootc-images/prune-registry.sh
T
Misthios e4251f4d78
Build containers / fedora-cosmic (rawhide) (push) Failing after 45s
Build containers / fedora-cosmic (44) (push) Successful in 11m0s
Build containers / Prune old releases (push) Successful in 29s
ci: fix prune-registry registry ref case and protect signatures
The registry path is lowercase, so the capitalized owner made skopeo inspect
fail and every cosign .sig tag was deleted. Lowercase the owner and, if no
digest resolves, keep all signature tags instead of deleting them.
2026-09-27 20:28:40 +02:00

77 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Prune old container image versions (tags) for an image in the Gitea registry.
#
# Keeps the moving tag (e.g. "44") and the newest versioned tag per distro,
# plus the cosign signature tag (sha256-<digest>.sig) for each kept image.
#
# Usage:
# REGISTRY_TOKEN=<write:package> REGISTRY_USERNAME=<user> \
# ./prune-registry.sh [image] [owner] [distro...]
set -euo pipefail
IMAGE="${1:-fedora-cosmic}"; shift || true
OWNER="${1:-Misthios}"; shift || true
DISTROS=("$@"); [[ ${#DISTROS[@]} -gt 0 ]] || DISTROS=(44 rawhide)
GITEA_URL="${GITEA_URL:-https://git.plabble.org}"
REGISTRY_HOST="${REGISTRY_HOST:-$(printf '%s' "${GITEA_URL}" | sed -E 's#https?://##')}"
TOKEN="${REGISTRY_TOKEN:?REGISTRY_TOKEN (write:package) is required}"
AUTHFILE="${AUTHFILE:-${HOME}/.docker/config.json}"
API="${GITEA_URL%/}/api/v1/packages/${OWNER}/container/${IMAGE}"
# Registry paths are lowercase (the Gitea API owner is not).
IMAGE_REF="${REGISTRY_HOST}/$(printf '%s' "${OWNER}" | tr '[:upper:]' '[:lower:]')/${IMAGE}"
# Collect all versions (paginated).
versions=""
page=1
while :; do
page_json="$(curl -fsSL -H "Authorization: token ${TOKEN}" \
"${API}?limit=50&page=${page}")" || break
[[ "$(jq 'length' <<< "${page_json}")" -eq 0 ]] && break
versions+="$(jq -r '.[].version' <<< "${page_json}")"$'\n'
page=$((page + 1))
[[ "${page}" -gt 40 ]] && break
done
# Decide what to keep.
declare -A keep=()
for d in "${DISTROS[@]}"; do
keep["${d}"]=1
newest="$(grep -E "^${d}\.[0-9]+\.[0-9]+$" <<< "${versions}" \
| sort -t. -k2,2n -k3,3n | tail -1)"
[[ -n "${newest}" ]] && keep["${newest}"]=1
done
# Keep the cosign signature of each kept image tag. If no digest could be
# resolved, keep every signature tag rather than risk deleting a needed one.
resolved=0
for tag in "${!keep[@]}"; do
[[ "${tag}" == sha256-* ]] && continue
digest="$(skopeo inspect --authfile "${AUTHFILE}" --format '{{.Digest}}' \
"docker://${IMAGE_REF}:${tag}" 2>/dev/null || true)"
if [[ -n "${digest}" ]]; then
keep["sha256-${digest#sha256:}.sig"]=1
resolved=1
fi
done
if [[ "${resolved}" -eq 0 ]]; then
echo "WARNING: could not resolve any image digest; keeping all signature tags"
while IFS= read -r v; do
[[ "${v}" == sha256-* ]] && keep["${v}"]=1
done <<< "${versions}"
fi
# Delete everything else.
while IFS= read -r v; do
[[ -z "${v}" ]] && continue
if [[ -n "${keep[${v}]:-}" ]]; then
echo "keep ${v}"
else
echo "remove ${v}"
curl -fsSL -X DELETE -H "Authorization: token ${TOKEN}" \
"${API}/${v}" >/dev/null || echo " (failed to delete ${v})"
fi
done <<< "${versions}"
echo "Pruned ${IMAGE} registry versions."