heatmap / scripts /run_local.ps1
Ndg07's picture
Feat: 24-hour cleanup for local SQLite
c293f7c
# Local Development Setup Script (PowerShell)
# Starts all services required for the misinformation heatmap application
param(
[string]$Mode = "local",
[switch]$SkipDeps,
[switch]$SkipDb,
[switch]$SkipFrontend,
[switch]$Verbose,
[switch]$Detached,
[switch]$Stop,
[switch]$Status,
[switch]$Logs,
[switch]$Help
)
# Colors for output
$Red = "Red"
$Green = "Green"
$Yellow = "Yellow"
$Blue = "Cyan"
$Purple = "Magenta"
# Configuration
$ProjectRoot = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
$BackendDir = Join-Path $ProjectRoot "backend"
$FrontendDir = Join-Path $ProjectRoot "frontend"
$DataDir = Join-Path $ProjectRoot "data"
$LogsDir = Join-Path $ProjectRoot "logs"
function Write-Header {
param([string]$Message)
Write-Host "================================" -ForegroundColor $Purple
Write-Host $Message -ForegroundColor $Purple
Write-Host "================================" -ForegroundColor $Purple
}
function Write-Status {
param([string]$Message)
Write-Host "[INFO] $Message" -ForegroundColor $Blue
}
function Write-Success {
param([string]$Message)
Write-Host "[SUCCESS] $Message" -ForegroundColor $Green
}
function Write-Warning {
param([string]$Message)
Write-Host "[WARNING] $Message" -ForegroundColor $Yellow
}
function Write-Error {
param([string]$Message)
Write-Host "[ERROR] $Message" -ForegroundColor $Red
}
function Show-Usage {
Write-Host "Usage: .\run_local.ps1 [OPTIONS]"
Write-Host ""
Write-Host "Options:"
Write-Host " -Help Show this help message"
Write-Host " -Mode MODE Set deployment mode (local|cloud) [default: local]"
Write-Host " -SkipDeps Skip dependency installation"
Write-Host " -SkipDb Skip database initialization"
Write-Host " -SkipFrontend Skip frontend serving"
Write-Host " -Verbose Enable verbose output"
Write-Host " -Detached Run services in detached mode"
Write-Host " -Stop Stop all running services"
Write-Host " -Status Show status of running services"
Write-Host " -Logs Show logs from all services"
Write-Host ""
Write-Host "Examples:"
Write-Host " .\run_local.ps1 Start all services in local mode"
Write-Host " .\run_local.ps1 -Mode cloud Start with cloud configuration"
Write-Host " .\run_local.ps1 -SkipDeps Start without installing dependencies"
Write-Host " .\run_local.ps1 -Detached Start services in background"
Write-Host " .\run_local.ps1 -Stop Stop all running services"
}
function Test-Prerequisites {
Write-Status "Checking prerequisites..."
# Check Python
try {
$pythonVersion = python --version 2>&1
Write-Status "Python version: $pythonVersion"
} catch {
Write-Error "Python is not installed. Please install Python 3.8 or higher."
exit 1
}
# Check pip
try {
pip --version | Out-Null
} catch {
Write-Error "pip is not installed. Please install pip."
exit 1
}
# Check Node.js (for frontend)
if (-not $SkipFrontend) {
try {
$nodeVersion = node --version
Write-Status "Node.js version: $nodeVersion"
} catch {
Write-Warning "Node.js not found. Frontend serving will be disabled."
$script:SkipFrontend = $true
}
}
# Check required directories
$requiredDirs = @($BackendDir, $FrontendDir, $DataDir)
foreach ($dir in $requiredDirs) {
if (-not (Test-Path $dir)) {
Write-Error "Required directory not found: $dir"
exit 1
}
}
Write-Success "Prerequisites check completed"
}
function New-Directories {
Write-Status "Creating necessary directories..."
@($LogsDir, $DataDir, (Join-Path $ProjectRoot ".env")) | ForEach-Object {
if (-not (Test-Path $_)) {
New-Item -ItemType Directory -Path $_ -Force | Out-Null
}
}
Write-Success "Directories created"
}
function Install-Dependencies {
if ($SkipDeps) {
Write-Warning "Skipping dependency installation"
return
}
Write-Status "Installing Python dependencies..."
Set-Location $BackendDir
# Create virtual environment if it doesn't exist
if (-not (Test-Path "venv")) {
Write-Status "Creating Python virtual environment..."
python -m venv venv
}
# Activate virtual environment
& ".\venv\Scripts\Activate.ps1"
# Upgrade pip
pip install --upgrade pip
# Install requirements
if (Test-Path "requirements.txt") {
pip install -r requirements.txt
} else {
Write-Error "requirements.txt not found in backend directory"
exit 1
}
Write-Success "Python dependencies installed"
# Install frontend dependencies if needed
if (-not $SkipFrontend -and (Test-Path (Join-Path $FrontendDir "package.json"))) {
Write-Status "Installing frontend dependencies..."
Set-Location $FrontendDir
npm install
Write-Success "Frontend dependencies installed"
}
}
function Initialize-Database {
if ($SkipDb) {
Write-Warning "Skipping database initialization"
return
}
Write-Status "Initializing database..."
Set-Location $BackendDir
& ".\venv\Scripts\Activate.ps1"
# Run database initialization script
if (Test-Path "init_db.py") {
python init_db.py --mode $Mode
Write-Success "Database initialized"
} else {
Write-Warning "Database initialization script not found, skipping..."
}
}
function Set-Environment {
Write-Status "Setting up environment variables..."
# Create .env file if it doesn't exist
$envFile = Join-Path $ProjectRoot ".env"
if (-not (Test-Path $envFile)) {
Write-Status "Creating .env file..."
$envContent = @"
# Misinformation Heatmap Configuration
MODE=$Mode
DEBUG=true
LOG_LEVEL=INFO
# Database Configuration
DATABASE_URL=sqlite:///./data/heatmap.db
# API Configuration
API_HOST=0.0.0.0
API_PORT=8000
CORS_ORIGINS=["http://localhost:3000", "http://localhost:8000"]
# NLP Configuration
HUGGINGFACE_TOKEN=
MODEL_CACHE_DIR=./models
# Pub/Sub Configuration (Local)
PUBSUB_EMULATOR_HOST=localhost:8085
PUBSUB_PROJECT_ID=misinformation-heatmap-local
# Google Cloud Configuration (for cloud mode)
GOOGLE_CLOUD_PROJECT=
GOOGLE_APPLICATION_CREDENTIALS=
# IBM Watson Configuration (for cloud mode)
WATSON_DISCOVERY_API_KEY=
WATSON_DISCOVERY_URL=
# Monitoring Configuration
ENABLE_METRICS=true
METRICS_PORT=9090
"@
Set-Content -Path $envFile -Value $envContent
Write-Success ".env file created"
} else {
Write-Status ".env file already exists"
}
}
function Start-PubSubEmulator {
if ($Mode -ne "local") {
return
}
Write-Status "Starting Pub/Sub emulator..."
# Check if gcloud is installed
try {
gcloud version | Out-Null
} catch {
Write-Warning "gcloud CLI not found. Installing Pub/Sub emulator..."
pip install google-cloud-pubsub
}
# Start emulator
$pubsubLog = Join-Path $LogsDir "pubsub-emulator.log"
if ($Detached) {
$pubsubProcess = Start-Process -FilePath "gcloud" -ArgumentList "beta", "emulators", "pubsub", "start", "--host-port=localhost:8085" -RedirectStandardOutput $pubsubLog -RedirectStandardError $pubsubLog -PassThru
$pubsubProcess.Id | Out-File (Join-Path $LogsDir "pubsub.pid")
Write-Success "Pub/Sub emulator started (PID: $($pubsubProcess.Id))"
} else {
Write-Status "Starting Pub/Sub emulator (press Ctrl+C to stop all services)"
$pubsubProcess = Start-Process -FilePath "gcloud" -ArgumentList "beta", "emulators", "pubsub", "start", "--host-port=localhost:8085" -PassThru
$pubsubProcess.Id | Out-File (Join-Path $LogsDir "pubsub.pid")
}
# Wait for emulator to start
Start-Sleep -Seconds 3
# Create topics and subscriptions
$env:PUBSUB_EMULATOR_HOST = "localhost:8085"
$createTopicsScript = @"
import os
from google.cloud import pubsub_v1
os.environ['PUBSUB_EMULATOR_HOST'] = 'localhost:8085'
project_id = 'misinformation-heatmap-local'
publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()
# Create topics
topics = ['events-raw', 'events-processed', 'events-validated']
for topic_name in topics:
topic_path = publisher.topic_path(project_id, topic_name)
try:
publisher.create_topic(request={'name': topic_path})
print(f'Created topic: {topic_name}')
except Exception as e:
print(f'Topic {topic_name} may already exist: {e}')
# Create subscriptions
subscriptions = [
('events-raw', 'events-raw-sub'),
('events-processed', 'events-processed-sub'),
('events-validated', 'events-validated-sub')
]
for topic_name, sub_name in subscriptions:
topic_path = publisher.topic_path(project_id, topic_name)
subscription_path = subscriber.subscription_path(project_id, sub_name)
try:
subscriber.create_subscription(
request={'name': subscription_path, 'topic': topic_path}
)
print(f'Created subscription: {sub_name}')
except Exception as e:
print(f'Subscription {sub_name} may already exist: {e}')
"@
python -c $createTopicsScript
}
function Start-Backend {
Write-Status "Starting backend API server..."
Set-Location $BackendDir
& ".\venv\Scripts\Activate.ps1"
$apiLog = Join-Path $LogsDir "api.log"
if ($Detached) {
$apiProcess = Start-Process -FilePath "python" -ArgumentList "api.py" -RedirectStandardOutput $apiLog -RedirectStandardError $apiLog -PassThru
$apiProcess.Id | Out-File (Join-Path $LogsDir "api.pid")
Write-Success "Backend API started (PID: $($apiProcess.Id))"
} else {
Write-Status "Starting backend API (press Ctrl+C to stop all services)"
$apiProcess = Start-Process -FilePath "python" -ArgumentList "api.py" -PassThru
$apiProcess.Id | Out-File (Join-Path $LogsDir "api.pid")
}
}
function Start-Frontend {
if ($SkipFrontend) {
Write-Warning "Skipping frontend server"
return
}
Write-Status "Starting frontend server..."
Set-Location $FrontendDir
$frontendLog = Join-Path $LogsDir "frontend.log"
# Use Python's built-in HTTP server for simplicity
if ($Detached) {
$frontendProcess = Start-Process -FilePath "python" -ArgumentList "-m", "http.server", "3000" -RedirectStandardOutput $frontendLog -RedirectStandardError $frontendLog -PassThru
$frontendProcess.Id | Out-File (Join-Path $LogsDir "frontend.pid")
Write-Success "Frontend server started (PID: $($frontendProcess.Id))"
} else {
Write-Status "Starting frontend server (press Ctrl+C to stop all services)"
$frontendProcess = Start-Process -FilePath "python" -ArgumentList "-m", "http.server", "3000" -PassThru
$frontendProcess.Id | Out-File (Join-Path $LogsDir "frontend.pid")
}
}
function Test-HealthChecks {
Write-Status "Performing health checks..."
# Wait a moment for services to start
Start-Sleep -Seconds 5
# Check backend API
try {
Invoke-WebRequest -Uri "http://localhost:8000/health" -UseBasicParsing | Out-Null
Write-Success "Backend API is healthy"
} catch {
Write-Warning "Backend API health check failed"
}
# Check frontend
if (-not $SkipFrontend) {
try {
Invoke-WebRequest -Uri "http://localhost:3000" -UseBasicParsing | Out-Null
Write-Success "Frontend server is healthy"
} catch {
Write-Warning "Frontend server health check failed"
}
}
# Check Pub/Sub emulator (local mode only)
if ($Mode -eq "local") {
try {
Invoke-WebRequest -Uri "http://localhost:8085" -UseBasicParsing | Out-Null
Write-Success "Pub/Sub emulator is healthy"
} catch {
Write-Warning "Pub/Sub emulator health check failed"
}
}
}
function Show-Status {
Write-Header "Service Status"
# Check API
$apiPidFile = Join-Path $LogsDir "api.pid"
if (Test-Path $apiPidFile) {
$apiPid = Get-Content $apiPidFile
if (Get-Process -Id $apiPid -ErrorAction SilentlyContinue) {
Write-Success "Backend API running (PID: $apiPid)"
} else {
Write-Warning "Backend API not running (stale PID file)"
}
} else {
Write-Warning "Backend API not started"
}
# Check frontend
$frontendPidFile = Join-Path $LogsDir "frontend.pid"
if (Test-Path $frontendPidFile) {
$frontendPid = Get-Content $frontendPidFile
if (Get-Process -Id $frontendPid -ErrorAction SilentlyContinue) {
Write-Success "Frontend server running (PID: $frontendPid)"
} else {
Write-Warning "Frontend server not running (stale PID file)"
}
} else {
Write-Warning "Frontend server not started"
}
# Check Pub/Sub emulator
$pubsubPidFile = Join-Path $LogsDir "pubsub.pid"
if (Test-Path $pubsubPidFile) {
$pubsubPid = Get-Content $pubsubPidFile
if (Get-Process -Id $pubsubPid -ErrorAction SilentlyContinue) {
Write-Success "Pub/Sub emulator running (PID: $pubsubPid)"
} else {
Write-Warning "Pub/Sub emulator not running (stale PID file)"
}
} else {
Write-Warning "Pub/Sub emulator not started"
}
}
function Show-Logs {
Write-Header "Service Logs"
$apiLog = Join-Path $LogsDir "api.log"
if (Test-Path $apiLog) {
Write-Host "=== Backend API Logs ===" -ForegroundColor $Blue
Get-Content $apiLog -Tail 20
Write-Host ""
}
$frontendLog = Join-Path $LogsDir "frontend.log"
if (Test-Path $frontendLog) {
Write-Host "=== Frontend Server Logs ===" -ForegroundColor $Blue
Get-Content $frontendLog -Tail 20
Write-Host ""
}
$pubsubLog = Join-Path $LogsDir "pubsub-emulator.log"
if (Test-Path $pubsubLog) {
Write-Host "=== Pub/Sub Emulator Logs ===" -ForegroundColor $Blue
Get-Content $pubsubLog -Tail 20
Write-Host ""
}
}
function Stop-Services {
Write-Header "Stopping Services"
# Stop API
$apiPidFile = Join-Path $LogsDir "api.pid"
if (Test-Path $apiPidFile) {
$apiPid = Get-Content $apiPidFile
if (Get-Process -Id $apiPid -ErrorAction SilentlyContinue) {
Stop-Process -Id $apiPid -Force
Write-Success "Backend API stopped"
}
Remove-Item $apiPidFile -Force
}
# Stop frontend
$frontendPidFile = Join-Path $LogsDir "frontend.pid"
if (Test-Path $frontendPidFile) {
$frontendPid = Get-Content $frontendPidFile
if (Get-Process -Id $frontendPid -ErrorAction SilentlyContinue) {
Stop-Process -Id $frontendPid -Force
Write-Success "Frontend server stopped"
}
Remove-Item $frontendPidFile -Force
}
# Stop Pub/Sub emulator
$pubsubPidFile = Join-Path $LogsDir "pubsub.pid"
if (Test-Path $pubsubPidFile) {
$pubsubPid = Get-Content $pubsubPidFile
if (Get-Process -Id $pubsubPid -ErrorAction SilentlyContinue) {
Stop-Process -Id $pubsubPid -Force
Write-Success "Pub/Sub emulator stopped"
}
Remove-Item $pubsubPidFile -Force
}
Write-Success "All services stopped"
}
function Show-ServiceUrls {
Write-Header "Service URLs"
Write-Host "Backend API: http://localhost:8000" -ForegroundColor $Green
Write-Host "API Documentation: http://localhost:8000/docs" -ForegroundColor $Green
Write-Host "Health Check: http://localhost:8000/health" -ForegroundColor $Green
if (-not $SkipFrontend) {
Write-Host "Frontend: http://localhost:3000" -ForegroundColor $Green
}
if ($Mode -eq "local") {
Write-Host "Pub/Sub Emulator: http://localhost:8085" -ForegroundColor $Green
}
Write-Host ""
Write-Host "Logs Directory: $LogsDir" -ForegroundColor $Yellow
Write-Host "Data Directory: $DataDir" -ForegroundColor $Yellow
}
# Main execution
function Main {
if ($Help) {
Show-Usage
return
}
if ($Stop) {
Stop-Services
return
}
if ($Status) {
Show-Status
return
}
if ($Logs) {
Show-Logs
return
}
Write-Header "Misinformation Heatmap - Local Development Setup"
Test-Prerequisites
New-Directories
Set-Environment
Install-Dependencies
Initialize-Database
# Start services
if ($Mode -eq "local") {
Start-PubSubEmulator
}
Start-Backend
Start-Frontend
# Perform health checks
Test-HealthChecks
# Show service information
Show-ServiceUrls
if ($Detached) {
Write-Success "All services started in detached mode"
Write-Status "Use '.\run_local.ps1 -Status' to check service status"
Write-Status "Use '.\run_local.ps1 -Logs' to view service logs"
Write-Status "Use '.\run_local.ps1 -Stop' to stop all services"
} else {
Write-Success "All services started successfully!"
Write-Status "Press Ctrl+C to stop all services"
# Wait for user interrupt
try {
while ($true) {
Start-Sleep -Seconds 1
}
} finally {
if (-not $Detached) {
Write-Status "Cleaning up..."
Stop-Services
}
}
}
}
# Run main function
Main