391 lines
12 KiB
Bash
Executable File
391 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ClassroomCopilot Startup Script
|
|
# Usage: ./start.sh [start_mode]
|
|
# start_mode options: infra, seed, seed-test, gais-data, full, dev, prod
|
|
|
|
set -e
|
|
|
|
# Function to show help
|
|
show_help() {
|
|
echo "ClassroomCopilot Startup Script"
|
|
echo ""
|
|
echo "Usage: ./start.sh [start_mode] [--yes]"
|
|
echo ""
|
|
echo "Start modes:"
|
|
echo " infra - Setup infrastructure (Neo4j schema, calendar, Supabase buckets)"
|
|
echo " seed - Seed canonical full environment (20 school users)"
|
|
echo " seed-test - Seed lightweight test environment (9 school users)"
|
|
echo " gais-data - Import GAIS data (Edubase, etc.)"
|
|
echo " full - Run full initialization (infra → seed)"
|
|
echo " nuke - 💥 NUKE Redis - Clear all queue data for fresh start"
|
|
echo " dev - Run development server with auto-reload"
|
|
echo " prod - Run production server (for Docker/containerized deployment)"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " ./start.sh # Run in dev mode (default)"
|
|
echo " ./start.sh infra # Setup infrastructure"
|
|
echo " ./start.sh seed # Seed canonical full environment"
|
|
echo " ./start.sh seed-test # Seed lightweight test environment"
|
|
echo " ./start.sh gais-data # Import GAIS data"
|
|
echo " ./start.sh full # Run full initialization"
|
|
echo " ./start.sh full --yes # Run full initialization without prompts"
|
|
echo " ./start.sh nuke # 💥 NUKE Redis completely"
|
|
echo " ./start.sh dev # Run development server"
|
|
echo " ./start.sh prod # Run production server"
|
|
echo ""
|
|
echo "For more information, see README_STARTUP.md"
|
|
}
|
|
|
|
# Check for help flag
|
|
if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "help" ]]; then
|
|
show_help
|
|
exit 0
|
|
fi
|
|
|
|
# Default to dev mode if no argument provided
|
|
START_MODE=${1:-dev}
|
|
|
|
# Non-interactive flag
|
|
AUTO_YES=false
|
|
if [[ "$2" == "--yes" || "$2" == "-y" ]]; then
|
|
AUTO_YES=true
|
|
fi
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Function to print colored output
|
|
print_status() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# Function to check if Python is available
|
|
check_python() {
|
|
if command -v python3 &> /dev/null; then
|
|
PYTHON_CMD="python3"
|
|
elif command -v python &> /dev/null; then
|
|
PYTHON_CMD="python"
|
|
else
|
|
print_error "Python is not installed or not in PATH"
|
|
exit 1
|
|
fi
|
|
print_status "Using Python: $PYTHON_CMD"
|
|
}
|
|
|
|
# Function to check if virtual environment is activated
|
|
check_venv() {
|
|
if [[ "$VIRTUAL_ENV" == "" ]]; then
|
|
print_warning "No virtual environment detected. Consider activating one for production use."
|
|
else
|
|
print_status "Virtual environment activated: $VIRTUAL_ENV"
|
|
fi
|
|
}
|
|
|
|
# Function to check environment variables
|
|
check_env() {
|
|
if [[ ! -f ".env" ]]; then
|
|
print_warning ".env file not found. Make sure environment variables are set."
|
|
else
|
|
print_status ".env file found"
|
|
fi
|
|
}
|
|
|
|
# Function to run infrastructure setup
|
|
run_infra() {
|
|
print_status "Running infrastructure setup mode..."
|
|
print_status "This will set up Neo4j schema, calendar structure, and Supabase buckets."
|
|
|
|
# Check if we should proceed
|
|
if [[ "$AUTO_YES" != true ]]; then
|
|
read -p "Do you want to continue with infrastructure setup? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
print_status "Infrastructure setup cancelled."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
print_status "Starting infrastructure setup process..."
|
|
$PYTHON_CMD main.py --mode infra
|
|
|
|
if [ $? -eq 0 ]; then
|
|
print_success "Infrastructure setup completed successfully!"
|
|
else
|
|
print_error "Infrastructure setup failed!"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to run canonical environment seed
|
|
run_seed() {
|
|
local mode=${1:-seed}
|
|
if [[ "$mode" == "seed-test" ]]; then
|
|
print_status "Running lightweight seed-test mode (9 school users)..."
|
|
else
|
|
print_status "Running canonical seed mode (20 school users)..."
|
|
fi
|
|
|
|
# Check if we should proceed
|
|
if [[ "$AUTO_YES" != true ]]; then
|
|
read -p "Do you want to continue with $mode? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
print_status "$mode cancelled."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
print_status "Starting $mode process..."
|
|
$PYTHON_CMD main.py --mode "$mode"
|
|
|
|
if [ $? -eq 0 ]; then
|
|
print_success "$mode completed successfully!"
|
|
else
|
|
print_error "$mode failed!"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to run GAIS data import
|
|
run_gais_data() {
|
|
print_status "Running GAIS data import mode..."
|
|
print_status "This will import publicly available school databases (Edubase, etc.) into Neo4j."
|
|
|
|
# Check if we should proceed
|
|
if [[ "$AUTO_YES" != true ]]; then
|
|
read -p "Do you want to continue with GAIS data import? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
print_status "GAIS data import cancelled."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
print_status "Starting GAIS data import process..."
|
|
$PYTHON_CMD main.py --mode gais-data
|
|
|
|
if [ $? -eq 0 ]; then
|
|
print_success "GAIS data import completed successfully!"
|
|
else
|
|
print_error "GAIS data import failed!"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to nuke Redis - clear all queue data
|
|
run_nuke() {
|
|
print_status "💥 NUKING Redis - Clear all queue data for fresh start..."
|
|
print_warning "This will DELETE ALL Redis data including queues, tasks, and metrics."
|
|
|
|
# Check if we should proceed
|
|
if [[ "$AUTO_YES" != true ]]; then
|
|
read -p "Are you SURE you want to nuke Redis? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
print_status "Redis nuke cancelled."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
print_status "Nuking Redis..."
|
|
|
|
# Kill any running servers first
|
|
print_status "Stopping any running API servers..."
|
|
pkill -f "python.*main\.py" 2>/dev/null || true
|
|
pkill -f "uvicorn" 2>/dev/null || true
|
|
sleep 2
|
|
|
|
# Clear Redis using new manager
|
|
$PYTHON_CMD -c "
|
|
from modules.redis_manager import get_redis_manager
|
|
import redis, os
|
|
|
|
try:
|
|
# Nuke all environments
|
|
total_cleared = 0
|
|
for env in ['dev', 'prod', 'test']:
|
|
try:
|
|
manager = get_redis_manager(env)
|
|
if manager.ensure_service_running() and manager.connect():
|
|
all_keys = manager.client.keys('*')
|
|
if all_keys:
|
|
manager.client.flushdb()
|
|
total_cleared += len(all_keys)
|
|
print(f'💥 NUKED {env.upper()}: Cleared {len(all_keys)} keys (db={manager.config.db})')
|
|
else:
|
|
print(f'✅ {env.upper()}: Already empty (db={manager.config.db})')
|
|
manager.client.close()
|
|
except Exception as e:
|
|
print(f'⚠️ Warning: Could not clear {env} environment: {e}')
|
|
|
|
print(f'💥 TOTAL NUKED: {total_cleared} keys across all environments')
|
|
print('🧹 Redis completely reset - ready for clean start!')
|
|
except Exception as e:
|
|
print(f'❌ Failed to connect to Redis: {e}')
|
|
exit(1)
|
|
"
|
|
|
|
if [ $? -eq 0 ]; then
|
|
print_success "💥 Redis NUKED successfully! Fresh slate ready."
|
|
else
|
|
print_error "Redis nuke failed!"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to run full initialization (all steps in order)
|
|
run_full() {
|
|
print_status "Running full initialization (infra → seed)..."
|
|
|
|
# Single confirmation for the whole flow
|
|
if [[ "$AUTO_YES" != true ]]; then
|
|
read -p "Do you want to run the full initialization? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
print_status "Full initialization cancelled."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Run infra
|
|
run_infra || { print_error "Full init aborted during infra."; exit 1; }
|
|
|
|
# Run canonical full seed
|
|
run_seed seed || { print_error "Full init aborted during seed."; exit 1; }
|
|
|
|
print_success "Full initialization completed successfully!"
|
|
}
|
|
|
|
# Function to run development mode
|
|
run_dev() {
|
|
print_status "Running development mode..."
|
|
|
|
# Stop any running API servers
|
|
print_status "🛑 Stopping any running API servers..."
|
|
pkill -f "python.*main\.py" 2>/dev/null || true
|
|
pkill -f "uvicorn" 2>/dev/null || true
|
|
sleep 1
|
|
|
|
# Ensure Redis service is running and will auto-clear dev database
|
|
print_status "🔧 Ensuring Redis service is running for development..."
|
|
|
|
$PYTHON_CMD -c "
|
|
from modules.redis_manager import ensure_redis_running
|
|
if ensure_redis_running('dev'):
|
|
print('✅ Redis service ready for development (will auto-clear db=0)')
|
|
else:
|
|
print('❌ Failed to start Redis service')
|
|
exit(1)
|
|
" || { print_error "Redis setup failed"; exit 1; }
|
|
|
|
print_status "🎯 Development mode will use clean Redis database (db=0)..."
|
|
print_status "Starting uvicorn server with auto-reload..."
|
|
|
|
export BACKEND_DEV_MODE=true
|
|
$PYTHON_CMD main.py --mode dev
|
|
|
|
if [ $? -eq 0 ]; then
|
|
print_success "Development server stopped successfully!"
|
|
else
|
|
print_error "Development server failed!"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to run production mode
|
|
run_prod() {
|
|
print_status "Running production mode..."
|
|
|
|
# Ensure Redis service is running with data recovery
|
|
print_status "🏰 Ensuring Redis service is running for production..."
|
|
|
|
$PYTHON_CMD -c "
|
|
from modules.redis_manager import ensure_redis_running
|
|
if ensure_redis_running('prod'):
|
|
print('✅ Redis service ready for production (db=1, with task recovery)')
|
|
else:
|
|
print('❌ Failed to start Redis service')
|
|
exit(1)
|
|
" || { print_error "Redis setup failed"; exit 1; }
|
|
|
|
print_status "Starting uvicorn server in production mode..."
|
|
|
|
export BACKEND_DEV_MODE=false
|
|
$PYTHON_CMD main.py --mode prod
|
|
|
|
if [ $? -eq 0 ]; then
|
|
print_success "Production server stopped successfully!"
|
|
else
|
|
print_error "Production server failed!"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
print_status "ClassroomCopilot Startup Script"
|
|
print_status "Start mode: $START_MODE"
|
|
echo
|
|
|
|
# Pre-flight checks
|
|
check_python
|
|
check_venv
|
|
check_env
|
|
echo
|
|
|
|
# Execute based on start mode
|
|
case $START_MODE in
|
|
"infra")
|
|
run_infra
|
|
;;
|
|
"seed")
|
|
run_seed seed
|
|
;;
|
|
"seed-test")
|
|
run_seed seed-test
|
|
;;
|
|
"gais-data")
|
|
run_gais_data
|
|
;;
|
|
"full")
|
|
run_full
|
|
;;
|
|
"nuke")
|
|
run_nuke
|
|
;;
|
|
"dev")
|
|
run_dev
|
|
;;
|
|
"prod")
|
|
run_prod
|
|
;;
|
|
*)
|
|
print_error "Invalid start mode: $START_MODE"
|
|
print_status "Valid modes: infra, seed, seed-test, gais-data, full, nuke, dev, prod"
|
|
print_status "Usage: ./start.sh [start_mode]"
|
|
print_status "Use './start.sh --help' for more information"
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|