419 lines
12 KiB
Bash
Executable File
419 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ClassroomCopilot Startup Script
|
|
# Usage: ./start.sh [start_mode]
|
|
# start_mode options: infra, demo-school, demo-users, 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 " demo-school - Create demo school (KevlarAI)"
|
|
echo " demo-users - Create demo users"
|
|
echo " gais-data - Import GAIS data (Edubase, etc.)"
|
|
echo " full - Run full initialization (infra → demo-school → demo-users → gais-data)"
|
|
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 demo-school # Create demo school"
|
|
echo " ./start.sh demo-users # Create demo users"
|
|
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 demo school creation
|
|
run_demo_school() {
|
|
print_status "Running demo school creation mode..."
|
|
print_status "This will create the KevlarAI demo school."
|
|
|
|
# Check if we should proceed
|
|
if [[ "$AUTO_YES" != true ]]; then
|
|
read -p "Do you want to continue with demo school creation? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
print_status "Demo school creation cancelled."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
print_status "Starting demo school creation process..."
|
|
$PYTHON_CMD main.py --mode demo-school
|
|
|
|
if [ $? -eq 0 ]; then
|
|
print_success "Demo school creation completed successfully!"
|
|
else
|
|
print_error "Demo school creation failed!"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to run demo users creation
|
|
run_demo_users() {
|
|
print_status "Running demo users creation mode..."
|
|
print_status "This will create demo users for testing."
|
|
|
|
# Check if we should proceed
|
|
if [[ "$AUTO_YES" != true ]]; then
|
|
read -p "Do you want to continue with demo users creation? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
print_status "Demo users creation cancelled."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
print_status "Starting demo users creation process..."
|
|
$PYTHON_CMD main.py --mode demo-users
|
|
|
|
if [ $? -eq 0 ]; then
|
|
print_success "Demo users creation completed successfully!"
|
|
else
|
|
print_error "Demo users creation 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 → demo-school → demo-users → gais-data)..."
|
|
|
|
# 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 demo school
|
|
run_demo_school || { print_error "Full init aborted during demo-school."; exit 1; }
|
|
|
|
# Run demo users
|
|
run_demo_users || { print_error "Full init aborted during demo-users."; exit 1; }
|
|
|
|
# Run GAIS data import
|
|
run_gais_data || { print_error "Full init aborted during gais-data."; 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
|
|
;;
|
|
"demo-school")
|
|
run_demo_school
|
|
;;
|
|
"demo-users")
|
|
run_demo_users
|
|
;;
|
|
"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, demo-school, demo-users, gais-data, 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 "$@"
|