#!/usr/bin/env bash # OMNIS Deployment Script for Proxmox # Deploys OMNIS application to Proxmox containers/VMs # Usage: ./scripts/deploy-omnis.sh [environment] [vmid] [host] set -euo pipefail # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Load shared modules if available SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" source "$SCRIPT_DIR/lib/logging.sh" 2>/dev/null || true source "$SCRIPT_DIR/lib/ssh-helpers.sh" 2>/dev/null || true # Default values ENVIRONMENT="${1:-production}" VMID="${2:-}" PROXMOX_HOST="${3:-${PROXMOX_HOST_ML110:-192.168.11.10}}" PROXMOX_USER="${PROXMOX_USER:-root}" OMNIS_DIR="${OMNIS_DIR:-$PROJECT_ROOT/OMNIS}" REMOTE_OMNIS_DIR="${REMOTE_OMNIS_DIR:-/opt/omnis}" # Logging functions (if not loaded) log_info() { echo -e "${BLUE}ℹ${NC} $*"; } log_success() { echo -e "${GREEN}✅${NC} $*"; } log_warning() { echo -e "${YELLOW}⚠️${NC} $*"; } log_error() { echo -e "${RED}❌${NC} $*"; } log_header() { echo -e "\n${BLUE}========================================${NC}"; echo -e "${BLUE}$*${NC}"; echo -e "${BLUE}========================================${NC}\n"; } show_usage() { cat < /dev/null; then log_error "Node.js not found. Please install Node.js 18+" exit 1 fi NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) if [ "$NODE_VERSION" -lt 18 ]; then log_error "Node.js version must be 18+. Current: $(node -v)" exit 1 fi log_success "Node.js $(node -v) found" # Check pnpm if ! command -v pnpm &> /dev/null; then log_warning "pnpm not found. Installing..." npm install -g pnpm || { log_error "Failed to install pnpm" exit 1 } fi log_success "pnpm $(pnpm -v) found" # Check if deploying to Proxmox if [ "$DEPLOY_LOCAL" != "true" ]; then # Check SSH connection if ! ssh -o BatchMode=yes -o ConnectTimeout=5 "$PROXMOX_USER@$PROXMOX_HOST" exit 2>/dev/null; then log_error "Cannot connect to Proxmox host: $PROXMOX_HOST" log_info "Please ensure SSH key is set up for passwordless access" exit 1 fi log_success "SSH connection to $PROXMOX_HOST successful" fi } # Validate configuration validate_config() { log_info "Validating configuration..." cd "$OMNIS_DIR" if [ -f "scripts/validate-config.sh" ]; then if ./scripts/validate-config.sh; then log_success "Configuration validation passed" else log_error "Configuration validation failed" exit 1 fi else log_warning "Configuration validation script not found, skipping..." fi } # Build application build_application() { if [ "$SKIP_BUILD" = "true" ]; then log_warning "Skipping build (--skip-build)" return fi log_info "Building application..." cd "$OMNIS_DIR" # Install dependencies log_info "Installing dependencies..." pnpm install --frozen-lockfile cd backend pnpm install --frozen-lockfile cd .. # Build frontend log_info "Building frontend..." pnpm build || { log_error "Frontend build failed" exit 1 } # Build backend log_info "Building backend..." cd backend pnpm build || { log_error "Backend build failed" exit 1 } cd .. log_success "Application built successfully" } # Run tests run_tests() { if [ "$SKIP_TESTS" = "true" ]; then log_warning "Skipping tests (--skip-tests)" return fi log_info "Running tests..." cd "$OMNIS_DIR" # Type checking log_info "Type checking..." pnpm type-check || log_warning "Type check had warnings" cd backend pnpm type-check || log_warning "Backend type check had warnings" cd .. # Linting log_info "Linting..." pnpm run lint 2>/dev/null || log_warning "Linting had warnings" # Unit tests log_info "Running unit tests..." pnpm test:run 2>/dev/null || log_warning "Some tests failed" log_success "Tests completed" } # Deploy to Proxmox container deploy_to_container() { local vmid="$1" log_info "Deploying to Proxmox container VMID $vmid..." # Create remote directory ssh "$PROXMOX_USER@$PROXMOX_HOST" "mkdir -p $REMOTE_OMNIS_DIR" # Copy built files log_info "Copying application files..." scp -r "$OMNIS_DIR/dist" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/" || { log_error "Failed to copy frontend files" exit 1 } scp -r "$OMNIS_DIR/backend/dist" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/backend/" || { log_error "Failed to copy backend files" exit 1 } # Copy configuration files log_info "Copying configuration files..." ssh "$PROXMOX_USER@$PROXMOX_HOST" "mkdir -p $REMOTE_OMNIS_DIR/backend" scp "$OMNIS_DIR/backend/.env" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/backend/.env" 2>/dev/null || { log_warning "Backend .env not found, you may need to configure it manually" } # Copy deployment scripts log_info "Copying deployment scripts..." scp -r "$OMNIS_DIR/scripts" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/" 2>/dev/null || true # Install in container log_info "Installing in container VMID $vmid..." ssh "$PROXMOX_USER@$PROXMOX_HOST" "pct push $vmid $REMOTE_OMNIS_DIR /opt/omnis" || { log_error "Failed to push files to container" exit 1 } # Run setup in container log_info "Running setup in container..." ssh "$PROXMOX_USER@$PROXMOX_HOST" "pct exec $vmid -- bash -c 'cd /opt/omnis/backend && pnpm install --prod && pnpm migrate'" || { log_warning "Setup in container had issues" } log_success "Deployed to container VMID $vmid" } # Deploy to Proxmox host deploy_to_host() { log_info "Deploying to Proxmox host..." # Create remote directory ssh "$PROXMOX_USER@$PROXMOX_HOST" "mkdir -p $REMOTE_OMNIS_DIR/{backend,logs,uploads}" # Copy built files log_info "Copying application files..." scp -r "$OMNIS_DIR/dist" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/" || { log_error "Failed to copy frontend files" exit 1 } scp -r "$OMNIS_DIR/backend/dist" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/backend/" || { log_error "Failed to copy backend files" exit 1 } # Copy configuration log_info "Copying configuration files..." scp "$OMNIS_DIR/backend/.env" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/backend/.env" 2>/dev/null || { log_warning "Backend .env not found" } # Copy package files scp "$OMNIS_DIR/backend/package.json" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/backend/" 2>/dev/null || true scp "$OMNIS_DIR/backend/pnpm-lock.yaml" "$PROXMOX_USER@$PROXMOX_HOST:$REMOTE_OMNIS_DIR/backend/" 2>/dev/null || true # Install dependencies on remote host log_info "Installing dependencies on remote host..." ssh "$PROXMOX_USER@$PROXMOX_HOST" "cd $REMOTE_OMNIS_DIR/backend && pnpm install --prod --frozen-lockfile" || { log_warning "Dependency installation had issues" } # Run migrations if [ "$ENVIRONMENT" = "production" ] || [ "$ENVIRONMENT" = "staging" ]; then log_info "Running database migrations..." ssh "$PROXMOX_USER@$PROXMOX_HOST" "cd $REMOTE_OMNIS_DIR/backend && pnpm migrate" || { log_warning "Migrations had issues" } fi log_success "Deployed to Proxmox host at $REMOTE_OMNIS_DIR" } # Deploy locally deploy_local() { log_info "Deploying locally..." cd "$OMNIS_DIR" # Run migrations if needed if [ "$ENVIRONMENT" = "production" ] || [ "$ENVIRONMENT" = "staging" ]; then log_info "Running database migrations..." cd backend pnpm migrate || log_warning "Migrations had issues" cd .. fi log_success "Local deployment ready" log_info "Start backend: cd backend && pnpm start" log_info "Start frontend: pnpm preview" } # Main deployment function main() { # Parse arguments SKIP_TESTS="false" SKIP_BUILD="false" DEPLOY_LOCAL="false" while [[ $# -gt 0 ]]; do case $1 in --skip-tests) SKIP_TESTS="true" shift ;; --skip-build) SKIP_BUILD="true" shift ;; --local) DEPLOY_LOCAL="true" shift ;; --help|-h) show_usage exit 0 ;; *) shift ;; esac done log_header "OMNIS Deployment - $ENVIRONMENT" # Check prerequisites check_prerequisites # Validate configuration validate_config # Build application build_application # Run tests run_tests # Deploy if [ "$DEPLOY_LOCAL" = "true" ]; then deploy_local elif [ -n "$VMID" ]; then deploy_to_container "$VMID" else deploy_to_host fi log_header "Deployment Complete" log_success "OMNIS deployed successfully to $ENVIRONMENT" if [ "$DEPLOY_LOCAL" != "true" ]; then log_info "Remote location: $REMOTE_OMNIS_DIR" log_info "Start backend: ssh $PROXMOX_USER@$PROXMOX_HOST 'cd $REMOTE_OMNIS_DIR/backend && pnpm start'" fi } main "$@"