Files
shz-admin/scripts/deploy-production-frontend.sh

136 lines
3.9 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
set -Eeuo pipefail
# 正式环境部署参数固定在脚本中,避免通过环境变量误传到测试或其他服务器。
readonly ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
readonly BUILD_DIR="${ROOT_DIR}/shihezi"
readonly DEPLOY_HOST="47.111.103.66"
readonly DEPLOY_USER="root"
readonly DEPLOY_SSH_PORT="22"
readonly DEPLOY_PATH="/opt/service/project/shz-admin/dist"
DRY_RUN=0
info() {
printf '\033[1;32m%s\033[0m\n' "$*"
}
error() {
printf '\033[1;31m%s\033[0m\n' "$*" >&2
}
die() {
error "$*"
exit 1
}
usage() {
cat <<'EOF'
用法:
./scripts/deploy-production-frontend.sh
./scripts/deploy-production-frontend.sh --dry-run
功能:
1. 使用 npm run build 构建当前 PC 前端
2. 将 shihezi/ 上传到正式服务器的 Nginx 静态目录
3. 校验远程 index.html并比对本地与远程 SHA-256
正式环境参数(固定):
SSH 主机root@47.111.103.66:22
静态目录:/opt/service/project/shz-admin/dist
访问前缀:/shihezi/
参数:
--dry-run 只构建并检查产物,不连接服务器、不上传文件
-h, --help 显示帮助
说明:
脚本不会自动安装依赖。若 node_modules 不存在,请先执行 npm install。
上传使用 rsync --delete远程静态目录中本地没有的文件会被删除。
脚本使用当前用户已有的 SSH key/agent不保存密码。
EOF
}
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run)
DRY_RUN=1
;;
-h|--help)
usage
exit 0
;;
*)
die "未知参数:$1(使用 --help 查看用法)"
;;
esac
shift
done
}
validate_local_environment() {
command -v npm >/dev/null 2>&1 || die "未找到 npm"
command -v ssh >/dev/null 2>&1 || die "未找到 ssh"
command -v rsync >/dev/null 2>&1 || die "未找到 rsync"
command -v shasum >/dev/null 2>&1 || die "未找到 shasum无法校验构建产物"
[[ -f "${ROOT_DIR}/package.json" ]] || die "未找到 ${ROOT_DIR}/package.json"
[[ -d "${ROOT_DIR}/node_modules" ]] || die "未找到 node_modules请先执行 npm install"
}
build_frontend() {
info "开始构建正式前端npm run build"
npm run build
[[ -s "${BUILD_DIR}/index.html" ]] || die "构建完成但未找到 ${BUILD_DIR}/index.html"
info "本地构建完成:${BUILD_DIR}"
}
check_production_access() {
local target="${DEPLOY_USER}@${DEPLOY_HOST}"
info "检查正式服务器目录:${target}:${DEPLOY_PATH}/"
ssh -o BatchMode=yes -o ConnectTimeout=10 -p "${DEPLOY_SSH_PORT}" "${target}" \
"test -d '${DEPLOY_PATH}' && test -w '${DEPLOY_PATH}'"
}
upload_frontend() {
local target="${DEPLOY_USER}@${DEPLOY_HOST}"
local ssh_command="ssh -o BatchMode=yes -o ConnectTimeout=10 -p ${DEPLOY_SSH_PORT}"
if [[ "${DRY_RUN}" == "1" ]]; then
info "DRY RUN不会连接服务器或上传文件"
info "目标:${target}:${DEPLOY_PATH}/"
return
fi
check_production_access
info "上传构建产物:${BUILD_DIR}/ -> ${target}:${DEPLOY_PATH}/"
rsync -az --delete --delay-updates \
-e "${ssh_command}" \
"${BUILD_DIR}/" "${target}:${DEPLOY_PATH}/"
local local_hash
local remote_hash
local_hash="$(shasum -a 256 "${BUILD_DIR}/index.html" | awk '{print $1}')"
remote_hash="$(ssh -o BatchMode=yes -o ConnectTimeout=10 -p "${DEPLOY_SSH_PORT}" "${target}" \
"test -s '${DEPLOY_PATH}/index.html' && sha256sum '${DEPLOY_PATH}/index.html' | awk '{print \$1}'")"
[[ -n "${remote_hash}" ]] || die "远程 index.html 不存在或为空"
[[ "${local_hash}" == "${remote_hash}" ]] || die "远程 index.html 校验失败:本地 ${local_hash},远程 ${remote_hash}"
info "正式前端部署完成http://${DEPLOY_HOST}/shihezi/"
info "index.html SHA-256 校验通过:${local_hash}"
}
main() {
parse_args "$@"
cd "${ROOT_DIR}"
validate_local_environment
build_frontend
upload_frontend
}
main "$@"