Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
136 lines
3.9 KiB
Bash
Executable File
136 lines
3.9 KiB
Bash
Executable File
#!/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 "$@"
|