diff --git a/.gitignore b/.gitignore index e2546c8..cac4aa1 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ skatespots.zip # Generated native project (recreate with `npm run android:init`) /android/ + +# Netlify CLI link state +.netlify diff --git a/AGENTS.md b/AGENTS.md index 4945f21..e604adf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,7 +47,9 @@ The committed `package-lock.json` (from commit `f25fc2b`) had entries stripped o 2. Update the **top** section of `release-notes.txt` (format: `vX.Y.Z`, blank line, notes, then `---` before older versions). ### Deploy -- **Web**: `npm run build` produces the web `dist/` (with `_headers`/`_redirects`); deploy via shakespeare.diy (preferred) or drag `dist/` to the Netlify site's Deploys tab. +- **Web (auto)**: a systemd user timer (`skatespots-deploy.timer`) runs `scripts/auto-deploy.sh` every ~3 min. When `origin/main` changes it builds and runs `netlify deploy --prod --dir=dist`. It deploys **only committed code** (skips if tracked files are modified) and never mutates a dirty tree. One-time setup: `netlify login` + `netlify link`. Logs: `journalctl --user -u skatespots-deploy`. Manual run: `scripts/auto-deploy.sh`. + - ⚠️ Shakespeare's "Deploy" rebuilds **its own workspace**, which is NOT updated by git pushes — so pushing to the repo does not change what Shakespeare deploys. Prefer the auto-deploy timer (or drag `dist/` to Netlify). +- **Web (manual)**: `npm run build` produces the web `dist/` (with `_headers`/`_redirects`); deploy by dragging `dist/` to the Netlify site's Deploys tab. - **Zapstore (Android)**, from the repo root: `SIGN_WITH='bunker://...' zsp publish zapstore.yaml` - `zsp publish --wizard` is **broken for this app** (the wizard can't parse a nostrhub web `repository` — it supports only GitHub/GitLab/Gitea/F-Droid/local). Always pass `zapstore.yaml`. - No NIP-07 browser extension is installed, so `SIGN_WITH=browser` fails. Use `bunker://…` (Amber) or `nsec1…`. diff --git a/scripts/auto-deploy.sh b/scripts/auto-deploy.sh new file mode 100755 index 0000000..0854a11 --- /dev/null +++ b/scripts/auto-deploy.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# +# Auto-deploy SkateSpots to Netlify when the published origin/main changes. +# +# Driven by the systemd user timer `skatespots-deploy.timer`. It is SAFE by +# construction: it only ever deploys committed code, and it never touches a +# dirty working tree. +# +# One-time setup (see AGENTS.md): +# netlify login +# netlify link # choose the existing SkateSpots site +# +# Manual run / debug: +# scripts/auto-deploy.sh +# journalctl --user -u skatespots-deploy -n 50 +# +set -euo pipefail + +REPO="/home/sovereignsk8/SkateSpots" +# systemd runs with a minimal PATH; node/npm live under nvm here. +export PATH="/home/sovereignsk8/.nvm/versions/node/v22.23.1/bin:$PATH" + +STATE_DIR="$HOME/.local/state/skatespots-deploy" +SHA_FILE="$STATE_DIR/last-deployed-sha" +LOCK_FILE="$STATE_DIR/last-lock-hash" +mkdir -p "$STATE_DIR" + +log() { echo "[$(date -Is)] $*"; } + +# Serialise runs (a slow deploy must not overlap the next timer tick). +exec 9>"$STATE_DIR/.lock" +if ! flock -n 9; then + log "another deploy is already running — skipping" + exit 0 +fi + +cd "$REPO" + +# 1. What is published now? +if ! git fetch --quiet origin main; then + log "git fetch failed — skipping" + exit 0 +fi + +REMOTE_SHA="$(git rev-parse origin/main)" +LAST_SHA="$(cat "$SHA_FILE" 2>/dev/null || true)" + +if [ "$REMOTE_SHA" = "$LAST_SHA" ]; then + exit 0 # nothing new since the last deploy +fi + +# 2. Only deploy committed code (ignore untracked build/generated files). +if [ -n "$(git status --porcelain --untracked-files=no)" ]; then + log "origin/main moved to ${REMOTE_SHA:0:9} but tracked files are modified — skipping" + exit 0 +fi + +# 3. Move the repo to the published commit (fast-forward only). +if [ "$(git rev-parse HEAD)" != "$REMOTE_SHA" ]; then + if git merge --ff-only --quiet origin/main; then + log "fast-forwarded to ${REMOTE_SHA:0:9}" + else + log "local main has diverged from origin/main — skipping" + exit 0 + fi +fi + +# 4. Re-install only when the lockfile changed (avoid `npm run build`'s own `npm i`, +# which can rewrite the lock and dirty the tree). +LOCK_HASH="$(git rev-parse HEAD:package-lock.json)" +if [ "$LOCK_HASH" != "$(cat "$LOCK_FILE" 2>/dev/null || true)" ]; then + log "package-lock changed — npm ci" + npm ci --silent + echo "$LOCK_HASH" > "$LOCK_FILE" +fi + +# 5. Build the web bundle directly (skip the `npm i` in `npm run build`). +log "building…" +./node_modules/.bin/vite build -l error +cp dist/index.html dist/404.html + +# 6. Deploy to Netlify production. +log "deploying to Netlify…" +netlify deploy --prod --dir=dist + +echo "$REMOTE_SHA" > "$SHA_FILE" +log "deployed ${REMOTE_SHA:0:9} ✓"