Files

181 lines
5.0 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 本地执行:SSH 到服务器拉代码并发布(支持 staging / production 同机双栈)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ENV_FILE="$SCRIPT_DIR/deploy.env"
DEPLOY_HOST=""
DEPLOY_USER="root"
DEPLOY_PORT="22"
DEPLOY_SSH_KEY=""
APP_ROOT=""
GIT_REMOTE="origin"
GIT_BRANCH=""
DUKANG_DEPLOY_ENV=""
CHECK_ONLY=false
RELEASE_ARGS=()
usage() {
cat <<'EOF'
用法: deploy/deploy.sh --env staging|production [选项] [-- 远程 release 参数]
环境配置: deploy/deploy.env(可复制 deploy.env.example
选项:
--env ENV staging(测试)| production(生产)【必填,或用 deploy-staging/prod.sh】
--host HOST 服务器地址(覆盖 deploy.env
--user USER SSH 用户,默认 root
--port PORT SSH 端口,默认 22
--key PATH SSH 私钥路径
--branch BRANCH 发布分支(staging 默认 devproduction 默认 main
--check 仅 SSH 连接并查看 PM2 / 端口状态
-h, --help 显示帮助
示例:
./deploy/deploy-staging.sh -- --skip-db
./deploy/deploy-prod.sh -- --skip-db
./deploy/deploy.sh --env staging --branch dev -- --skip-db
./deploy/deploy.sh --env production --branch main -- --skip-db
EOF
}
load_env() {
if [[ -f "$ENV_FILE" ]]; then
# shellcheck disable=SC1090
source "$ENV_FILE"
fi
}
load_env
# CLI 覆盖 deploy.env(须在 load_env 之后解析)
CLI_ENV=""
CLI_BRANCH=""
while [[ $# -gt 0 ]]; do
case "$1" in
--env) CLI_ENV="$2"; shift 2 ;;
--host) DEPLOY_HOST="$2"; shift 2 ;;
--user) DEPLOY_USER="$2"; shift 2 ;;
--port) DEPLOY_PORT="$2"; shift 2 ;;
--key) DEPLOY_SSH_KEY="$2"; shift 2 ;;
--branch) CLI_BRANCH="$2"; shift 2 ;;
--check) CHECK_ONLY=true; shift ;;
-h|--help) usage; exit 0 ;;
--)
shift
RELEASE_ARGS=("$@")
break
;;
*) RELEASE_ARGS+=("$1"); shift ;;
esac
done
if [[ -n "$CLI_ENV" ]]; then
DUKANG_DEPLOY_ENV="$CLI_ENV"
fi
# 兼容旧调用:未传 --env 时,若 GIT_BRANCH=main 视为生产,否则 staging
if [[ -z "$DUKANG_DEPLOY_ENV" ]]; then
if [[ "${CLI_BRANCH:-${GIT_BRANCH:-}}" == "main" || "${CLI_BRANCH:-${GIT_BRANCH:-}}" == "master" ]]; then
DUKANG_DEPLOY_ENV=production
else
DUKANG_DEPLOY_ENV=staging
echo "WARN: 未指定 --env,默认按 staging 发测试环境。生产请用 --env production 或 deploy-prod.sh" >&2
fi
fi
case "$DUKANG_DEPLOY_ENV" in
staging|stage|test) DUKANG_DEPLOY_ENV=staging ;;
production|prod) DUKANG_DEPLOY_ENV=production ;;
*)
echo "错误: --env 须为 staging 或 production" >&2
exit 1
;;
esac
if [[ "$DUKANG_DEPLOY_ENV" == "staging" ]]; then
APP_ROOT="${STAGING_APP_ROOT:-${APP_ROOT:-/opt/dukang-staging}}"
# 若 deploy.env 里 APP_ROOT 仍是生产路径,staging 强制用 STAGING_APP_ROOT 或默认
if [[ -n "${STAGING_APP_ROOT:-}" ]]; then
APP_ROOT="$STAGING_APP_ROOT"
elif [[ "$APP_ROOT" == "/opt/dukang" ]]; then
APP_ROOT="/opt/dukang-staging"
fi
# 测试固定默认 devCLI --branch 优先,忽略 deploy.env 里误配的 main
GIT_BRANCH="${CLI_BRANCH:-dev}"
PORT_GREP='819[0-4]'
else
APP_ROOT="${PROD_APP_ROOT:-${APP_ROOT:-/opt/dukang}}"
if [[ -n "${PROD_APP_ROOT:-}" ]]; then
APP_ROOT="$PROD_APP_ROOT"
elif [[ "$APP_ROOT" == "/opt/dukang-staging" ]]; then
APP_ROOT="/opt/dukang"
fi
# 生产固定默认 mainCLI --branch 优先,忽略 deploy.env 里误配的 dev
GIT_BRANCH="${CLI_BRANCH:-main}"
PORT_GREP='809[0-4]'
fi
if [[ -z "$DEPLOY_HOST" ]]; then
echo "错误: 未配置 DEPLOY_HOST。请创建 deploy/deploy.env 或使用 --host" >&2
exit 1
fi
SSH_OPTS=(-o "StrictHostKeyChecking=accept-new" -p "$DEPLOY_PORT")
if [[ -n "$DEPLOY_SSH_KEY" ]]; then
SSH_OPTS+=(-i "$DEPLOY_SSH_KEY")
fi
TARGET="${DEPLOY_USER}@${DEPLOY_HOST}"
run_remote() {
ssh "${SSH_OPTS[@]}" "$TARGET" "$@"
}
if [[ "$CHECK_ONLY" == true ]]; then
echo "==> 检查 $TARGET ($DUKANG_DEPLOY_ENV)"
run_remote "pm2 list; ss -tlnp | grep -E '$PORT_GREP' || true"
exit 0
fi
REMOTE_RELEASE_ARGS=""
if [[ ${#RELEASE_ARGS[@]} -gt 0 ]]; then
REMOTE_RELEASE_ARGS="${RELEASE_ARGS[*]}"
fi
echo "==> 发布到 $TARGET env=$DUKANG_DEPLOY_ENV branch=$GIT_BRANCH root=$APP_ROOT"
run_remote bash -s <<EOF
set -euo pipefail
APP_ROOT="$APP_ROOT"
GIT_REMOTE="$GIT_REMOTE"
GIT_BRANCH="$GIT_BRANCH"
RELEASE_ARGS="$REMOTE_RELEASE_ARGS"
DUKANG_DEPLOY_ENV="$DUKANG_DEPLOY_ENV"
export DEPLOY_TRIGGER=manual
export APP_ROOT
export DUKANG_DEPLOY_ENV
cd "\$APP_ROOT"
if [[ ! -d .git ]]; then
echo "错误: \$APP_ROOT 不是 git 仓库。请先 clone 到该目录(staging 建议 /opt/dukang-staging" >&2
exit 1
fi
echo "==> 拉取代码"
git fetch "\$GIT_REMOTE"
git checkout "\$GIT_BRANCH"
git pull --ff-only "\$GIT_REMOTE" "\$GIT_BRANCH"
# 无额外参数时执行 DB 同步;无 schema 变更请显式传 -- --skip-db
if [[ -n "\$RELEASE_ARGS" ]]; then
bash deploy/remote-release.sh \$RELEASE_ARGS
else
bash deploy/remote-release.sh
fi
EOF
echo "==> 本地发布命令已完成 ($DUKANG_DEPLOY_ENV)"