Executable
+94
@@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
# 91短剧测试服:构建 → 测试 → tar.gz + SHA-256 → 可选上传并执行 run.sh。
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
cd "$SCRIPT_DIR"
|
||||
source "$SCRIPT_DIR/scripts/deploy-common.sh"
|
||||
HOST="${DEPLOY_HOST:-root@172.104.181.99}"
|
||||
SSH_PORT="${DEPLOY_SSH_PORT:-22889}"
|
||||
# 保留 91dj-web 已约定的上传位置;项目包和 Supervisor 标识使用 91dj。
|
||||
REMOTE_DIR="${DEPLOY_DIR:-/server/web_91dj/h5}"
|
||||
# 远端启动脚本目录独立于上传目录,按服务器约定执行。
|
||||
RUN_DIR="${DEPLOY_RUN_DIR:-/server/web_91dj/h5}"
|
||||
CHECK_URL="${DEPLOY_CHECK_URL:-}"
|
||||
PACKAGE_NAME="${DEPLOY_PACKAGE_NAME:-web_91dj_h5.tar.gz}"
|
||||
CHECKSUM_NAME="$PACKAGE_NAME.sha256"
|
||||
PACKAGE_ONLY=0
|
||||
for argument in "$@"; do
|
||||
case "$argument" in
|
||||
--dry-run) DEPLOY_DRY_RUN=1 ;;
|
||||
--package-only) PACKAGE_ONLY=1 ;;
|
||||
-h|--help)
|
||||
printf '用法:%s [--dry-run] [--package-only]\n' "$0"
|
||||
printf '仅打包:--package-only。仅预览:--dry-run(不构建、不联网)。\n'
|
||||
printf '上传目标:%s:%s %s/。\n' "$HOST" "$SSH_PORT" "${REMOTE_DIR%/}"
|
||||
printf '上传成功后:ssh -p %s %s "cd %s && bash run.sh"\n' "$SSH_PORT" "$HOST" "$RUN_DIR"
|
||||
printf '可覆盖 DEPLOY_HOST、DEPLOY_DIR、DEPLOY_RUN_DIR(%s)、DEPLOY_SSH_PORT、DEPLOY_PACKAGE_NAME(%s)、DEPLOY_CHECK_URL。\n' "$RUN_DIR" "$PACKAGE_NAME"
|
||||
exit 0 ;;
|
||||
*) fail "不支持的参数 $argument" ;;
|
||||
esac
|
||||
done
|
||||
[[ "$PACKAGE_NAME" =~ ^[a-zA-Z0-9_][a-zA-Z0-9_.-]*\.tar\.gz$ ]] || fail 'DEPLOY_PACKAGE_NAME 必须是 .tar.gz 文件名'
|
||||
if [ "$PACKAGE_ONLY" = 0 ] && [ "${DEPLOY_DRY_RUN:-0}" != 1 ]; then
|
||||
valid_host "$HOST" DEPLOY_HOST; valid_path "$REMOTE_DIR" DEPLOY_DIR; valid_path "$RUN_DIR" DEPLOY_RUN_DIR; valid_port "$SSH_PORT" DEPLOY_SSH_PORT
|
||||
need ssh; need scp
|
||||
fi
|
||||
check_local test
|
||||
if [ -n "$CHECK_URL" ]; then
|
||||
node --input-type=module -e 'const u=new URL(process.argv[1]);if(!["http:","https:"].includes(u.protocol)||u.username||u.password||u.search||u.hash||u.pathname!=="/")process.exit(1)' "$CHECK_URL" || fail 'DEPLOY_CHECK_URL 必须是 HTTP(S) 站点根地址'
|
||||
fi
|
||||
if [ "${DEPLOY_DRY_RUN:-0}" = 1 ]; then
|
||||
printf 'DRY RUN:测试环境;不构建、不连接服务器。\n'; public_profile test
|
||||
printf ' npm run build:test → npm test → npm run bundle:test → %s + %s\n' "$PACKAGE_NAME" "$CHECKSUM_NAME"
|
||||
printf ' 包内不含 node_modules、本地环境覆盖和缓存;服务端 npm ci --omit=dev 后 node start.mjs。\n'
|
||||
if [ "$PACKAGE_ONLY" = 1 ]; then printf ' 仅生成本地包。\n'
|
||||
else
|
||||
printf ' 发布目标:%s:%s(SSH %s)。\n' "$HOST" "$REMOTE_DIR" "$SSH_PORT"
|
||||
printf ' 上传 %s、%s 和 up_next_h5.sh。\n' "$PACKAGE_NAME" "$CHECKSUM_NAME"
|
||||
printf ' 上传成功后:ssh -p %s %s "cd %s && bash run.sh"\n' "$SSH_PORT" "$HOST" "$RUN_DIR"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
need tar
|
||||
[ -s deploy/up_next_h5.sh ] || fail '缺少 deploy/up_next_h5.sh'
|
||||
bash -n deploy/up_next_h5.sh
|
||||
lock_build
|
||||
step '构建测试环境并运行回归测试'
|
||||
npm run build:test
|
||||
TEST_APP_ENV=test npm test
|
||||
step '整理 standalone 测试包'
|
||||
npm run bundle:test
|
||||
for file in start.mjs server.js .next-test/BUILD_ID config/test.env; do
|
||||
[ -s "dist/test/$file" ] || fail "测试包缺少 $file"
|
||||
done
|
||||
[ -d dist/test/.next-test/static ] && [ -d dist/test/public ] || fail '测试包缺少静态资源'
|
||||
step "生成 $PACKAGE_NAME 和 SHA-256"
|
||||
TEMP_PACKAGE=$(mktemp "$SCRIPT_DIR/dist/.test-archive.XXXXXX")
|
||||
if ! COPYFILE_DISABLE=1 COPY_EXTENDED_ATTRIBUTES_DISABLE=1 tar --no-xattrs \
|
||||
--exclude='node_modules' --exclude='*/node_modules' --exclude='._*' --exclude='.DS_Store' \
|
||||
--exclude='*.local.env' --exclude='.env*' --exclude='*.log' \
|
||||
-czf "$TEMP_PACKAGE" -C dist/test .; then
|
||||
rm -f "$TEMP_PACKAGE"; fail '压缩失败'
|
||||
fi
|
||||
tar -tzf "$TEMP_PACKAGE" >/dev/null
|
||||
mv -f "$TEMP_PACKAGE" "$PACKAGE_NAME"
|
||||
chmod 600 "$PACKAGE_NAME"
|
||||
node --input-type=module - "$PACKAGE_NAME" "$CHECKSUM_NAME" <<'NODE'
|
||||
import {createHash} from 'node:crypto';
|
||||
import {readFileSync,writeFileSync} from 'node:fs';
|
||||
const [archive,checksum]=process.argv.slice(2);
|
||||
const bytes=readFileSync(archive);
|
||||
writeFileSync(checksum,createHash('sha256').update(bytes).digest('hex')+' '+archive+'\n');
|
||||
// The test and production commands share a package name; refresh its companion checksum too.
|
||||
writeFileSync(archive.replace(/\.tar\.gz$/,'.md5'),createHash('md5').update(bytes).digest('hex')+'\n');
|
||||
NODE
|
||||
printf '测试包:%s/%s;校验:%s/%s\n' "$SCRIPT_DIR" "$PACKAGE_NAME" "$SCRIPT_DIR" "$CHECKSUM_NAME"
|
||||
if [ "$PACKAGE_ONLY" = 1 ]; then exit 0; fi
|
||||
step "上传到 $HOST:$REMOTE_DIR/"
|
||||
ssh -p "$SSH_PORT" "$HOST" "mkdir -p '$REMOTE_DIR'"
|
||||
scp -P "$SSH_PORT" "$PACKAGE_NAME" "$CHECKSUM_NAME" deploy/up_next_h5.sh "$HOST:$REMOTE_DIR/"
|
||||
printf '测试包上传完成:%s:%s/%s\n' "$HOST" "${REMOTE_DIR%/}" "$PACKAGE_NAME"
|
||||
step "执行测试服 $RUN_DIR/run.sh"
|
||||
ssh -p "$SSH_PORT" "$HOST" "cd '$RUN_DIR' && bash run.sh"
|
||||
if [ -n "$CHECK_URL" ]; then node scripts/check-health.mjs "$CHECK_URL" test; fi
|
||||
printf '测试服 run.sh 执行完成:%s:%s/run.sh\n' "$HOST" "${RUN_DIR%/}"
|
||||
Reference in New Issue
Block a user