#!/bin/bash
# Prunes stale CI scratch. Read-only dirs are made writable first, otherwise
# rm cannot unlink their children even though we own them.
set -uo pipefail
prune() {
  local root="$1"; shift
  [ -d "$root" ] || return 0
  /usr/bin/find "$root" -maxdepth 1 -mindepth 1 "$@" -print0 2>/dev/null \
    | /usr/bin/xargs -0 -r -P4 -n100 /bin/chmod -R u+rwX -- 2>/dev/null
  /usr/bin/find "$root" -maxdepth 1 -mindepth 1 "$@" -print0 2>/dev/null \
    | /usr/bin/xargs -0 -r -P4 -n100 /bin/rm -rf --
}
prune /tmp -user "$(/usr/bin/id -un)" -mtime +1
prune "$HOME/builds" -mtime +1

# --- disk floor alarm -------------------------------------------------------
# Runs after the prune, so it reports only what the prune could not reclaim.
# /tmp is a 16G tmpfs capped at 1,048,576 inodes and it is inodes, not bytes,
# that hit 100% on debian1 on 2026-07-26 — all three floors are load-bearing.
NTFY_TOPIC="http://127.0.0.1:2586/megaplan-f25e25b3c41f42c8bd8ee60e"
COOLDOWN_SECS=$((6 * 60 * 60))
STAMP="$HOME/.cache/ci-disk-alarm.stamp"
ROOT_FLOOR_G=15
TMP_FLOOR_G=3
TMP_FLOOR_INODES=150000

disk_floor_alarm() {
  local breaches="" root_b tmp_b tmp_i now last

  root_b=$(/bin/df -B1 --output=avail / 2>/dev/null | /usr/bin/tail -1 | /usr/bin/tr -dc '0-9')
  tmp_b=$(/bin/df -B1 --output=avail /tmp 2>/dev/null | /usr/bin/tail -1 | /usr/bin/tr -dc '0-9')
  tmp_i=$(/bin/df --output=iavail /tmp 2>/dev/null | /usr/bin/tail -1 | /usr/bin/tr -dc '0-9')

  [ -n "$root_b" ] && [ "$root_b" -lt $((ROOT_FLOOR_G * 1024 * 1024 * 1024)) ] \
    && breaches="${breaches}/ has $((root_b / 1024 / 1024 / 1024))G free, floor ${ROOT_FLOOR_G}G. "
  [ -n "$tmp_b" ] && [ "$tmp_b" -lt $((TMP_FLOOR_G * 1024 * 1024 * 1024)) ] \
    && breaches="${breaches}/tmp has $((tmp_b / 1024 / 1024 / 1024))G free, floor ${TMP_FLOOR_G}G. "
  [ -n "$tmp_i" ] && [ "$tmp_i" -lt "$TMP_FLOOR_INODES" ] \
    && breaches="${breaches}/tmp has ${tmp_i} inodes free, floor ${TMP_FLOOR_INODES} — this is what ENOSPCs CI. "

  [ -n "$breaches" ] || return 0

  now=$(/bin/date +%s)
  last=$(/bin/cat "$STAMP" 2>/dev/null | /usr/bin/tr -dc '0-9')
  [ -n "$last" ] && [ $((now - last)) -lt "$COOLDOWN_SECS" ] && return 0

  # The stamp is written only on a delivered POST, so a failed send retries next hour.
  if /usr/bin/curl -fsS --max-time 20 \
      -H "Title: $(/bin/hostname) below a CI disk floor" \
      -H "Tags: rotating_light" \
      -d "Hourly scratch prune ran and did not clear it. ${breaches}" \
      "$NTFY_TOPIC" >/dev/null 2>&1; then
    /bin/mkdir -p "$(/usr/bin/dirname "$STAMP")"
    echo "$now" > "$STAMP"
  fi
}

disk_floor_alarm || true
