deploy.sh 5.81 KB
#!/bin/bash
# ============================================================================
# H5 项目多环境部署脚本
# ============================================================================
#
# 说明:支持一次部署到一个或多个环境
# 使用方法:./deploy.sh <env1> [env2] [env3] ...
#
# 示例:
#   ./deploy.sh dev              # 部署到开发环境
#   ./deploy.sh test prod           # 部署到测试和生产环境
#   ./deploy.sh dev test prod       # 部署到开发、测试和生产环境
#
# ============================================================================

set -e  # 遇到错误立即退出

# 获取脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"

# 加载配置文件
source "${SCRIPT_DIR}/config.sh"

# ============================================================================
# 辅助函数
# ============================================================================

# 显示分隔线
print_separator() {
    echo "================================================================================"
}

# 检查必需的命令
check_commands() {
    local required_cmds=("pnpm" "ssh" "scp" "tar" "rm")
    for cmd in "${required_cmds[@]}"; do
        if ! command -v "$cmd" &> /dev/null; then
            log_error "缺少必需命令: $cmd"
            log_info "请先安装缺失的工具"
            exit 1
        fi
    done
}

# 检查本地构建产物
check_build() {
    if [ ! -d "$BUILD_DIR" ]; then
        log_error "构建目录不存在: $BUILD_DIR"
        log_info "请先运行: $BUILD_COMMAND"
        exit 1
    fi
}

# 执行构建
do_build() {
    log_info "开始构建项目..."
    cd "$PROJECT_DIR"
    $BUILD_COMMAND

    if [ $? -ne 0 ]; then
        log_error "构建失败"
        exit 1
    fi

    log_success "构建完成"
    cd "$SCRIPT_DIR"
}

# 创建归档
create_archive() {
    local archive_name="$BUILD_ARCHIVE"

    log_info "创建部署归档: $archive_name"
    cd "$PROJECT_DIR"

    tar -czf "$archive_name" "$BUILD_DIR"

    if [ $? -ne 0 ]; then
        log_error "创建归档失败"
        exit 1
    fi

    log_success "归档创建完成: $archive_name"
    cd "$SCRIPT_DIR"
}

# 上传归档
upload_archive() {
    local archive_name="$1"

    log_info "上传归档到服务器..."

    scp -P "$SERVER_PORT" "$archive_name" \
        "${SERVER_USER}@${SERVER_HOST}:/tmp/"

    if [ $? -ne 0 ]; then
        log_error "上传失败"
        exit 1
    fi

    log_success "归档上传完成"
}

# 执行远程部署
do_deploy() {
    local archive_name="$1"
    local remote_archive_path="/tmp/${archive_name}"
    local remote_deploy_dir="$REMOTE_DEPLOY_DIR"

    log_info "开始远程部署..."

    ssh -p "$SERVER_PORT" "${SERVER_USER}@${SERVER_HOST}" << EOF
set -e

# 进入部署目录
cd "\$remote_deploy_dir" || mkdir -p "\$remote_deploy_dir"

# 备份当前版本(如果启用)
if [ "\$BACKUP_ENABLED" = "true" ]; then
    echo "[INFO] 备份当前版本..."
    if [ -d "\$remote_deploy_dir" ]; then
        # 查找现有的备份目录
        BACKUP_DIR="\${remote_deploy_dir}_backup_\$(date +%Y%m%d_%H%M%S)"
        mkdir -p "\$BACKUP_DIR"
        # 备份当前版本
        cp -r "\$remote_deploy_dir/"* "\$BACKUP_DIR/" 2>/dev/null || true
        echo "[SUCCESS] 备份完成: \$BACKUP_DIR"

        # 清理旧备份(保留指定数量)
        if [ "\$BACKUP_MAX_COUNT" -gt 0 ]; then
            echo "[INFO] 清理旧备份(保留 \$BACKUP_MAX_COUNT 个)..."
            ls -td "\${remote_deploy_dir}_backup_" | sort -r | tail -n +\`"\$BACKUP_MAX_COUNT\" | xargs rm -rf
        fi
    fi
fi

# 解压新版本
echo "[INFO] 解压新版本..."
tar -xzf "\$remote_archive_path" -C "\$remote_deploy_dir"

# 清理归档文件
rm -f "\$remote_archive_path"

echo "[SUCCESS] 部署完成"
EOF

    if [ $? -ne 0 ]; then
        log_error "远程部署失败"
        exit 1
    fi

    log_success "远程部署完成"
}

# 部署到单个环境
deploy_to_env() {
    local env_name="$1"

    log_info "=========================================="
    log_info "开始部署到环境: $env_name"
    log_info "=========================================="

    # 加载环境配置
    load_env_config "$env_name"

    # 执行构建
    do_build

    # 创建归档
    create_archive "$BUILD_ARCHIVE"

    # 上传归档
    upload_archive "$BUILD_ARCHIVE"

    # 执行远程部署
    do_deploy "$BUILD_ARCHIVE"

    log_success "环境 [$env_name] 部署完成"
}

# ============================================================================
# 主流程
# ============================================================================

# 检查命令
check_commands

# 检查是否提供了环境参数
if [ $# -eq 0 ]; then
    log_error "使用方法: $0 <env1> [env2] [env3] ..."
    log_info "可用环境: dev, oa, behalo"
    exit 1
fi

# 显示将要部署的环境
log_info "将要部署到以下环境:"
for env in "$@"; do
    echo "  - $env"
done
print_separator

# 确认部署
read -p "确认部署以上环境?(y/N): " confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
    log_warning "已取消部署"
    exit 0
fi

print_separator

# 逐个部署环境
for env in "$@"; do
    deploy_to_env "$env"
    print_separator
done

# 最终总结
log_success "所有环境部署完成!"
print_separator
log_info "部署摘要:"
for env in "$@"; do
    echo "  ✓ $env"
done
print_separator

log_info "访问地址:"
for env in "$@"; do
    case "$env" in
        dev)
            echo "  - 开发环境: http://oa-dev.onwall.cn"
            ;;
        oa)
            echo "  - OA环境: http://oa.onwall.cn"
            ;;
        behalo)
            echo "  - Behalo环境: http://behalo.onwall.cn"
            ;;
    esac
done
print_separator

log_success "部署流程全部结束!"