diff --git a/scripts/deploy-artifact-to-eric-turner.sh b/scripts/deploy-artifact-to-eric-turner.sh new file mode 100755 index 0000000..51df4a3 --- /dev/null +++ b/scripts/deploy-artifact-to-eric-turner.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +set -euo pipefail + +# deploy-artifact-to-eric-turner.sh +# +# Deploy the Signal & Noise interactive HTML artifact to the eric-turner.com +# Hugo site, then force Hugo to pick up the change by touching hugo.yaml. +# +# Why touch hugo.yaml? Hugo runs as `hugo server --poll 1s` in a Docker +# bind-mount. The poll watcher detects changes in the top-level file tree +# reliably, but NEW subdirectories under static/ (added via scp after the +# server started) don't always get picked up by the watcher's in-memory +# state. The config-file watch is more reliable — touching hugo.yaml +# triggers a full rebuild, which re-reads all static/ subdirectories and +# invalidates any stale file cache. +# +# This is the durable fix for the "I scp'd the file but the live URL still +# shows the old version" problem we hit twice. Always use this script +# (or `touch hugo.yaml` after any manual scp) instead of raw scp. +# +# Usage: +# bash scripts/deploy-artifact-to-eric-turner.sh +# bash scripts/deploy-artifact-to-eric-turner.sh --verify +# +# Requires SSH access to root@10.13.0.254 and Hugo running in +# /mnt/user/docker/showcase. + +REMOTE_HOST="root@10.13.0.254" +REMOTE_DIR="/mnt/user/docker/showcase" +REMOTE_STATIC_DIR="${REMOTE_DIR}/static/memex" +REMOTE_HUGO_CONFIG="${REMOTE_DIR}/hugo.yaml" +PUBLIC_URL="https://eric-turner.com/memex/signal-and-noise.html" + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +LOCAL_HTML="${REPO_ROOT}/docs/artifacts/signal-and-noise.html" + +VERIFY=false +while [[ $# -gt 0 ]]; do + case "$1" in + --verify) VERIFY=true; shift ;; + -h|--help) + sed -n '3,27p' "$0" | sed 's/^# \?//' + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +if [[ ! -f "${LOCAL_HTML}" ]]; then + echo "Local file not found: ${LOCAL_HTML}" >&2 + exit 1 +fi + +log() { printf '[%s] %s\n' "$(date '+%H:%M:%S')" "$*"; } + +log "uploading $(basename "${LOCAL_HTML}") ($(wc -c < "${LOCAL_HTML}") bytes) to ${REMOTE_HOST}:${REMOTE_STATIC_DIR}/" +ssh "${REMOTE_HOST}" "mkdir -p ${REMOTE_STATIC_DIR}" +scp -q "${LOCAL_HTML}" "${REMOTE_HOST}:${REMOTE_STATIC_DIR}/signal-and-noise.html" + +log "touching ${REMOTE_HUGO_CONFIG} to trigger Hugo config reload" +ssh "${REMOTE_HOST}" "touch ${REMOTE_HUGO_CONFIG}" + +log "waiting 3s for Hugo to rebuild..." +sleep 3 + +if ${VERIFY}; then + log "verifying live URL content..." + live_content="$(curl -sS --max-time 10 "${PUBLIC_URL}")" + + local_title="$(grep -o '[^<]*' "${LOCAL_HTML}" | head -1)" + live_title="$(echo "${live_content}" | grep -o '[^<]*' | head -1)" + + if [[ "${local_title}" == "${live_title}" ]]; then + log "✓ title matches: ${live_title}" + else + log "✗ title mismatch!" + log " local: ${local_title}" + log " live: ${live_title}" + log " Hugo may still be rebuilding. Retry in a few seconds or check ssh ${REMOTE_HOST} 'docker logs showcase-hugo-1'" + exit 1 + fi + + # Count tab buttons — match both "tab-btn" and "tab-btn active" + local_tabs="$(grep -cE 'class="tab-btn[^"]*".*onclick' "${LOCAL_HTML}" || true)" + live_tabs="$(echo "${live_content}" | grep -cE 'class="tab-btn[^"]*".*onclick' || true)" + if [[ "${local_tabs}" == "${live_tabs}" ]]; then + log "✓ tab count matches: ${live_tabs} tabs" + else + log "✗ tab count mismatch: local=${local_tabs} live=${live_tabs}" + exit 1 + fi +fi + +log "deployed → ${PUBLIC_URL}"