From 4083f3195a1e84c2f0deeeadaa49c0cc58b43358 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 5 Sep 2026 10:04:59 +0200 Subject: [PATCH] Keep Forgejo prune inventory outside replaceable checkouts Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a06ecb-456a-71c2-b41e-0755d336e883 --- .../weekly-forgejo-package-prune.md | 2 +- docs/runbook.md | 12 ++- k8s/railiance/20-runtime.yaml | 47 ++++++++++ scripts/refresh_live_images.sh | 88 ++----------------- 4 files changed, 63 insertions(+), 86 deletions(-) diff --git a/activity-definitions/weekly-forgejo-package-prune.md b/activity-definitions/weekly-forgejo-package-prune.md index 02f707a..0a86910 100644 --- a/activity-definitions/weekly-forgejo-package-prune.md +++ b/activity-definitions/weekly-forgejo-package-prune.md @@ -17,7 +17,7 @@ context_sources: required: true params: prune_script: /opt/railiance-platform/tools/cmd/forgejo-package-prune - live_images_file: /opt/railiance-platform/docs/evidence/live-images-all.txt + live_images_file: /var/lib/railiance-platform/live-images/all.txt apply: true max_versions: 3 evidence_sinks: diff --git a/docs/runbook.md b/docs/runbook.md index a5ce5a4..9b04f0d 100644 --- a/docs/runbook.md +++ b/docs/runbook.md @@ -602,7 +602,7 @@ Refresh protection list after cluster image rollouts: # From workstation with both contexts, or merge scp'd exports on railiance01: ./scripts/refresh_live_images.sh # railiance01 worker hostPath target: -OUT=~/railiance-platform/docs/evidence/live-images-all.txt \ +OUT=~/.local/state/railiance-platform/live-images/all.txt \ EXTRA_LIVE_FILES=/path/to/coulombcore-export.txt \ ./scripts/refresh_live_images.sh ``` @@ -614,7 +614,7 @@ cd ~/railiance-platform export VAULT_ADDR=https://bao.coulomb.social # OIDC or platform token — never paste PAT into chat export FORGEJO_TOKEN=$(bao kv get -field=API_TOKEN platform/workloads/forgejo/forgejo-admin) -./tools/cmd/forgejo-package-prune --apply --live-images-file docs/evidence/live-images-all.txt +./tools/cmd/forgejo-package-prune --apply --live-images-file ~/.local/state/railiance-platform/live-images/all.txt ``` `weekly-sbom-staleness` is emergency-paused in source and production. Its @@ -1025,3 +1025,11 @@ uv run alembic upgrade head uv run python src/activity_core/seed.py # Re-register search attributes (see Dev environment step 4) ``` + + +Inventory durability (RPF-WP-0028): the worker mounts the host inventory directory +read-only at `/var/lib/railiance-platform/live-images`; the weekly definition uses +`all.txt` there. `make refresh-live-images` uses the platform publisher and keeps +prior cluster tags on export failure. Run the host hook +`~/.local/bin/railiance-live-images-refresh` after each cluster image rollout. +The helper installation is versioned outside both repository checkouts. diff --git a/k8s/railiance/20-runtime.yaml b/k8s/railiance/20-runtime.yaml index 924c164..f678da6 100644 --- a/k8s/railiance/20-runtime.yaml +++ b/k8s/railiance/20-runtime.yaml @@ -48,6 +48,46 @@ metadata: app.kubernetes.io/name: activity-core app.kubernetes.io/part-of: activity-core data: + weekly-forgejo-package-prune.md: | + --- + id: weekly-forgejo-package-prune + name: Weekly Forgejo Package Prune + enabled: true + owner: custodian-agent + governance: custodian + status: active + trigger: + type: cron + cron_expression: "30 3 * * 0" + timezone: UTC + misfire_policy: skip + context_sources: + - type: shell + query: forgejo_package_prune + operation: forgejo_package_prune + required: true + params: + prune_script: /opt/railiance-platform/tools/cmd/forgejo-package-prune + live_images_file: /var/lib/railiance-platform/live-images/all.txt + apply: true + max_versions: 3 + evidence_sinks: + - type: state-hub-progress + event_type: forgejo_package_prune + author: activity-core + bind_to: context.prune + --- + + # Weekly Forgejo Package Prune + + Runs every Sunday at 03:30 UTC (after the 02:15 `forgejo-backup` cron). Invokes + `railiance-platform/tools/cmd/forgejo-package-prune` to retain the newest **3** + versions per `coulomb` package (OCI, PyPI, npm, generic). Production image tags + (live cluster + Helm values) are protected. + + **Enabled 2026-07-21** (`ACTIVITY-WP-0020` T05/T06): first apply deleted 38 + stale package versions; worker has `FORGEJO_TOKEN` + host-mounted + `/opt/railiance-platform` prune tools. glas-profile-pilot.md: | --- id: glas-profile-pilot @@ -1361,6 +1401,9 @@ spec: - name: railiance-platform mountPath: /opt/railiance-platform readOnly: true + - name: live-image-inventory + mountPath: /var/lib/railiance-platform/live-images + readOnly: true - name: kubeconfigs mountPath: /kube readOnly: true @@ -1385,6 +1428,10 @@ spec: hostPath: path: /home/tegwick/railiance-platform type: Directory + - name: live-image-inventory + hostPath: + path: /home/tegwick/.local/state/railiance-platform/live-images + type: Directory - name: kubeconfigs hostPath: path: /home/tegwick/.kube diff --git a/scripts/refresh_live_images.sh b/scripts/refresh_live_images.sh index 4ee0dbf..d075c86 100755 --- a/scripts/refresh_live_images.sh +++ b/scripts/refresh_live_images.sh @@ -1,86 +1,8 @@ #!/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 +# Platform-owned, additive multi-cluster protection refresh after image rollouts. 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 +PLATFORM_INVENTORY_ROOT="${PLATFORM_INVENTORY_ROOT:-${HOME}/.local/lib/railiance-platform-inventory/current}" +if [[ ! -d "$PLATFORM_INVENTORY_ROOT" ]]; then + PLATFORM_INVENTORY_ROOT="${HOME}/railiance-platform" fi +exec bash "$PLATFORM_INVENTORY_ROOT/tools/cmd/refresh-live-images"