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>
62 lines
2.8 KiB
Bash
Executable File
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
|