#!/usr/bin/env bash # 生产发布脚本 — 仅当用户明确要求「发布生产」时由人工/Agent 执行 # TKMind H5 → 105 服务器增量部署 # # 用法: # ./rsync_to_server.sh # 默认:同步 H5 并发布到 go.tkmind.cn # ./rsync_to_server.sh h5 # 同上 # ./rsync_to_server.sh goosed # 本地 Docker 编译 goosed 并上传 # ./rsync_to_server.sh all # H5 + goosed # ./rsync_to_server.sh h5 --skip-test # ./rsync_to_server.sh h5 --no-restart # # 典型流程: # cd ui/h5 && pnpm dev # 本地开发 # cd ui/h5 && pnpm run test:local # 本地验证 # ./rsync_to_server.sh # 同步到 105 set -euo pipefail ROOT="$(cd "$(dirname "$0")" && pwd)" H5_DIR="${ROOT}/ui/h5" DEPLOY_ENV="${ROOT}/deploy/h5-105.env" EXCLUDE_FILE="${ROOT}/deploy/.rsync-exclude-h5" H5_DEPLOY_HOST="${H5_DEPLOY_HOST:-root@120.26.184.105}" H5_REMOTE_DIR="${H5_REMOTE_DIR:-/root/tkmind_go/ui/h5}" H5_PROD_URL="${H5_PROD_URL:-https://go.tkmind.cn}" H5_SYSTEMD_SERVICE="${H5_SYSTEMD_SERVICE:-goose-h5}" GOOSED_DEPLOY_SCRIPT="${ROOT}/deploy/deploy-goosed-105.sh" TKMIND_API_SYSTEMD_SERVICE="${TKMIND_API_SYSTEMD_SERVICE:-goosed-tkmind-go}" TARGET="${1:-h5}" shift || true SKIP_TEST=0 SKIP_BUILD=0 NO_RESTART=0 for arg in "$@"; do case "$arg" in --skip-test) SKIP_TEST=1 ;; --skip-build) SKIP_BUILD=1 ;; --no-restart) NO_RESTART=1 ;; -h|--help) sed -n '2,16p' "$0" exit 0 ;; *) echo "未知参数: $arg" >&2 exit 1 ;; esac done if [[ -f "${DEPLOY_ENV}" ]]; then set -a # shellcheck disable=SC1090 source "${DEPLOY_ENV}" set +a fi ssh_cmd() { ssh -o ConnectTimeout=15 -o BatchMode=yes "${H5_DEPLOY_HOST}" "$@" } pkg_run() { cd "${H5_DIR}" if command -v pnpm >/dev/null 2>&1; then pnpm "$@" else npm "$@" fi } deploy_h5() { echo "======================================" echo "TKMind H5 → 105 部署" echo "时间: $(date '+%Y-%m-%d %H:%M:%S')" echo "本地: ${H5_DIR}" echo "远端: ${H5_DEPLOY_HOST}:${H5_REMOTE_DIR}" echo "公网: ${H5_PROD_URL}" echo "======================================" if [[ "${SKIP_TEST}" -eq 0 ]]; then echo "==> 本地测试..." cd "${H5_DIR}" pkg_run test fi echo "==> 迁移远端 temp → MindSpace(若存在)..." ssh_cmd "if [[ -d '${H5_REMOTE_DIR}/temp' && ! -d '${H5_REMOTE_DIR}/MindSpace' ]]; then mv '${H5_REMOTE_DIR}/temp' '${H5_REMOTE_DIR}/MindSpace'; fi" echo "==> rsync 同步 H5 代码(不含 MindSpace 用户数据)..." rsync -az --delete --exclude-from="${EXCLUDE_FILE}" \ "${H5_DIR}/" \ "${H5_DEPLOY_HOST}:${H5_REMOTE_DIR}/" if [[ "${SKIP_BUILD}" -eq 0 ]]; then echo "==> 远端构建..." ssh_cmd "cd '${H5_REMOTE_DIR}' && npm install && npm run build" fi if [[ "${NO_RESTART}" -eq 0 ]]; then echo "==> 重启服务..." ssh_cmd "systemctl is-active --quiet '${TKMIND_API_SYSTEMD_SERVICE}' || systemctl start '${TKMIND_API_SYSTEMD_SERVICE}'" ssh_cmd "systemctl restart '${H5_SYSTEMD_SERVICE}'" ssh_cmd "systemctl is-active --quiet nginx || systemctl start nginx" sleep 2 fi echo "" echo "=== 健康检查 ===" ssh_cmd "systemctl is-active '${TKMIND_API_SYSTEMD_SERVICE}' && echo '${TKMIND_API_SYSTEMD_SERVICE}: active' || echo '${TKMIND_API_SYSTEMD_SERVICE}: inactive'" ssh_cmd "systemctl is-active '${H5_SYSTEMD_SERVICE}' && echo '${H5_SYSTEMD_SERVICE}: active' || echo '${H5_SYSTEMD_SERVICE}: inactive'" ssh_cmd "curl -sk 'https://127.0.0.1:3000/status' && echo ' ← tkmind-api'" || true ssh_cmd "curl -s 'http://127.0.0.1:8080/api/status' && echo ' ← h5'" || true curl -s --max-time 20 -o /dev/null -w "${H5_PROD_URL} → %{http_code}\n" "${H5_PROD_URL}/" || true echo "" echo "✅ H5 已发布到 ${H5_PROD_URL}" } deploy_goosed() { local extra=() [[ "${SKIP_BUILD}" -eq 1 ]] && extra+=(--skip-build) [[ "${NO_RESTART}" -eq 1 ]] && extra+=(--no-restart) if ((${#extra[@]})); then "${GOOSED_DEPLOY_SCRIPT}" "${extra[@]}" else "${GOOSED_DEPLOY_SCRIPT}" fi } deploy_all() { deploy_h5 deploy_goosed } case "${TARGET}" in h5) deploy_h5 ;; goosed) deploy_goosed ;; all) deploy_all ;; *) echo "用法: ./rsync_to_server.sh [h5|goosed|all] [选项]" >&2 echo " 选项: --skip-test --skip-build --no-restart" >&2 exit 1 ;; esac