# Runner container hooks warmer DaemonSet.
# Downloads the patched runner-container-hooks zip once per node to NVMe,
# so runner pods can mount it read-only without per-pod downloads.
#
# See: https://github.com/jeanschmidt/runner-container-hooks/releases/tag/v0.8.17
# v0.8.17 drops the stream-buffers dependency whose WritableStreamBuffer used the
# deprecated Buffer() constructor (per-step DEP0005 warning), via
# jeanschmidt/runner-container-hooks#12. Remove this when the fix lands upstream.
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: runner-hooks-warmer
  namespace: arc-runners
  labels:
    app: runner-hooks-warmer
    app.kubernetes.io/name: runner-hooks-warmer
    app.kubernetes.io/component: runner-infrastructure
spec:
  selector:
    matchLabels:
      app: runner-hooks-warmer

  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: "25%"

  template:
    metadata:
      labels:
        app: runner-hooks-warmer

    spec:
      priorityClassName: system-node-critical

      # Pin to the dedicated c7i-runner pool (where runner pods live).
      # Workflow pool nodes don't run runner pods, so they don't need hooks.
      nodeSelector:
        node-fleet: "c7i-runner"

      # Tolerate node-fleet + instance-type taints carried by c7i-runner nodes.
      tolerations:
        - key: node-fleet
          operator: Equal
          value: "c7i-runner"
          effect: NoSchedule
        - key: instance-type
          operator: Exists
          effect: NoSchedule

      containers:
        - name: hooks-warmer
          image: public.ecr.aws/docker/library/alpine:3.21
          command:
            - /bin/sh
            - -c
            - |
              set -eu
              HOOKS_VERSION="0.8.17"
              HOOKS_URL="https://github.com/jeanschmidt/runner-container-hooks/releases/download/v${HOOKS_VERSION}/actions-runner-hooks-k8s-${HOOKS_VERSION}.zip"
              DEST="/mnt/runner-container-hooks"
              MARKER="$DEST/.version"

              # If already downloaded at this version, just sleep
              if [ -f "$MARKER" ] && [ "$(cat "$MARKER")" = "$HOOKS_VERSION" ]; then
                  echo "Hooks v${HOOKS_VERSION} already present at $DEST"
              else
                  echo "Downloading hooks v${HOOKS_VERSION}..."
                  apk add --no-cache curl unzip >/dev/null 2>&1
                  TMP=$(mktemp -d)
                  curl -fsSL -o "$TMP/hooks.zip" "$HOOKS_URL"
                  mkdir -p "$DEST"
                  # Extract to temp dir, then atomic swap via mv
                  unzip -o "$TMP/hooks.zip" -d "$DEST/dist-new"
                  mv "$DEST/dist" "$DEST/dist-old" 2>/dev/null || true
                  mv "$DEST/dist-new" "$DEST/dist"
                  rm -rf "$DEST/dist-old"

                  if [ ! -f "$DEST/dist/index.js" ]; then
                      echo "ERROR: index.js not found after extraction — zip structure may have changed"
                      rm -rf "$DEST/dist"
                      exit 1
                  fi

                  echo "$HOOKS_VERSION" > "$MARKER"
                  rm -rf "$TMP"
                  echo "Hooks v${HOOKS_VERSION} installed to $DEST/dist/"
              fi

              # Stay alive so DaemonSet doesn't restart
              echo "Hooks warmer idle."
              while true; do sleep 3600; done

          resources:
            requests:
              cpu: 10m
              memory: 32Mi
            limits:
              cpu: 200m
              memory: 128Mi

          volumeMounts:
            - name: hooks-dir
              mountPath: /mnt/runner-container-hooks

      volumes:
        - name: hooks-dir
          hostPath:
            path: /mnt/runner-container-hooks
            type: DirectoryOrCreate
