67 lines
2.2 KiB
Bash
67 lines
2.2 KiB
Bash
#!/usr/bin/env bash
|
|
# Delete Gitea Actions artifacts by exact name (keep newest N).
|
|
# Usage: prune-gitea-artifacts.sh <owner/repo> <artifact-name> [keep_last]
|
|
# Env: GITEA_BASE_URL, GITEA_TOKEN (or REGISTRY_PASSWORD)
|
|
set -euo pipefail
|
|
|
|
REPO="${1:?owner/repo e.g. EventHub/EventHubFront}"
|
|
NAME_FILTER="${2:?artifact name}"
|
|
KEEP_LAST="${3:-0}"
|
|
BASE="${GITEA_BASE_URL:-https://git.sabilin.com}"
|
|
TOKEN="${GITEA_TOKEN:-${REGISTRY_PASSWORD:-}}"
|
|
|
|
if [[ -z "${TOKEN}" ]]; then
|
|
echo "prune-gitea-artifacts: no token — skip" >&2
|
|
exit 0
|
|
fi
|
|
|
|
python3 - "${BASE}" "${TOKEN}" "${REPO}" "${NAME_FILTER}" "${KEEP_LAST}" <<'PY'
|
|
import json, os, sys, urllib.request, urllib.error
|
|
|
|
base, token, repo, name_filter, keep_last = sys.argv[1:6]
|
|
keep_last = int(keep_last)
|
|
headers = {"Authorization": f"token {token}", "Accept": "application/json"}
|
|
|
|
def get(url):
|
|
req = urllib.request.Request(url, headers=headers)
|
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
|
return json.load(resp)
|
|
|
|
def delete(url):
|
|
req = urllib.request.Request(url, headers=headers, method="DELETE")
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
|
return resp.status
|
|
except urllib.error.HTTPError as e:
|
|
return e.code
|
|
|
|
arts = []
|
|
page = 1
|
|
while page <= 40:
|
|
url = f"{base.rstrip('/')}/api/v1/repos/{repo}/actions/artifacts?limit=50&page={page}"
|
|
try:
|
|
data = get(url)
|
|
except Exception as exc:
|
|
print(f"prune-gitea-artifacts: list failed: {exc}", file=sys.stderr)
|
|
sys.exit(0)
|
|
batch = data if isinstance(data, list) else (data.get("artifacts") or data.get("data") or [])
|
|
if not batch:
|
|
break
|
|
for a in batch:
|
|
n = str(a.get("name") or "")
|
|
if n == name_filter or n.startswith(name_filter):
|
|
arts.append(a)
|
|
if len(batch) < 50:
|
|
break
|
|
page += 1
|
|
|
|
# Prefer newest first by id desc
|
|
arts.sort(key=lambda a: int(a.get("id") or 0), reverse=True)
|
|
to_delete = arts[keep_last:]
|
|
print(f"prune-gitea-artifacts: {repo} name={name_filter} matched={len(arts)} delete={len(to_delete)} keep={keep_last}")
|
|
for a in to_delete:
|
|
aid = a.get("id")
|
|
code = delete(f"{base.rstrip('/')}/api/v1/repos/{repo}/actions/artifacts/{aid}")
|
|
print(f" delete id={aid} name={a.get('name')} http={code}")
|
|
PY
|