diff --git a/docs/deploy.md b/docs/deploy.md index 276f017d..f22a0f63 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -41,7 +41,14 @@ Nginx 80/443 ## 更新游戏文件 -源码有改动后,在本机执行: +上述流程已封装为一键脚本 `tools/deploy.sh`(git pull --ff-only + rsync + +chown + 冒烟验证),在部署服务器上执行: + +```bash +bash tools/deploy.sh +``` + +等价的手动步骤(源码有改动后,在本机执行): ```bash sudo rsync -a --delete \ @@ -52,7 +59,9 @@ sudo rsync -a --delete \ sudo chown -R www-data:www-data /var/www/soundgame ``` -静态文件即时生效,不必 reload Nginx。改了 `soundgame.conf` 才需要: +静态文件即时生效,不必 reload Nginx;配合全站 `no-cache` 缓存策略,用户下次 +打开页面即可拿到新文件(2026-09-07 之前 js/css 曾是 24h 强缓存,部署后旧 JS +在用户浏览器里滞留一天,表现为"改了却没生效")。改了 `soundgame.conf` 才需要: ```bash sudo nginx -t && sudo systemctl reload nginx @@ -111,6 +120,11 @@ server { root /var/www/soundgame; index index.html; + # 全站 no-cache:可缓存但必须回源验证(ETag→304)。 + # 2026-09-07 教训:此前 js/css 是 max-age=86400 public,引擎修复部署后 + # 用户浏览器 24h 内仍执行旧 audio.js,句尾截断"修不好"。静态小站回源 + # 验证成本可忽略,换取每次部署立即生效。 + add_header Cache-Control "no-cache"; add_header X-Content-Type-Options nosniff; add_header Referrer-Policy strict-origin-when-cross-origin; @@ -123,15 +137,13 @@ server { } location ~* \.(ogg|m4a|mp3|wav|png|jpg|jpeg|gif|ico|svg|woff2?)$ { - expires 7d; - add_header Cache-Control "public"; + add_header Cache-Control "no-cache"; add_header X-Content-Type-Options nosniff; access_log off; } location ~* \.(js|css)$ { - expires 1d; - add_header Cache-Control "public"; + add_header Cache-Control "no-cache"; add_header X-Content-Type-Options nosniff; } } diff --git a/tools/deploy.sh b/tools/deploy.sh new file mode 100755 index 00000000..defa0e32 --- /dev/null +++ b/tools/deploy.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# deploy.sh — 部署服务器一键上线(git pull → rsync → 冒烟验证) +# +# 用法(部署服务器上): +# bash tools/deploy.sh +# +# 做三件事: +# 1. git pull --ff-only 拉最新代码(本地有未提交改动且与远端 +# 冲突时会中止,报错信息 git 自带) +# 2. rsync web/ → /var/www/soundgame(排除开发用文件;--delete 与源保持 +# 精确一致)+ chown www-data +# 3. 冒烟验证线上关键 URL(大厅 / 子站 / 301 / 音频 Range) +# +# 静态文件即时生效;全站 no-cache(ETag→304),用户下次打开页面即拿到 +# 新版。只有改了 nginx 配置(sites-available/soundgame.conf)才需要另行: +# sudo nginx -t && sudo systemctl reload nginx +# +# 完整部署说明见 docs/deploy.md。 + +set -euo pipefail + +REPO=$(cd "$(dirname "$0")/.." && pwd) # 仓库根(本脚本在 tools/ 下) +DEST=/var/www/soundgame +BASE=https://game.xiangsilian.com + +echo '==> git pull' +git -C "$REPO" pull --ff-only + +echo "==> rsync $REPO/web/ → $DEST" +sudo rsync -a --delete \ + --exclude harness/ --exclude gen/ --exclude test/ \ + --exclude server/ --exclude template/ \ + --exclude '*.py' --exclude '*.md' --exclude '*.sh' \ + "$REPO/web/" "$DEST/" +sudo chown -R www-data:www-data "$DEST" + +echo '==> 冒烟验证' +ok=1 +check() { # check <描述> <期望状态码> [额外 curl 参数...] + local desc=$1 expect=$2 url=$3 + shift 3 + local code + code=$(curl -sk -o /dev/null -w '%{http_code}' "$@" "$url" || true) + if [ "$code" = "$expect" ]; then + echo " PASS $code $desc" + else + echo " FAIL $code(期望 $expect) $desc" + ok=0 + fi +} +check '大厅(HTTPS)' 200 "$BASE/" +check 'HTTP→301 跳 HTTPS' 301 "http://game.xiangsilian.com/" +check 'rpg 子站' 200 "$BASE/rpg/" +check 'dungeon 子站' 200 "$BASE/dungeon/" +check '音频 Range 206' 206 "$BASE/rpg/audio/bgm/boss.ogg" -H 'Range: bytes=0-1023' + +if [ "$ok" = 1 ]; then + echo '==> 部署完成:用户下次打开页面即拿到新版(no-cache 回源验证)' +else + echo '==> 冒烟有失败项,请检查上方 FAIL 行' >&2 + exit 1 +fi