#!/bin/bash # ForensicPathways Deployment Script – *ownership-aware* + VISUAL ENHANCED # Usage: sudo ./deploy.sh set -e # ═══════════════════════════════════════════════════════════════════════════════ # 🎨 VISUAL ENHANCEMENT SYSTEM # ═══════════════════════════════════════════════════════════════════════════════ # Color palette declare -r RED='\033[0;31m' declare -r GREEN='\033[0;32m' declare -r YELLOW='\033[0;33m' declare -r BLUE='\033[0;34m' declare -r MAGENTA='\033[0;35m' declare -r CYAN='\033[0;36m' declare -r WHITE='\033[0;37m' declare -r BOLD='\033[1m' declare -r DIM='\033[2m' declare -r ITALIC='\033[3m' declare -r UNDERLINE='\033[4m' declare -r BLINK='\033[5m' declare -r REVERSE='\033[7m' declare -r RESET='\033[0m' # Gradient colors declare -r GRAD1='\033[38;5;196m' # Bright red declare -r GRAD2='\033[38;5;202m' # Orange declare -r GRAD3='\033[38;5;208m' # Dark orange declare -r GRAD4='\033[38;5;214m' # Yellow orange declare -r GRAD5='\033[38;5;220m' # Yellow declare -r GRAD6='\033[38;5;118m' # Light green declare -r GRAD7='\033[38;5;82m' # Green declare -r GRAD8='\033[38;5;51m' # Cyan declare -r GRAD9='\033[38;5;33m' # Blue declare -r GRAD10='\033[38;5;129m' # Purple # Background colors declare -r BG_RED='\033[41m' declare -r BG_GREEN='\033[42m' declare -r BG_YELLOW='\033[43m' declare -r BG_BLUE='\033[44m' declare -r BG_MAGENTA='\033[45m' declare -r BG_CYAN='\033[46m' # Unicode box drawing declare -r BOX_H='═' declare -r BOX_V='║' declare -r BOX_TL='╔' declare -r BOX_TR='╗' declare -r BOX_BL='╚' declare -r BOX_BR='╝' declare -r BOX_T='╦' declare -r BOX_B='╩' declare -r BOX_L='╠' declare -r BOX_R='╣' declare -r BOX_C='╬' # Fancy Unicode characters declare -r ARROW_R='▶' declare -r ARROW_D='▼' declare -r DIAMOND='◆' declare -r STAR='★' declare -r BULLET='●' declare -r CIRCLE='◯' declare -r SQUARE='▪' declare -r TRIANGLE='▲' # Animation frames SPINNER_FRAMES=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏') PULSE_FRAMES=('●' '◐' '◑' '◒' '◓' '◔' '◕' '◖' '◗' '◘') WAVE_FRAMES=('▁' '▂' '▃' '▄' '▅' '▆' '▇' '█' '▇' '▆' '▅' '▄' '▃' '▂') # Terminal dimensions COLS=$(tput cols 2>/dev/null || echo 80) LINES=$(tput lines 2>/dev/null || echo 24) # ═══════════════════════════════════════════════════════════════════════════════ # 🎯 VISUAL FUNCTIONS # ═══════════════════════════════════════════════════════════════════════════════ print_gradient_text() { local text="$1" local colors=("$GRAD1" "$GRAD2" "$GRAD3" "$GRAD4" "$GRAD5" "$GRAD6" "$GRAD7" "$GRAD8" "$GRAD9" "$GRAD10") local length=${#text} local color_count=${#colors[@]} for ((i=0; i/dev/null; do printf "\r${CYAN}${SPINNER_FRAMES[$frame]}${RESET} ${message}" frame=$(((frame + 1) % ${#SPINNER_FRAMES[@]})) sleep 0.1 done printf "\r${GREEN}✓${RESET} ${message}\n" } pulsing_dots() { local count="${1:-5}" local cycles="${2:-3}" for ((c=0; c 80 ? 80 : COLS-4)) local title_padding=$(((box_width-title_len)/2)) local subtitle_padding=$(((box_width-subtitle_len)/2)) echo # Top gradient border printf "${BOLD}" for ((i=0; i0; i--)); do printf "\r${YELLOW}${BOLD}⏳ $message in ${i}s...${RESET}" sleep 1 done printf "\r${GREEN}${BOLD}🚀 $message${RESET} \n" } matrix_rain() { local duration="${1:-2}" local chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%^&*()_+-=[]{}|;:,.<>?" for ((i=0; i/dev/null; then status_ok "System npm located: $(which npm)" printf "${MAGENTA}${BOLD}📦 Installing dependencies${RESET}" { sudo -u "$ORIGINAL_USER" npm install > /tmp/npm_install.log 2>&1 & spinner $! "Installing dependencies" } printf "${MAGENTA}${BOLD}🏗️ Building application${RESET}" { sudo -u "$ORIGINAL_USER" npm run build > /tmp/npm_build.log 2>&1 & spinner $! "Building application" } return 0 fi # B) nvm-managed npm printf "${YELLOW}🔍 Scanning for nvm installation...${RESET}\n" if sudo -u "$ORIGINAL_USER" bash -c " export NVM_DIR='$ORIGINAL_HOME/.nvm' [ -s \"\$NVM_DIR/nvm.sh\" ] && source \"\$NVM_DIR/nvm.sh\" [ -s '$ORIGINAL_HOME/.bashrc' ] && source '$ORIGINAL_HOME/.bashrc' command -v npm &>/dev/null "; then status_ok "NVM-managed npm located" printf "${MAGENTA}${BOLD}📦 Installing dependencies with nvm${RESET}" { sudo -u "$ORIGINAL_USER" bash -c " export NVM_DIR='$ORIGINAL_HOME/.nvm' [ -s \"\$NVM_DIR/nvm.sh\" ] && source \"\$NVM_DIR/nvm.sh\" [ -s '$ORIGINAL_HOME/.bashrc' ] && source '$ORIGINAL_HOME/.bashrc' npm install > /tmp/npm_install.log 2>&1 npm run build > /tmp/npm_build.log 2>&1 " & spinner $! "Building with nvm" } return 0 fi # C) Installation instructions with fancy formatting draw_box "NPM NOT FOUND" "$(cat << 'EOF' Please install Node.js and npm first: Option 1 (apt): sudo apt update && sudo apt install nodejs npm Option 2 (NodeSource – recommended): curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt-get install -y nodejs Option 3 (nvm – as user): curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash source ~/.bashrc && nvm install 20 EOF)" 70 "$RED" return 1 } # ═══════════════════════════════════════════════════════════════════════════════ # 🏗️ PHASE 2: BUILD ORCHESTRATION # ═══════════════════════════════════════════════════════════════════════════════ section_header "2" "BUILD ORCHESTRATION" "🏗️" if [ ! -d "dist" ] || [ ! "$(ls -A dist 2>/dev/null)" ]; then status_info "No dist/ directory found" typewriter "Initiating build process..." 0.05 "$YELLOW" find_and_use_npm || exit 1 else status_ok "Existing dist/ directory detected" echo printf "${YELLOW}${BOLD}🤔 Rebuild application? ${RESET}${DIM}(y/N):${RESET} " read -r REPLY echo if [[ $REPLY =~ ^[Yy]$ ]]; then typewriter "Rebuilding application..." 0.05 "$CYAN" find_and_use_npm || { status_warning "Build failed, using existing dist/" } else typewriter "Using existing build..." 0.05 "$GREEN" fi fi # Build validation with dramatic effect printf "${CYAN}${BOLD}🔍 Validating build output${RESET}" pulsing_dots 8 2 if [ ! -d "dist" ] || [ ! "$(ls -A dist 2>/dev/null)" ]; then echo draw_box "BUILD FAILURE" "Build failed or dist/ directory is empty" 50 "$RED" exit 1 fi # Build success celebration echo printf "${GREEN}${BOLD}${BG_GREEN}${WHITE} BUILD SUCCESS ${RESET}\n" celebrate # ═══════════════════════════════════════════════════════════════════════════════ # 📁 PHASE 3: INFRASTRUCTURE SETUP # ═══════════════════════════════════════════════════════════════════════════════ section_header "3" "INFRASTRUCTURE PROVISIONING" "📁" status_working "Creating directory structure" { mkdir -p "$WEBROOT" "$LOG_DIR" "$DATA_DIR" "$UPLOADS_DIR" "$WEBROOT/src/data" & spinner $! "Provisioning directories" } # Directory creation progress DIRS=("$WEBROOT" "$LOG_DIR" "$DATA_DIR" "$UPLOADS_DIR" "$WEBROOT/src/data") for i in "${!DIRS[@]}"; do progress_bar $((i+1)) ${#DIRS[@]} 40 "Creating directories" sleep 0.1 done echo status_ok "Directory infrastructure ready" # ═══════════════════════════════════════════════════════════════════════════════ # 🚀 PHASE 4: APPLICATION DEPLOYMENT # ═══════════════════════════════════════════════════════════════════════════════ section_header "4" "APPLICATION DEPLOYMENT" "🚀" # File copy with visual progress status_working "Deploying application files" TOTAL_FILES=$(find dist -type f | wc -l) COPIED=0 { cp -r dist/. "$WEBROOT/" & PID=$! while kill -0 $PID 2>/dev/null; do CURRENT_FILES=$(find "$WEBROOT" -type f 2>/dev/null | wc -l) if [ $CURRENT_FILES -gt $COPIED ]; then COPIED=$CURRENT_FILES progress_bar $COPIED $TOTAL_FILES 50 "Copying files" fi sleep 0.1 done wait $PID progress_bar $TOTAL_FILES $TOTAL_FILES 50 "Copying files" } echo SIZE=$(du -sh dist | cut -f1) status_ok "Application deployed ($SIZE, $TOTAL_FILES files)" # Package.json copy with flair printf "${MAGENTA}${BOLD}📋 Deploying package.json${RESET}" pulsing_dots 3 1 cp package.json "$WEBROOT/" status_ok "Package configuration deployed" # ═══════════════════════════════════════════════════════════════════════════════ # ⚙️ PHASE 5: RUNTIME DEPENDENCY MANAGEMENT # ═══════════════════════════════════════════════════════════════════════════════ section_header "5" "RUNTIME DEPENDENCY RESOLUTION" "⚙️" typewriter "Transferring ownership for dependency installation..." 0.03 "$YELLOW" chown -R "$ORIGINAL_USER":"$ORIGINAL_USER" "$WEBROOT" printf "${CYAN}${BOLD}📦 Installing runtime dependencies${RESET}\n" { sudo -u "$ORIGINAL_USER" bash -c ' set -e cd "'"$WEBROOT"'" if command -v npm &>/dev/null; then npm install --production > /tmp/runtime_deps.log 2>&1 else export NVM_DIR="'$ORIGINAL_HOME'/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh" [ -s "'$ORIGINAL_HOME'/.bashrc" ] && source "'$ORIGINAL_HOME'/.bashrc" npm install --production > /tmp/runtime_deps.log 2>&1 fi ' & spinner $! "Installing runtime dependencies" } # Dependency success effect printf "${GREEN}${BOLD}🎯 Dependencies locked and loaded!${RESET}\n" wave_animation 40 1 # ═══════════════════════════════════════════════════════════════════════════════ # 🗃️ PHASE 6: DATA & CONTENT ORCHESTRATION # ═══════════════════════════════════════════════════════════════════════════════ section_header "6" "DATA & CONTENT ORCHESTRATION" "🗃️" status_working "Deploying core data structures" if [ -f "src/data/tools.yaml" ]; then cp src/data/tools.yaml "$WEBROOT/src/data/" TOOL_COUNT=$(grep -c "^ - name:" "src/data/tools.yaml" || echo "unknown") status_ok "Tools database deployed ($TOOL_COUNT tools)" else status_error "Critical file missing: src/data/tools.yaml" exit 1 fi status_working "Deploying knowledge base" if [ -d "src/content/knowledgebase" ]; then mkdir -p "$WEBROOT/src/content" cp -r src/content/knowledgebase "$WEBROOT/src/content/" KB_COUNT=$(find src/content/knowledgebase -name "*.md" 2>/dev/null | wc -l) status_ok "Knowledge base deployed ($KB_COUNT articles)" # Knowledge base visualization printf "${BLUE}${BOLD}📚 Knowledge Base Structure:${RESET}\n" find src/content/knowledgebase -name "*.md" | head -5 | while read -r file; do printf " ${CYAN}${DIAMOND}${RESET} ${file#src/content/knowledgebase/}\n" done if [ $KB_COUNT -gt 5 ]; then printf " ${DIM}... and $((KB_COUNT-5)) more articles${RESET}\n" fi else status_warning "No knowledge base directory found (optional)" fi # ═══════════════════════════════════════════════════════════════════════════════ # ⚙️ PHASE 7: ENVIRONMENT CONFIGURATION # ═══════════════════════════════════════════════════════════════════════════════ section_header "7" "ENVIRONMENT CONFIGURATION" "⚙️" printf "${YELLOW}${BOLD}🔧 Configuring environment${RESET}" pulsing_dots 5 1 cp .env.example "$WEBROOT/.env" status_ok "Environment template deployed" draw_box "CONFIGURATION NOTICE" "IMPORTANT: Edit $WEBROOT/.env with your configuration" 60 "$YELLOW" # ═══════════════════════════════════════════════════════════════════════════════ # 📝 PHASE 8: LOGGING INFRASTRUCTURE # ═══════════════════════════════════════════════════════════════════════════════ section_header "8" "LOGGING INFRASTRUCTURE" "📝" LOG_FILES=("access.log" "error.log" "ai-pipeline.log") for i in "${!LOG_FILES[@]}"; do progress_bar $((i+1)) ${#LOG_FILES[@]} 30 "Creating log files" touch "$LOG_DIR/${LOG_FILES[$i]}" sleep 0.2 done echo status_ok "Logging infrastructure established" # ═══════════════════════════════════════════════════════════════════════════════ # 🔐 PHASE 9: PERMISSION MATRIX # ═══════════════════════════════════════════════════════════════════════════════ section_header "9" "PERMISSION MATRIX CONFIGURATION" "🔐" typewriter "Implementing security hardening..." 0.04 "$RED" # Permission operations with progress PERM_OPERATIONS=( "chown -R www-data:www-data $WEBROOT" "chmod -R 755 $WEBROOT" "chmod 600 $WEBROOT/.env" "chmod 755 $DATA_DIR $UPLOADS_DIR $LOG_DIR" "chmod 644 $LOG_DIR/*.log" ) for i in "${!PERM_OPERATIONS[@]}"; do progress_bar $((i+1)) ${#PERM_OPERATIONS[@]} 45 "Setting permissions" eval "${PERM_OPERATIONS[$i]}" sleep 0.3 done echo if [ -f "$WEBROOT/server/entry.mjs" ]; then chmod 755 "$WEBROOT/server/entry.mjs" status_ok "Server entry point permissions configured" fi status_ok "Permission matrix locked down" # ═══════════════════════════════════════════════════════════════════════════════ # ✅ PHASE 10: DEPLOYMENT VALIDATION # ═══════════════════════════════════════════════════════════════════════════════ section_header "10" "DEPLOYMENT VALIDATION MATRIX" "✅" VALIDATION_ERRORS=0 VALIDATIONS=( "$WEBROOT/.env|Environment configuration" "$WEBROOT/src/data/tools.yaml|Tools database" ) # Check application files if [ -f "$WEBROOT/index.html" ] || [ -d "$WEBROOT/server" ]; then VALIDATIONS+=("$WEBROOT/index.html|Application files") fi echo printf "${CYAN}${BOLD}🔍 Running comprehensive validation suite...${RESET}\n" for validation in "${VALIDATIONS[@]}"; do IFS='|' read -r file desc <<< "$validation" printf "${YELLOW}Testing: $desc${RESET}" pulsing_dots 3 1 if [ -f "$file" ] || [ -d "$file" ]; then status_ok "$desc validated" else status_error "$desc missing" ((VALIDATION_ERRORS++)) fi done # ═══════════════════════════════════════════════════════════════════════════════ # 🎊 FINAL RESULTS SPECTACULAR # ═══════════════════════════════════════════════════════════════════════════════ echo if [ $VALIDATION_ERRORS -eq 0 ]; then # Success celebration sequence printf "${GREEN}${BOLD}${BG_GREEN}${WHITE}" for ((i=0; i