# k8s/forge/runner-gc-cronjob.yaml
# Garbage-collects the forgejo-runner's DinD layer cache (runner-dind PVC,
# 30Gi). Every CI build/pull only adds images and build-cache layers — there
# is no automatic pruning, so without this the PVC fills up and breaks builds.
#
# Runs `docker image prune` / `docker builder prune` inside the live dind
# container via `kubectl exec`, rather than a sidecar in the runner pod itself,
# so it can run on its own schedule independent of runner restarts.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: runner-gc
  namespace: cicd

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: runner-gc
  namespace: cicd
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: runner-gc
  namespace: cicd
subjects:
  - kind: ServiceAccount
    name: runner-gc
    namespace: cicd
roleRef:
  kind: Role
  name: runner-gc
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: forgejo-runner-image-gc
  namespace: cicd
spec:
  schedule: "0 3 * * *"   # daily 03:00
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 1
      activeDeadlineSeconds: 600
      template:
        spec:
          serviceAccountName: runner-gc
          restartPolicy: Never
          tolerations:
            - key: node-role.kubernetes.io/control-plane
              operator: Exists
              effect: NoSchedule
          containers:
            - name: gc
              image: alpine/k8s:1.31.0
              command:
                - sh
                - -c
                - |
                  set -e
                  POD=$(kubectl -n cicd get pod -l app=forgejo-runner -o jsonpath='{.items[0].metadata.name}')
                  if [ -z "$POD" ]; then
                    echo "no forgejo-runner pod found, skipping"
                    exit 0
                  fi
                  echo "before:"
                  kubectl -n cicd exec "$POD" -c dind -- df -h /var/lib/docker
                  echo "pruning images unused for >72h on $POD"
                  kubectl -n cicd exec "$POD" -c dind -- docker image prune -af --filter "until=72h"
                  echo "pruning build cache unused for >72h on $POD"
                  kubectl -n cicd exec "$POD" -c dind -- docker builder prune -af --filter "until=72h"
                  echo "after:"
                  kubectl -n cicd exec "$POD" -c dind -- df -h /var/lib/docker
              resources:
                requests:
                  cpu: 50m
                  memory: 64Mi
                limits:
                  cpu: 250m
                  memory: 128Mi
