Some checks failed
Deploy Backend / deploy (push) Has been cancelled
P0 - Panic 风险修复: - payment.rs: unwrap() → let-else safe handling - payment.rs: get_jwt_secret() expect → Result/AppError - auth.rs: openid 切片添加 len >= 8 守卫 - main.rs: 启动时 expect → unwrap_or_else 描述性 panic - main.rs: Directive::from_str 添加 fallback P1 - 逻辑/安全修复: - payment.rs: urlencoding() + 解码 bug 修复 (移除 had_escape) - payment.rs: Mock 支付添加 check_mock_payment_allowed 检查 - db.rs: 永久会员 NULL → 2099-12-31 一致化 - user.rs: 维护模式添加安全说明注释 - 自动清理 unused_variables 警告 (_is_mobile) P2 - 错误吞没修复: - main.rs: 3 处定时任务 let _ = → if let Err = tracing::error! - db.rs + admin.rs: 7 处通知/审计日志 let _ = → tracing::warn! - auth.rs: refresh token 保存 add warn 日志 P3 - 死代码清理: - models.rs: 移除 TokenResponse (dead) - models.rs: 移除 AppState 中 5 个未使用字段 (env var 直接读取) - error.rs: 移除 3 个 dead ErrorResponse 方法 - rate_limiter.rs: extract_client_ip_from_header → #[cfg(test)] - models.rs: 注释 typo fix (user_ytpe → user_type) - db.rs: RefreshToken 添加 deserialization 注释 Shell 脚本修复: - deploy.sh: run_migrations 移到 restart_service 之前 - test.sh: 移除 EXIT trap 覆盖; heredoc 引号修复; 维护模式添加 restart - common.sh: mock_key 添加 sed 转义 (防 / & 注入) 验证: cargo check 0 warnings, 8 tests passed
212 lines
7.8 KiB
Bash
Executable File
212 lines
7.8 KiB
Bash
Executable File
#!/bin/bash
|
||
# ===========================================
|
||
# Rust Backend Deployment Script
|
||
# ===========================================
|
||
# Usage: ./deploy.sh [development|production] [options]
|
||
#
|
||
# Options:
|
||
# --dry-run 预览模式
|
||
# --yes, -y 跳过确认
|
||
# --skip-tests 跳过部署后测试
|
||
# --rollback 回滚到指定备份
|
||
# --backup-list 列出可用备份
|
||
# --logs [N] 查看后端日志(默认50行)
|
||
# --tail [N] 实时跟踪日志
|
||
# --status 查看服务状态
|
||
# --post-logs 部署后显示日志
|
||
# --init-env 初始化 systemd service 模板
|
||
# --deploy-service 上传 systemd service 文件到服务器
|
||
# --target blue|green 蓝绿部署目标(默认单实例)
|
||
# --remote-host IP 部署目标服务器(默认 1panel-server)
|
||
# ===========================================
|
||
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
source "${SCRIPT_DIR}/lib/common.sh"
|
||
source "${SCRIPT_DIR}/lib/test.sh"
|
||
|
||
# ---------- 默认值 ----------
|
||
PROJECT_NAME="rust-backend"
|
||
REMOTE_USER="root"
|
||
REMOTE_HOST="aliyun-server"
|
||
APP_ENV="production"
|
||
|
||
DRY_RUN=false; SKIP_CONFIRM=false; SKIP_TESTS=false
|
||
ROLLBACK=false; LIST_BACKUPS=false; VIEW_LOGS=false; TAIL_LOGS=false
|
||
LOG_LINES=50; VIEW_STATUS=false; POST_DEPLOY_LOGS=false; INIT_ENV=false
|
||
DEPLOY_SERVICE=false; BACKUP_PATH=""
|
||
|
||
# ---------- 选项解析 ----------
|
||
BG_TARGET="" # blue 或 green(仅 production 有效)
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--dry-run) DRY_RUN=true ;;
|
||
--yes|-y) SKIP_CONFIRM=true ;;
|
||
--skip-tests) SKIP_TESTS=true ;;
|
||
--rollback) ROLLBACK=true ;;
|
||
--backup-list) LIST_BACKUPS=true ;;
|
||
--logs) VIEW_LOGS=true ;;
|
||
--tail) TAIL_LOGS=true ;;
|
||
--logs=*) VIEW_LOGS=true; LOG_LINES="${1#*=}" ;;
|
||
--tail=*) TAIL_LOGS=true; LOG_LINES="${1#*=}" ;;
|
||
--status) VIEW_STATUS=true ;;
|
||
--post-logs) POST_DEPLOY_LOGS=true ;;
|
||
--init-env) INIT_ENV=true ;;
|
||
--deploy-service) DEPLOY_SERVICE=true ;;
|
||
--target) BG_TARGET="${2:-}"; shift ;;
|
||
--remote-host) REMOTE_HOST="${2:-}"; shift ;;
|
||
--help|-h)
|
||
echo "用法: $0 [development|production] [options]"
|
||
echo ""
|
||
echo "选项:"
|
||
echo " --dry-run 预览模式"
|
||
echo " --yes, -y 跳过确认"
|
||
echo " --skip-tests 跳过部署后测试"
|
||
echo " --target blue|green 蓝绿部署目标"
|
||
echo " --remote-host IP 部署目标服务器(默认 aliyun-server)"
|
||
echo " --rollback 回滚到指定备份"
|
||
echo " --backup-list 列出可用备份"
|
||
echo " --logs [N] 查看后端日志(默认50行)"
|
||
echo " --tail [N] 实时跟踪日志"
|
||
echo " --status 查看服务状态"
|
||
echo " --post-logs 部署后显示日志"
|
||
echo " --init-env 初始化 systemd service 模板"
|
||
echo " --deploy-service 上传 systemd service 文件到服务器"
|
||
exit 0 ;;
|
||
*)
|
||
if [[ "$1" == "development" || "$1" == "production" ]]; then
|
||
APP_ENV="$1"
|
||
else
|
||
echo "未知选项: $1"; exit 1
|
||
fi ;;
|
||
esac; shift
|
||
done
|
||
|
||
# 提前建立 SSH 连接(蓝绿检测需要 remote())
|
||
ssh_connect
|
||
|
||
# ---------- 蓝绿目标自动检测 + 配置 ----------
|
||
# 优先级: 手动 --target > 自动检测
|
||
detect_blue_green() {
|
||
local proxy_conf; proxy_conf=$(get_proxy_conf)
|
||
local active
|
||
active=$(remote "sudo cat ${proxy_conf} 2>/dev/null" 2>/dev/null | grep -oP '127\.0\.0\.1:\d+' | head -1 || echo "")
|
||
|
||
case "${APP_ENV}:${active}" in
|
||
*:4433) echo "blue" ;;
|
||
*:4434) echo "green" ;;
|
||
*:8083) echo "blue" ;;
|
||
*:8084) echo "green" ;;
|
||
*) echo "" ;;
|
||
esac
|
||
}
|
||
|
||
if [ -z "$BG_TARGET" ] && [ "${APP_ENV}" = "production" ]; then
|
||
# 自动检测:部署到待命环境(仅生产环境支持蓝绿)
|
||
active_target=$(detect_blue_green)
|
||
if [ -n "$active_target" ]; then
|
||
BG_TARGET=$([ "$active_target" = "blue" ] && echo "green" || echo "blue")
|
||
log_info "自动检测: 当前活动 ${active_target},部署到 ${BG_TARGET}"
|
||
fi
|
||
fi
|
||
|
||
if [ -n "$BG_TARGET" ]; then
|
||
case "${APP_ENV}:${BG_TARGET}" in
|
||
production:blue) BG_PORT="4433"; BG_DIR="rust_backend_blue"; BG_SVC="rust-backend-blue.service" ;;
|
||
production:green) BG_PORT="4434"; BG_DIR="rust_backend_green"; BG_SVC="rust-backend-green.service" ;;
|
||
development:blue) BG_PORT="8083"; BG_DIR="rust_backend_dev_blue"; BG_SVC="rust-backend-dev-blue.service" ;;
|
||
development:green)BG_PORT="8084"; BG_DIR="rust_backend_dev_green";BG_SVC="rust-backend-dev-green.service" ;;
|
||
*) echo "错误: --target 只能是 blue 或 green"; exit 1 ;;
|
||
esac
|
||
fi
|
||
|
||
# ---------- 环境配置 ----------
|
||
case "${APP_ENV}" in
|
||
development)
|
||
if [ -n "$BG_TARGET" ]; then
|
||
REMOTE_DIR="/root/rust/${BG_DIR}"
|
||
SERVICE_NAME="${BG_SVC}"
|
||
BACKEND_PORT="${BG_PORT}"
|
||
else
|
||
REMOTE_DIR="/root/rust/rust_backend_dev"
|
||
SERVICE_NAME="rust-backend-dev.service"
|
||
BACKEND_PORT="8080"
|
||
fi
|
||
TEST_DOMAIN="https://dev.xmclassmate.top"
|
||
DB_CONTAINER="postgres"
|
||
DB_NAME="milkydata_dev"
|
||
DB_USER="milkydata" ;;
|
||
production)
|
||
if [ -n "$BG_TARGET" ]; then
|
||
REMOTE_DIR="/root/rust/${BG_DIR}"
|
||
SERVICE_NAME="${BG_SVC}"
|
||
BACKEND_PORT="${BG_PORT}"
|
||
else
|
||
REMOTE_DIR="/root/rust/rust_backend"
|
||
SERVICE_NAME="rust-backend.service"
|
||
BACKEND_PORT="4433"
|
||
fi
|
||
TEST_DOMAIN="https://xmclassmate.top"
|
||
DB_CONTAINER="postgres"
|
||
DB_NAME="milkydata"
|
||
DB_USER="milkydata" ;;
|
||
esac
|
||
|
||
# ---------- 快捷命令 ----------
|
||
GIT_VERSION=$(get_git_info)
|
||
|
||
if [ "$LIST_BACKUPS" = true ]; then list_backups; exit 0; fi
|
||
if [ "$INIT_ENV" = true ]; then init_env; exit 0; fi
|
||
if [ "$DEPLOY_SERVICE" = true ]; then deploy_service_file; exit 0; fi
|
||
if [ "$VIEW_LOGS" = true ]; then view_logs; exit 0; fi
|
||
if [ "$TAIL_LOGS" = true ]; then tail_logs; exit 0; fi
|
||
if [ "$VIEW_STATUS" = true ]; then status; exit 0; fi
|
||
if [ "$ROLLBACK" = true ]; then rollback; exit 0; fi
|
||
|
||
# ---------- 主部署流程 ----------
|
||
show_deploy_info
|
||
confirm_deploy
|
||
check_not_active
|
||
check_dependencies
|
||
check_service_file
|
||
check_ssl_expiry
|
||
|
||
build_project
|
||
backup_old_version
|
||
cleanup_old_backups 5
|
||
|
||
upload_binary
|
||
upload_dir "迁移文件" migrations
|
||
upload_script "测试脚本" test_deployment.sh test_deployment.sh
|
||
upload_script "清理脚本" scripts/cleanup_refresh_tokens.sh scripts/cleanup_refresh_tokens.sh
|
||
upload_script "备份脚本" scripts/backup-db.sh scripts/backup-db.sh
|
||
|
||
deploy_service_file
|
||
run_migrations # Moved BEFORE restart
|
||
restart_service
|
||
|
||
if run_tests; then
|
||
log_to_file "DEPLOY success"
|
||
send_webhook "success" "部署完成"
|
||
echo ""; log_info "========== 部署完成!=========="
|
||
echo -e " Git: ${GIT_VERSION}"; echo -e " 环境: ${APP_ENV}"
|
||
if [ -n "$BG_TARGET" ]; then
|
||
echo -e " 目标: ${BG_TARGET} (:${BG_PORT})"
|
||
echo -e ""
|
||
echo -e " ${YELLOW}自动切换代理...${NC}"
|
||
if bash "${SCRIPT_DIR}/scripts/switch-env.sh" --switch "${BG_TARGET}" 2>&1; then
|
||
log_info "代理已切换至 ${BG_TARGET} (:${BG_PORT})"
|
||
else
|
||
log_warn "代理切换失败,请手动执行: ./scripts/switch-env.sh --switch ${BG_TARGET}"
|
||
fi
|
||
fi
|
||
echo ""
|
||
[ "$POST_DEPLOY_LOGS" = true ] && { echo ""; view_logs; }
|
||
else
|
||
log_error "========== 部署失败,已自动回滚 =========="
|
||
exit 1
|
||
fi
|
||
|
||
exit 0
|