activity-core/scripts/refresh_live_images.sh
tegwick 4f5399df84
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 3s
Build and Publish Container Image / build-and-push (push) Successful in 28s
Implement ACTIVITY-WP-0022/0023: safe sink default and gap closures
Default ISSUE_SINK_TYPE to state-hub (no silent Forgejo issues), hard-fail
prune apply without live-images protection, refresh-live-images script,
disable TaskExecutor stub by default, and document consumer/sink contracts.
2026-07-21 21:40:08 +02:00

86 lines
2.7 KiB
Bash
Executable file

#!/usr/bin/env bash
# ACTIVITY-WP-0023-T04: refresh multi-cluster live Forgejo image protection list.
#
# Exports container images matching forgejo.coulomb.social from one or more
# kubectl contexts and merges them into a single non-secret list used by
# weekly-forgejo-package-prune (live_images_file).
#
# Usage:
# ./scripts/refresh_live_images.sh
# OUT=/path/to/live-images-all.txt CONTEXTS="default hosteurope" ./scripts/refresh_live_images.sh
#
# On railiance01 (worker hostPath target):
# OUT=~/railiance-platform/docs/evidence/live-images-all.txt ./scripts/refresh_live_images.sh
set -euo pipefail
OUT="${OUT:-${HOME}/railiance-platform/docs/evidence/live-images-all.txt}"
# Space-separated kubeconfig contexts (empty = current default context only)
CONTEXTS="${CONTEXTS:-}"
PATTERN="${FORGEJO_IMAGE_PATTERN:-forgejo.coulomb.social}"
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
export_one() {
local ctx="$1"
local dest="$2"
local args=()
if [[ -n "$ctx" ]]; then
args=(--context "$ctx")
fi
if ! kubectl "${args[@]}" get pods -A -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' \
2>/dev/null | grep -E "$PATTERN" | sort -u >"$dest"; then
# also try hosteurope-style if default failed
kubectl "${args[@]}" get pods -A -o json 2>/dev/null \
| python3 -c "
import json,sys,re
pat=re.compile(r'${PATTERN}')
try:
d=json.load(sys.stdin)
except Exception:
sys.exit(0)
for it in d.get('items',[]):
for c in (it.get('spec') or {}).get('containers') or []:
img=c.get('image') or ''
if pat.search(img):
print(img)
" | sort -u >"$dest" || true
fi
# hostPath / crictl fallback not required; empty file is ok for this context
local n
n=$(wc -l <"$dest" | tr -d ' ')
echo "context=${ctx:-current}: ${n} forgejo images" >&2
}
if [[ -z "$CONTEXTS" ]]; then
export_one "" "$tmpdir/a.txt"
cat "$tmpdir/a.txt" >"$tmpdir/all.txt"
else
: >"$tmpdir/all.txt"
i=0
for ctx in $CONTEXTS; do
export_one "$ctx" "$tmpdir/c$i.txt"
cat "$tmpdir/c$i.txt" >>"$tmpdir/all.txt"
i=$((i + 1))
done
fi
# Also accept extra files to merge (e.g. coulombcore export scp'd earlier)
if [[ -n "${EXTRA_LIVE_FILES:-}" ]]; then
for f in $EXTRA_LIVE_FILES; do
if [[ -f "$f" ]]; then
cat "$f" >>"$tmpdir/all.txt"
echo "merged extra $f" >&2
fi
done
fi
sort -u "$tmpdir/all.txt" | grep -v '^$' >"$tmpdir/merged.txt" || true
mkdir -p "$(dirname "$OUT")"
cp "$tmpdir/merged.txt" "$OUT"
count=$(wc -l <"$OUT" | tr -d ' ')
echo "wrote $OUT ($count unique images)" >&2
if [[ "$count" -eq 0 ]]; then
echo "WARNING: empty live-images list — prune apply will refuse (ACTIVITY-WP-0023-T03)" >&2
exit 2
fi