paradramorama/deploy/deploy.sh
m3ultra 97a4a01b0b Deploy to monsterrobot.games/paradramorama
Games-lander pattern: rsync to the host path (RO bind mount into
forum-nginx, docker cp fails silently) + top-level symlink for the pretty
URL, no nginx change. Stamps a version query across the ES-module chain in
a staging copy because Cloudflare serves .js with max-age=14400 — without
it a redeploy shows stale code for hours.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 10:38:10 +10:00

62 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Deploy PARADRAMORAMA to monsterrobot.games/paradramorama (botchat/games VPS).
#
# The apex monsterrobot.games is a STATIC LANDING on humanjing@100.71.119.27:
# host /home/humanjing/monsterrobot.games -> forum-nginx
# /usr/share/nginx/html/games-lander (READ-ONLY bind mount)
# `docker cp` into the container FAILS SILENTLY because the mount is RO —
# always write to the host path, nginx serves it live.
#
# Routing needs NO nginx change: the apex server block ends in
# location / { try_files $uri $uri/ /index.html; }
# so any directory under the root is served directly. Games live in
# games/<name>/ with a top-level symlink for the pretty URL (same as
# mollycool, not-tonight).
#
# CACHE: Cloudflare fronts this domain and serves .js with max-age=14400 (4h).
# Without busting, a redeploy shows STALE CODE for hours. So the deploy stamps
# a version query onto the whole ES-module chain (index.html -> game.js ->
# world.js/audio.js) in a staging copy. Source files are never modified.
#
# Usage: ./deploy/deploy.sh
set -euo pipefail
VPS="humanjing@100.71.119.27"
LANDER="/home/humanjing/monsterrobot.games"
NAME="paradramorama"
SRC="$(cd "$(dirname "$0")/.." && pwd)"
URL="https://monsterrobot.games/${NAME}/"
STAMP="$(cd "$SRC" && git rev-parse --short HEAD 2>/dev/null || echo nogit)-$(date +%s)"
BUILD="$(mktemp -d /tmp/paradramorama_build_XXXXXX)"
trap 'rm -rf "$BUILD"' EXIT
echo "→ staging build ($STAMP)"
rsync -a --exclude '.git' --exclude '.gitignore' --exclude 'deploy' \
--exclude '.DS_Store' "$SRC/" "$BUILD/"
# stamp the module chain so Cloudflare + the browser always fetch fresh code
perl -pi -e "s{src=\"src/game\.js\"}{src=\"src/game.js?v=$STAMP\"}g" "$BUILD/index.html"
perl -pi -e "s{from '\./(world|audio)\.js'}{from './\$1.js?v=$STAMP'}g" "$BUILD/src/game.js"
grep -q "game.js?v=$STAMP" "$BUILD/index.html" || { echo "✗ stamp failed (index.html)"; exit 1; }
grep -q "world.js?v=$STAMP" "$BUILD/src/game.js" || { echo "✗ stamp failed (game.js imports)"; exit 1; }
echo "→ rsync → $VPS:$LANDER/games/$NAME/"
ssh "$VPS" "mkdir -p '$LANDER/games/$NAME'"
rsync -az --delete "$BUILD/" "$VPS:$LANDER/games/$NAME/"
echo "→ ensure pretty-URL symlink $LANDER/$NAME -> games/$NAME"
ssh "$VPS" "cd '$LANDER' && ln -sfn 'games/$NAME' '$NAME' && ls -ld '$NAME'"
echo "→ verifying live"
CB="$(date +%s)"
CODE=$(curl -sS -o /dev/null -w '%{http_code}' -L "${URL}?cb=${CB}" --max-time 25)
JS=$(curl -sS -o /dev/null -w '%{http_code}' -L "${URL}src/game.js?v=${STAMP}" --max-time 25)
SERVED=$(curl -sS -L "${URL}?cb=${CB}" --max-time 25 | grep -o "game\.js?v=[^\"]*" | head -1)
echo " index: $CODE game.js: $JS serving: $SERVED"
if [ "$CODE$JS" = "200200" ] && [ "$SERVED" = "game.js?v=$STAMP" ]; then
echo "✓ live at $URL"
else
echo "✗ NOT deployed cleanly (index=$CODE js=$JS served=$SERVED)"; exit 1
fi