#!/bin/bash # ============================================================================ # Development Server Startup Script for Task Reporter # Starts all services: MinIO, Backend (FastAPI), Frontend (Vite) # ============================================================================ set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Script directory (scripts are in project root) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$SCRIPT_DIR" # Load environment variables from .env file if [[ -f "$PROJECT_ROOT/.env" ]]; then # Export only specific port variables to avoid overriding shell environment export BACKEND_PORT="${BACKEND_PORT:-$(grep -E '^BACKEND_PORT=' "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 || echo '8000')}" export FRONTEND_PORT="${FRONTEND_PORT:-$(grep -E '^FRONTEND_PORT=' "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 || echo '3000')}" export MINIO_API_PORT="${MINIO_API_PORT:-$(grep -E '^MINIO_API_PORT=' "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 || echo '9000')}" export MINIO_CONSOLE_PORT="${MINIO_CONSOLE_PORT:-$(grep -E '^MINIO_CONSOLE_PORT=' "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 || echo '9001')}" else # Default values if .env doesn't exist export BACKEND_PORT="${BACKEND_PORT:-8000}" export FRONTEND_PORT="${FRONTEND_PORT:-3000}" export MINIO_API_PORT="${MINIO_API_PORT:-9000}" export MINIO_CONSOLE_PORT="${MINIO_CONSOLE_PORT:-9001}" fi # PID file locations PID_DIR="$PROJECT_ROOT/.pids" BACKEND_PID_FILE="$PID_DIR/backend.pid" FRONTEND_PID_FILE="$PID_DIR/frontend.pid" # Log file locations LOG_DIR="$PROJECT_ROOT/logs" BACKEND_LOG="$LOG_DIR/backend.log" FRONTEND_LOG="$LOG_DIR/frontend.log" # Helper functions print_header() { echo -e "\n${BLUE}=== $1 ===${NC}" } print_ok() { echo -e "${GREEN}[OK]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } print_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } print_info() { echo -e "${CYAN}[INFO]${NC} $1" } # Show help show_help() { echo "Usage: $0 [OPTIONS]" echo "" echo "Starts all development services for Task Reporter." echo "" echo "Options:" echo " -h, --help Show this help message" echo " --skip-checks Skip environment validation" echo " --no-frontend Don't start frontend server" echo " --no-minio Don't start MinIO (use external)" echo "" echo "Services started:" echo " - MinIO (Object Storage) - http://localhost:\$MINIO_API_PORT (API), http://localhost:\$MINIO_CONSOLE_PORT (Console)" echo " - Backend (FastAPI) - http://localhost:\$BACKEND_PORT" echo " - Frontend (Vite) - http://localhost:\$FRONTEND_PORT" } # Cleanup function for graceful shutdown cleanup() { echo -e "\n${YELLOW}Shutting down services...${NC}" "$PROJECT_ROOT/stop-dev.sh" exit 0 } # Trap Ctrl+C trap cleanup SIGINT SIGTERM # Parse arguments SKIP_CHECKS=false NO_FRONTEND=false NO_MINIO=false while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_help exit 0 ;; --skip-checks) SKIP_CHECKS=true shift ;; --no-frontend) NO_FRONTEND=true shift ;; --no-minio) NO_MINIO=true shift ;; *) echo "Unknown option: $1" show_help exit 1 ;; esac done echo -e "${BLUE}============================================${NC}" echo -e "${BLUE} Task Reporter - Development Server${NC}" echo -e "${BLUE}============================================${NC}" # Create directories mkdir -p "$PID_DIR" mkdir -p "$LOG_DIR" # ============================================================================ # Pre-flight Check # ============================================================================ if [[ "$SKIP_CHECKS" == "false" ]]; then print_header "Pre-flight Check" if ! "$PROJECT_ROOT/check-env.sh" -q; then print_error "Environment check failed. Fix issues above or use --skip-checks" exit 1 fi print_ok "Environment check passed" fi # ============================================================================ # Start MinIO # ============================================================================ if [[ "$NO_MINIO" == "false" ]]; then print_header "Starting MinIO" cd "$PROJECT_ROOT" # Check if MinIO container is already running if docker ps --format '{{.Names}}' | grep -q "task-reporter-minio"; then print_ok "MinIO is already running" else # Start MinIO if command -v docker-compose &> /dev/null; then docker-compose -f docker-compose.minio.yml up -d else docker compose -f docker-compose.minio.yml up -d fi # Wait for MinIO to be healthy print_info "Waiting for MinIO to be healthy..." MINIO_READY=false for i in {1..30}; do if curl -s "http://localhost:$MINIO_API_PORT/minio/health/live" > /dev/null 2>&1; then MINIO_READY=true break fi sleep 1 echo -n "." done echo "" if [[ "$MINIO_READY" == "true" ]]; then print_ok "MinIO is healthy" else print_error "MinIO failed to start within 30 seconds" exit 1 fi fi print_info "MinIO Console: http://localhost:$MINIO_CONSOLE_PORT (minioadmin/minioadmin)" fi # ============================================================================ # Start Backend # ============================================================================ print_header "Starting Backend" cd "$PROJECT_ROOT" # Check if backend is already running if [[ -f "$BACKEND_PID_FILE" ]] && kill -0 "$(cat "$BACKEND_PID_FILE")" 2>/dev/null; then print_ok "Backend is already running (PID: $(cat "$BACKEND_PID_FILE"))" else # Activate virtual environment and start uvicorn print_info "Starting uvicorn server..." # Source the virtual environment and run uvicorn ( source "$PROJECT_ROOT/venv/bin/activate" cd "$PROJECT_ROOT" uvicorn app.main:app --reload --host 0.0.0.0 --port "$BACKEND_PORT" > "$BACKEND_LOG" 2>&1 & echo $! > "$BACKEND_PID_FILE" ) # Wait for backend to be ready print_info "Waiting for backend to be ready..." BACKEND_READY=false for i in {1..15}; do if curl -s "http://localhost:$BACKEND_PORT/api/health" > /dev/null 2>&1 || curl -s "http://localhost:$BACKEND_PORT/docs" > /dev/null 2>&1; then BACKEND_READY=true break fi sleep 1 echo -n "." done echo "" if [[ "$BACKEND_READY" == "true" ]]; then print_ok "Backend is ready (PID: $(cat "$BACKEND_PID_FILE"))" else print_warn "Backend may still be starting. Check logs: $BACKEND_LOG" fi fi print_info "Backend API: http://localhost:$BACKEND_PORT" print_info "API Docs: http://localhost:$BACKEND_PORT/docs" # ============================================================================ # Start Frontend # ============================================================================ if [[ "$NO_FRONTEND" == "false" ]]; then print_header "Starting Frontend" cd "$PROJECT_ROOT/frontend" # Check if frontend is already running if [[ -f "$FRONTEND_PID_FILE" ]] && kill -0 "$(cat "$FRONTEND_PID_FILE")" 2>/dev/null; then print_ok "Frontend is already running (PID: $(cat "$FRONTEND_PID_FILE"))" else # Install dependencies if needed if [[ ! -d "node_modules" ]]; then print_info "Installing frontend dependencies..." npm install fi # Start Vite dev server print_info "Starting Vite dev server..." npm run dev > "$FRONTEND_LOG" 2>&1 & echo $! > "$FRONTEND_PID_FILE" # Wait for frontend to be ready sleep 3 if kill -0 "$(cat "$FRONTEND_PID_FILE")" 2>/dev/null; then print_ok "Frontend started (PID: $(cat "$FRONTEND_PID_FILE"))" else print_error "Frontend failed to start. Check logs: $FRONTEND_LOG" fi fi print_info "Frontend: http://localhost:$FRONTEND_PORT" fi # ============================================================================ # Summary # ============================================================================ print_header "Services Running" echo -e "${GREEN}============================================${NC}" echo -e "${GREEN} All services are running!${NC}" echo -e "${GREEN}============================================${NC}" echo "" echo -e " ${CYAN}Frontend:${NC} http://localhost:$FRONTEND_PORT" echo -e " ${CYAN}Backend API:${NC} http://localhost:$BACKEND_PORT" echo -e " ${CYAN}API Docs:${NC} http://localhost:$BACKEND_PORT/docs" echo -e " ${CYAN}MinIO Console:${NC} http://localhost:$MINIO_CONSOLE_PORT" echo "" echo -e " ${YELLOW}Logs:${NC}" echo -e " Backend: $BACKEND_LOG" echo -e " Frontend: $FRONTEND_LOG" echo "" echo -e " ${YELLOW}Press Ctrl+C to stop all services${NC}" echo "" # Keep script running to catch Ctrl+C while true; do sleep 1 done