#!/usr/bin/env bash
# Keeps the VM's copy of the pages (bashatest.howincloud.com, a GitHub clone) in sync with the Mac.
# Every INTERVAL seconds: a syntax check of every changed page script, then commit the page paths, push to the
# private backup (farisbasha) and fast-forward the VM's clone. A cycle with a syntax error is skipped, so the VM
# never gets a page that can't parse. The coordinator's full gate (ix_gate.sh) still runs at every check-in.
#   bash _tools/pages_autosync.sh            (loops until killed; log: /Volumes/Workspace/Scratch/coord/autosync.log)
set -uo pipefail
cd "$(dirname "$0")/.." || exit 1
INTERVAL=${INTERVAL:-600}
LOG=/Volumes/Workspace/Scratch/coord/autosync.log
mkdir -p "$(dirname "$LOG")"
LOCK=$(git rev-parse --git-path index.lock)   # .git here is a gitdir file, so the lock lives in the bare repo
# (coordinator 3 Nov 23:15, user: 'keep bashatest in sync') every page + its scripts/css/images, except 58m* (movie replica: local-only)
PATHS=(36_index.html '40*.js' '40*.html' '5[0-7]*.html' '5[0-7]*.js' '5[0-7]*.css' '6*.html' '6*.js' '6*.css' 69_base_wip 40k_draw.js 51_build.html 58_kill_library.html '58k*.js' '58k*.html' '58k*.json' 58k.css 59_tracker.html '60*.html' '61*.html' '61*.js' '62*.html' '62*.js' '63*.html' '64*.html' '64*.js' '65*.html' '7*.html' '7*.js' '7*.css' '8*.html' '8*.js' '8*.css' '9*.html' '9*.js' '9*.css' '1[0-9][0-9]_*' kill_review.html inbox.html doubts.html ix_status.js _tools img sfx)
say() { echo "$(date '+%d %b %H:%M:%S') $*" >> "$LOG"; }

while true; do
  if [[ -e $LOCK ]]; then say "skip: git busy"; sleep "$INTERVAL"; continue; fi
  # 36_index.html shows its counts from ix_status.js: refresh it whenever it is 20+ min old, so the user never sees stale numbers.
  # (coordinator 2 Nov 04:55) its headless-Chrome page probes pushed this Mac to load 45 next to a Unity build: run them niced, and only when
  # the 1-min load is under 15 (else retry next loop); a refresh older than 60 min runs anyway (still niced) so the counts never go very stale.
  LOAD1=$(sysctl -n vm.loadavg | awk '{print int($2)}')
  # (coordinator 2 Nov 15:45) both Mac test lanes are open now: refresh only when 60+ min old AND the 1-min load is under 10; forced after 180 min
  if [[ -z $(find ix_status.js -mmin -60 2>/dev/null) ]] && { [[ $LOAD1 -lt 10 ]] || [[ -z $(find ix_status.js -mmin -180 2>/dev/null) ]]; }; then
    perl -e 'alarm 900; exec @ARGV' nice -n 15 python3 _tools/ix_status.py >/dev/null 2>>"$LOG" || say "ix_status failed"
    python3 _tools/make_tracker.py >/dev/null 2>>"$LOG"
    # THE KILL LIBRARY HUB's data (58k_library.js): plain on every refresh; a full re-probe of the live pages (28 headless
    # Chromes, one at a time, each with lib_probe.mjs's sentry + watchdog) only when its cache is an hour old
    perl -e 'alarm 900; exec @ARGV' python3 _tools/make_library.py --live-if-stale 14400 >/dev/null 2>>"$LOG" || say "make_library failed"
  fi
  changed=$(git status --porcelain -- "${PATHS[@]}" | awk '{print $NF}')
  if [[ -z $changed ]]; then
    say "no page changes"
  else
    bad=""
    while IFS= read -r f; do
      [[ $f == *.js && -f $f ]] || continue
      node --check "$f" 2>/dev/null || bad="$bad $f"
    done <<< "$changed"
    if [[ -n $bad ]]; then
      say "skip: syntax error in$bad"
    else
      # only the pathspecs that match a file: git add aborts the whole add on a pattern with no match (e.g. a page not built yet)
      addp=(); for p in "${PATHS[@]}"; do [[ -n $(git ls-files -co --exclude-standard -- "$p" | head -1) ]] && addp+=("$p"); done
      git add -- "${addp[@]}" 2>>"$LOG"
      if git commit -q -m "pages: auto-sync $(date '+%d %b %H:%M')" 2>>"$LOG"; then
        perl -e 'alarm 120; exec @ARGV' git fetch -q farisbasha 2>>"$LOG" && git merge --no-edit -q farisbasha/main 2>>"$LOG"
        if perl -e 'alarm 180; exec @ARGV' git push -q farisbasha HEAD:main 2>>"$LOG"; then
          vm=$(perl -e 'alarm 90; exec @ARGV' ssh -o BatchMode=yes -o ConnectTimeout=15 root@bashatest.howincloud.com 'D=/srv/stickbash-pages; if [ -n "$(git -C $D status --porcelain 2>/dev/null | head -1)" ]; then git -C $D stash push -u -q -m "autoheal $(date +%m%d-%H%M) (stray copies; never rsync here)" && echo "$(date) autoheal stash" >> /root/pages-autoheal.log; chown -R root:root $D; fi; bash /root/stickbash/kit/linux/pages_vm.sh pull 2>&1 | tail -1')
          say "synced $(git log -1 --format=%h) · VM: $vm"
        else
          say "push failed"
        fi
      fi
    fi
  fi
  sleep "$INTERVAL"
done
