diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2bd5a0a --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/AGENTS.md b/AGENTS.md index 7137756..22435f8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2383,9 +2383,13 @@ Rules: `last-failure` marker; reports keep 12. Releases are one command via **`scripts/release.sh`** (notes check → `npm test` → bump → Android build → `zsp publish` → relay verification → commit/push + tag), reading the 0600 - `~/.config/skatespots/zsp.env` by default. The deploy timer has - `TimeoutStartSec=20min`, and all deploy/deps units are tracked in - `scripts/systemd/`. + `~/.config/skatespots/zsp.env` by default; pass `--deploy` to also force the + web deploy. `scripts/ops-health.sh` now reports the dep timers, next-due, + latest report/OSV and `last-failure`. The deploy timer has + `TimeoutStartSec=20min`, all deploy/deps units are tracked in + `scripts/systemd/`, and `.nvmrc` pins Node 22. A 2026-10-27 scan-only run + reports **3 packages / 4 OSV findings** (0 critical; `xlsx` is write-only and + the rest is dev build tooling). ### Community relay — self-hosted Newlay (2026-10-12) diff --git a/scripts/ops-health.sh b/scripts/ops-health.sh index d612806..5faffa0 100755 --- a/scripts/ops-health.sh +++ b/scripts/ops-health.sh @@ -204,6 +204,50 @@ if [ -f "$RUN_FILE" ]; then fi fi +# ── Dependency job ────────────────────────────────────────────────────────── +p "" +p "${B}Dependency job${N}" +DEPS_STATE="$HOME/.local/state/skatespots-deps" +DEPS_LAST="$DEPS_STATE/last-run" +DEPS_FAIL="$DEPS_STATE/last-failure" +DEPS_TIMER="$(systemctl --user is-active skatespots-deps.timer 2>/dev/null || echo unknown)" +SCAN_TIMER="$(systemctl --user is-active skatespots-deps-scan.timer 2>/dev/null || echo unknown)" +if [ "$DEPS_TIMER" = "active" ]; then + p " ${G}✓${N} 16-day dependency timer active ${DIM}(daily tick)${N}" +else + p " ${R}✗${N} dependency timer: ${DEPS_TIMER}" + problems+=("dependency timer is not active") + signature+="deps-timer;" +fi +if [ "$SCAN_TIMER" = "active" ]; then + p " ${G}✓${N} weekly CVE scan timer active" +else + p " ${Y}⚠${N} weekly CVE scan timer: ${SCAN_TIMER}" +fi +if [ -f "$DEPS_LAST" ]; then + deps_last="$(cat "$DEPS_LAST" 2>/dev/null || echo 0)" + # On success last-run is "now"; on failure it is "now - (interval - 3d)" so + # the next due date is the ~3-day retry, not a full 16-day wait. + deps_due=$(( deps_last + 16 * 86400 )) + if [ "$deps_due" -gt "$now" ]; then + p " ${DIM}next dependency update in ~$(human_age $((deps_due - now)))${N}" + else + p " ${Y}●${N} dependency update due at the next daily tick" + fi +fi +latest_report="$(ls -1t "$DEPS_STATE"/report-*.txt 2>/dev/null | head -1 || true)" +if [ -n "$latest_report" ]; then + osv="$(grep -E '^Total [0-9]+ packages affected' "$latest_report" | tail -1 || true)" + p " ${DIM}latest report: $(basename "$latest_report")${osv:+ — $osv}${N}" +fi +if [ -f "$DEPS_FAIL" ]; then + p " ${R}✗${N} last dependency run failed: $(cat "$DEPS_FAIL")" + problems+=("dependency update failed (see $DEPS_FAIL)") + signature+="deps-failed;" +else + p " ${G}✓${N} no recorded dependency failure" +fi + # ── Summary + optional notification ────────────────────────────────────────── p "" if [ ${#problems[@]} -eq 0 ]; then diff --git a/scripts/release.sh b/scripts/release.sh index a4c2772..87b5fbf 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -4,8 +4,10 @@ # Zapstore → verify → commit/push (+ optional git tag). # # Usage: -# scripts/release.sh patch|minor|major [--yes] -# scripts/release.sh 1.7.1 [--yes] +# scripts/release.sh patch|minor|major [--yes] [--deploy] +# scripts/release.sh 1.7.1 [--yes] [--deploy] +# --deploy also forces the web deploy (bypasses the 24h Netlify throttle, +# costs 15 credits); without it the deploy timer ships it shortly. # # Before running: # 1. write the new section at the TOP of release-notes.txt (do not commit it — @@ -23,8 +25,12 @@ ZSP="${ZSP:-$HOME/go/bin/zsp}" export ANDROID_HOME="${ANDROID_HOME:-$HOME/Android/Sdk}" SPEC="${1:-}" YES=0 +DEPLOY=0 shift || true -for a in "$@"; do [ "$a" = "--yes" ] && YES=1; done +for a in "$@"; do + [ "$a" = "--yes" ] && YES=1 + [ "$a" = "--deploy" ] && DEPLOY=1 +done die() { echo "✗ $*" >&2; exit 1; } log() { echo "• $*"; } @@ -129,9 +135,18 @@ if ! git push origin "v$VERSION" 2>/dev/null; then log "warning: tag v$VERSION was created locally but the push failed" fi +if [ "$DEPLOY" -eq 1 ]; then + log "forcing the web deploy (bypasses the 24h Netlify throttle)…" + scripts/auto-deploy.sh --force || log "warning: web deploy failed — check journalctl --user -u skatespots-deploy" +fi + echo echo "✓ SkateSpots $VERSION published" echo " APK: $APK" echo " SHA256: $SHA" -echo " Web: the deploy timer picks up the commit within ~3 min (24h throttle)" +if [ "$DEPLOY" -eq 1 ]; then + echo " Web: forced deploy requested above" +else + echo " Web: the deploy timer picks up the commit within ~3 min (24h throttle)" +fi echo " Zapstore: https://zapstore.dev/apps/org.skatespots.app"