445 lines
14 KiB
Bash
Executable File
445 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# ================================================================================================
|
||
# ENHANCED TECH STACK SELECTOR - MIGRATED VERSION STARTUP SCRIPT
|
||
# Uses PostgreSQL data migrated to Neo4j with proper price-based relationships
|
||
# ================================================================================================
|
||
|
||
set -e
|
||
|
||
# Parse command line arguments
|
||
FORCE_MIGRATION=false
|
||
if [ "$1" = "--force-migration" ] || [ "$1" = "-f" ]; then
|
||
FORCE_MIGRATION=true
|
||
echo "🔄 Force migration mode enabled"
|
||
elif [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
|
||
echo "Usage: $0 [OPTIONS]"
|
||
echo ""
|
||
echo "Options:"
|
||
echo " --force-migration, -f Force re-run all migrations"
|
||
echo " --help, -h Show this help message"
|
||
echo ""
|
||
echo "Examples:"
|
||
echo " $0 # Normal startup with auto-migration detection"
|
||
echo " $0 --force-migration # Force re-run all migrations"
|
||
exit 0
|
||
fi
|
||
|
||
echo "="*60
|
||
echo "🚀 ENHANCED TECH STACK SELECTOR v15.0 - MIGRATED VERSION"
|
||
echo "="*60
|
||
echo "✅ PostgreSQL data migrated to Neo4j"
|
||
echo "✅ Price-based relationships"
|
||
echo "✅ Real data from PostgreSQL"
|
||
echo "✅ Comprehensive pricing analysis"
|
||
echo "="*60
|
||
|
||
# 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 "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
# Check if Python is available
|
||
if ! command -v python3 &> /dev/null; then
|
||
print_error "Python3 is not installed or not in PATH"
|
||
exit 1
|
||
fi
|
||
|
||
print_status "Python3 found: $(python3 --version)"
|
||
|
||
# Check if pip is available
|
||
if ! command -v pip3 &> /dev/null; then
|
||
print_error "pip3 is not installed or not in PATH"
|
||
exit 1
|
||
fi
|
||
|
||
print_status "pip3 found: $(pip3 --version)"
|
||
|
||
# Check if psql is available
|
||
if ! command -v psql &> /dev/null; then
|
||
print_error "psql is not installed or not in PATH"
|
||
print_info "Please install PostgreSQL client tools:"
|
||
print_info " Ubuntu/Debian: sudo apt-get install postgresql-client"
|
||
print_info " CentOS/RHEL: sudo yum install postgresql"
|
||
print_info " macOS: brew install postgresql"
|
||
exit 1
|
||
fi
|
||
|
||
print_status "psql found: $(psql --version)"
|
||
|
||
# Check if createdb is available
|
||
if ! command -v createdb &> /dev/null; then
|
||
print_error "createdb is not installed or not in PATH"
|
||
print_info "Please install PostgreSQL client tools:"
|
||
print_info " Ubuntu/Debian: sudo apt-get install postgresql-client"
|
||
print_info " CentOS/RHEL: sudo yum install postgresql"
|
||
print_info " macOS: brew install postgresql"
|
||
exit 1
|
||
fi
|
||
|
||
print_status "createdb found: $(createdb --version)"
|
||
|
||
# Install/upgrade required packages
|
||
print_info "Installing/upgrading required packages..."
|
||
pip3 install --upgrade fastapi uvicorn neo4j psycopg2-binary anthropic loguru pydantic
|
||
|
||
# Function to create database if it doesn't exist
|
||
create_database_if_not_exists() {
|
||
print_info "Checking if database 'dev_pipeline' exists..."
|
||
|
||
# Try to connect to the specific database
|
||
if python3 -c "
|
||
import psycopg2
|
||
try:
|
||
conn = psycopg2.connect(
|
||
host='localhost',
|
||
port=5432,
|
||
user='pipeline_admin',
|
||
password='secure_pipeline_2024',
|
||
database='dev_pipeline'
|
||
)
|
||
conn.close()
|
||
print('Database dev_pipeline exists')
|
||
except Exception as e:
|
||
print(f'Database dev_pipeline does not exist: {e}')
|
||
exit(1)
|
||
" 2>/dev/null; then
|
||
print_status "Database 'dev_pipeline' exists"
|
||
return 0
|
||
else
|
||
print_warning "Database 'dev_pipeline' does not exist - creating it..."
|
||
|
||
# Try to create the database
|
||
if createdb -h localhost -p 5432 -U pipeline_admin dev_pipeline 2>/dev/null; then
|
||
print_status "Database 'dev_pipeline' created successfully"
|
||
return 0
|
||
else
|
||
print_error "Failed to create database 'dev_pipeline'"
|
||
print_info "Please create the database manually:"
|
||
print_info " createdb -h localhost -p 5432 -U pipeline_admin dev_pipeline"
|
||
return 1
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Check if PostgreSQL is running
|
||
print_info "Checking PostgreSQL connection..."
|
||
if ! python3 -c "
|
||
import psycopg2
|
||
try:
|
||
conn = psycopg2.connect(
|
||
host='localhost',
|
||
port=5432,
|
||
user='pipeline_admin',
|
||
password='secure_pipeline_2024',
|
||
database='postgres'
|
||
)
|
||
conn.close()
|
||
print('PostgreSQL connection successful')
|
||
except Exception as e:
|
||
print(f'PostgreSQL connection failed: {e}')
|
||
exit(1)
|
||
" 2>/dev/null; then
|
||
print_error "PostgreSQL is not running or not accessible"
|
||
print_info "Please ensure PostgreSQL is running and accessible"
|
||
exit 1
|
||
fi
|
||
|
||
print_status "PostgreSQL is running and accessible"
|
||
|
||
# Create database if it doesn't exist
|
||
if ! create_database_if_not_exists; then
|
||
exit 1
|
||
fi
|
||
|
||
# Function to check if database needs migration
|
||
check_database_migration() {
|
||
print_info "Checking if database needs migration..."
|
||
|
||
# Check if price_tiers table exists and has data
|
||
if ! python3 -c "
|
||
import psycopg2
|
||
try:
|
||
conn = psycopg2.connect(
|
||
host='localhost',
|
||
port=5432,
|
||
user='pipeline_admin',
|
||
password='secure_pipeline_2024',
|
||
database='dev_pipeline'
|
||
)
|
||
cursor = conn.cursor()
|
||
|
||
# Check if price_tiers table exists
|
||
cursor.execute(\"\"\"
|
||
SELECT EXISTS (
|
||
SELECT FROM information_schema.tables
|
||
WHERE table_schema = 'public'
|
||
AND table_name = 'price_tiers'
|
||
);
|
||
\"\"\")
|
||
table_exists = cursor.fetchone()[0]
|
||
|
||
if not table_exists:
|
||
print('price_tiers table does not exist - migration needed')
|
||
exit(1)
|
||
|
||
# Check if price_tiers has data
|
||
cursor.execute('SELECT COUNT(*) FROM price_tiers;')
|
||
count = cursor.fetchone()[0]
|
||
|
||
if count == 0:
|
||
print('price_tiers table is empty - migration needed')
|
||
exit(1)
|
||
|
||
# Check if stack_recommendations has sufficient data (should have more than 8 records)
|
||
cursor.execute('SELECT COUNT(*) FROM stack_recommendations;')
|
||
rec_count = cursor.fetchone()[0]
|
||
|
||
if rec_count < 30: # Expect at least 30 domain recommendations
|
||
print(f'stack_recommendations has only {rec_count} records - migration needed for additional domains')
|
||
exit(1)
|
||
|
||
# Check for specific new domains
|
||
cursor.execute(\"\"\"
|
||
SELECT COUNT(DISTINCT business_domain) FROM stack_recommendations
|
||
WHERE business_domain IN ('healthcare', 'finance', 'gaming', 'education', 'media', 'iot', 'social', 'elearning', 'realestate', 'travel', 'manufacturing', 'ecommerce', 'saas')
|
||
\"\"\")
|
||
new_domains_count = cursor.fetchone()[0]
|
||
|
||
if new_domains_count < 12: # Expect at least 12 domains
|
||
print(f'Only {new_domains_count} domains found - migration needed for additional domains')
|
||
exit(1)
|
||
|
||
print('Database appears to be fully migrated with all domains')
|
||
cursor.close()
|
||
conn.close()
|
||
|
||
except Exception as e:
|
||
print(f'Error checking database: {e}')
|
||
exit(1)
|
||
" 2>/dev/null; then
|
||
return 1 # Migration needed
|
||
else
|
||
return 0 # Migration not needed
|
||
fi
|
||
}
|
||
|
||
# Function to run PostgreSQL migrations
|
||
run_postgres_migrations() {
|
||
print_info "Running PostgreSQL migrations..."
|
||
|
||
# Migration files in order
|
||
migration_files=(
|
||
"db/001_schema.sql"
|
||
"db/002_tools_migration.sql"
|
||
"db/003_tools_pricing_migration.sql"
|
||
"db/004_comprehensive_stacks_migration.sql"
|
||
"db/005_comprehensive_ecommerce_stacks.sql"
|
||
"db/006_comprehensive_all_domains_stacks.sql"
|
||
)
|
||
|
||
# Set PGPASSWORD to avoid password prompts
|
||
export PGPASSWORD="secure_pipeline_2024"
|
||
|
||
for migration_file in "${migration_files[@]}"; do
|
||
if [ ! -f "$migration_file" ]; then
|
||
print_error "Migration file not found: $migration_file"
|
||
exit 1
|
||
fi
|
||
|
||
print_info "Running migration: $migration_file"
|
||
|
||
# Run migration with error handling
|
||
if psql -h localhost -p 5432 -U pipeline_admin -d dev_pipeline -f "$migration_file" -q 2>/dev/null; then
|
||
print_status "Migration completed: $migration_file"
|
||
else
|
||
print_error "Migration failed: $migration_file"
|
||
print_info "Check the error logs above for details"
|
||
print_info "You may need to run the migration manually:"
|
||
print_info " psql -h localhost -p 5432 -U pipeline_admin -d dev_pipeline -f $migration_file"
|
||
exit 1
|
||
fi
|
||
done
|
||
|
||
# Unset password
|
||
unset PGPASSWORD
|
||
|
||
print_status "All PostgreSQL migrations completed successfully"
|
||
}
|
||
|
||
# Check if migration is needed and run if necessary
|
||
if [ "$FORCE_MIGRATION" = true ]; then
|
||
print_warning "Force migration enabled - running migrations..."
|
||
run_postgres_migrations
|
||
|
||
# Verify migration was successful
|
||
print_info "Verifying migration..."
|
||
if check_database_migration; then
|
||
print_status "Migration verification successful"
|
||
else
|
||
print_error "Migration verification failed"
|
||
exit 1
|
||
fi
|
||
elif check_database_migration; then
|
||
print_status "Database is already migrated"
|
||
else
|
||
print_warning "Database needs migration - running migrations..."
|
||
run_postgres_migrations
|
||
|
||
# Verify migration was successful
|
||
print_info "Verifying migration..."
|
||
if check_database_migration; then
|
||
print_status "Migration verification successful"
|
||
else
|
||
print_error "Migration verification failed"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Show migration summary
|
||
print_info "Migration Summary:"
|
||
python3 -c "
|
||
import psycopg2
|
||
try:
|
||
conn = psycopg2.connect(
|
||
host='localhost',
|
||
port=5432,
|
||
user='pipeline_admin',
|
||
password='secure_pipeline_2024',
|
||
database='dev_pipeline'
|
||
)
|
||
cursor = conn.cursor()
|
||
|
||
# Get table counts
|
||
tables = ['price_tiers', 'frontend_technologies', 'backend_technologies', 'database_technologies',
|
||
'cloud_technologies', 'testing_technologies', 'mobile_technologies', 'devops_technologies',
|
||
'ai_ml_technologies', 'tools', 'price_based_stacks', 'stack_recommendations']
|
||
|
||
print('📊 Database Statistics:')
|
||
for table in tables:
|
||
try:
|
||
cursor.execute(f'SELECT COUNT(*) FROM {table};')
|
||
count = cursor.fetchone()[0]
|
||
print(f' {table}: {count} records')
|
||
except Exception as e:
|
||
print(f' {table}: Error - {e}')
|
||
|
||
cursor.close()
|
||
conn.close()
|
||
except Exception as e:
|
||
print(f'Error getting migration summary: {e}')
|
||
" 2>/dev/null
|
||
|
||
# Check if Neo4j is running
|
||
print_info "Checking Neo4j connection..."
|
||
if ! python3 -c "
|
||
from neo4j import GraphDatabase
|
||
try:
|
||
driver = GraphDatabase.driver('bolt://localhost:7687', auth=('neo4j', 'password'))
|
||
driver.verify_connectivity()
|
||
print('Neo4j connection successful')
|
||
driver.close()
|
||
except Exception as e:
|
||
print(f'Neo4j connection failed: {e}')
|
||
exit(1)
|
||
" 2>/dev/null; then
|
||
print_error "Neo4j is not running or not accessible"
|
||
print_info "Please start Neo4j first:"
|
||
print_info " docker run -d --name neo4j -p 7474:7474 -p 7687:7687 -e NEO4J_AUTH=neo4j/password neo4j:latest"
|
||
print_info " Wait for Neo4j to start (check http://localhost:7474)"
|
||
exit 1
|
||
fi
|
||
|
||
print_status "Neo4j is running and accessible"
|
||
|
||
# Check if migration has been run
|
||
print_info "Checking if migration has been completed..."
|
||
if ! python3 -c "
|
||
from neo4j import GraphDatabase
|
||
try:
|
||
driver = GraphDatabase.driver('bolt://localhost:7687', auth=('neo4j', 'password'))
|
||
with driver.session() as session:
|
||
result = session.run('MATCH (p:PriceTier) RETURN count(p) as count')
|
||
price_tiers = result.single()['count']
|
||
if price_tiers == 0:
|
||
print('No data found in Neo4j - migration needed')
|
||
exit(1)
|
||
else:
|
||
print(f'Found {price_tiers} price tiers - migration appears complete')
|
||
driver.close()
|
||
except Exception as e:
|
||
print(f'Error checking migration status: {e}')
|
||
exit(1)
|
||
" 2>/dev/null; then
|
||
print_warning "No data found in Neo4j - running migration..."
|
||
|
||
# Run migration
|
||
if python3 migrate_postgres_to_neo4j.py; then
|
||
print_status "Migration completed successfully"
|
||
else
|
||
print_error "Migration failed"
|
||
exit 1
|
||
fi
|
||
else
|
||
print_status "Migration appears to be complete"
|
||
fi
|
||
|
||
# Set environment variables
|
||
export NEO4J_URI="bolt://localhost:7687"
|
||
export NEO4J_USER="neo4j"
|
||
export NEO4J_PASSWORD="password"
|
||
export POSTGRES_HOST="localhost"
|
||
export POSTGRES_PORT="5432"
|
||
export POSTGRES_USER="pipeline_admin"
|
||
export POSTGRES_PASSWORD="secure_pipeline_2024"
|
||
export POSTGRES_DB="dev_pipeline"
|
||
export CLAUDE_API_KEY="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"
|
||
|
||
print_status "Environment variables set"
|
||
|
||
# Create logs directory if it doesn't exist
|
||
mkdir -p logs
|
||
|
||
# Start the migrated application
|
||
print_info "Starting Enhanced Tech Stack Selector (Migrated Version)..."
|
||
print_info "Server will be available at: http://localhost:8002"
|
||
print_info "API documentation: http://localhost:8002/docs"
|
||
print_info "Health check: http://localhost:8002/health"
|
||
print_info "Diagnostics: http://localhost:8002/api/diagnostics"
|
||
print_info ""
|
||
print_info "Press Ctrl+C to stop the server"
|
||
print_info ""
|
||
|
||
# Run TSS namespace migration
|
||
print_info "Running TSS namespace migration..."
|
||
cd src
|
||
if python3 migrate_to_tss_namespace.py; then
|
||
print_status "TSS namespace migration completed successfully"
|
||
else
|
||
print_error "TSS namespace migration failed"
|
||
exit 1
|
||
fi
|
||
|
||
# Start the application
|
||
print_info "Starting Tech Stack Selector application..."
|
||
python3 main_migrated.py
|