diff --git a/.gitignore b/.gitignore index b324d4b..dce07a9 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,7 @@ server.log node_modules/ frontend/dist/ frontend/.vite/ + +# Development scripts +.pids/ +logs/ diff --git a/check-env.sh b/check-env.sh new file mode 100755 index 0000000..5b93441 --- /dev/null +++ b/check-env.sh @@ -0,0 +1,258 @@ +#!/bin/bash +# ============================================================================ +# Environment Check Script for Task Reporter +# Validates all prerequisites required to run the development environment +# ============================================================================ + +# Note: Not using set -e because we handle errors explicitly with ERRORS counter + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Script directory (scripts are in project root) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$SCRIPT_DIR" + +# Track overall status +ERRORS=0 +WARNINGS=0 + +# 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" + ((ERRORS++)) +} + +print_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" + ((WARNINGS++)) +} + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +# Show help +show_help() { + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Validates the development environment for Task Reporter." + echo "" + echo "Options:" + echo " -h, --help Show this help message" + echo " -q, --quiet Only show errors and warnings" + echo "" + echo "Checks performed:" + echo " - Python version (3.10+)" + echo " - Node.js and npm" + echo " - Docker availability" + echo " - Virtual environment (venv/)" + echo " - Environment file (.env)" + echo " - Port availability (8000, 3000, 9000, 9001)" +} + +# Parse arguments +QUIET=false +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -q|--quiet) + QUIET=true + shift + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +echo -e "${BLUE}============================================${NC}" +echo -e "${BLUE} Task Reporter - Environment Check${NC}" +echo -e "${BLUE}============================================${NC}" + +# ============================================================================ +# Check Python version +# ============================================================================ +print_header "Python" + +if command -v python3 &> /dev/null; then + PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') + PYTHON_MAJOR=$(echo "$PYTHON_VERSION" | cut -d. -f1) + PYTHON_MINOR=$(echo "$PYTHON_VERSION" | cut -d. -f2) + + if [[ "$PYTHON_MAJOR" -ge 3 ]] && [[ "$PYTHON_MINOR" -ge 10 ]]; then + print_ok "Python $PYTHON_VERSION detected" + else + print_error "Python 3.10+ required, found $PYTHON_VERSION" + fi +else + print_error "Python3 not found. Please install Python 3.10+" +fi + +# ============================================================================ +# Check Node.js and npm +# ============================================================================ +print_header "Node.js" + +if command -v node &> /dev/null; then + NODE_VERSION=$(node --version) + print_ok "Node.js $NODE_VERSION detected" +else + print_error "Node.js not found. Please install Node.js 18+" +fi + +if command -v npm &> /dev/null; then + NPM_VERSION=$(npm --version) + print_ok "npm $NPM_VERSION detected" +else + print_error "npm not found. Please install npm" +fi + +# ============================================================================ +# Check Docker +# ============================================================================ +print_header "Docker" + +if command -v docker &> /dev/null; then + DOCKER_VERSION=$(docker --version | cut -d' ' -f3 | tr -d ',') + print_ok "Docker $DOCKER_VERSION detected" + + # Check if Docker daemon is running + if docker info &> /dev/null; then + print_ok "Docker daemon is running" + else + print_error "Docker daemon is not running. Please start Docker" + fi +else + print_error "Docker not found. Please install Docker" +fi + +if command -v docker-compose &> /dev/null; then + COMPOSE_VERSION=$(docker-compose --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) + print_ok "docker-compose $COMPOSE_VERSION detected" +elif docker compose version &> /dev/null; then + COMPOSE_VERSION=$(docker compose version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) + print_ok "docker compose (plugin) $COMPOSE_VERSION detected" +else + print_error "docker-compose not found. Please install docker-compose" +fi + +# ============================================================================ +# Check Virtual Environment +# ============================================================================ +print_header "Virtual Environment" + +if [[ -d "$PROJECT_ROOT/venv" ]]; then + print_ok "Virtual environment found at venv/" + + # Check if it has required packages + if [[ -f "$PROJECT_ROOT/venv/bin/activate" ]]; then + print_ok "venv/bin/activate exists" + else + print_warn "venv/bin/activate not found - venv may be corrupted" + fi +else + print_error "Virtual environment not found" + print_info "Create it with: python3 -m venv venv" + print_info "Then activate: source venv/bin/activate" + print_info "And install: pip install -r requirements.txt" +fi + +# ============================================================================ +# Check Environment File +# ============================================================================ +print_header "Environment File" + +if [[ -f "$PROJECT_ROOT/.env" ]]; then + print_ok ".env file exists" + + # Check for critical variables (use || true to prevent set -e from exiting) + if grep -q "^FERNET_KEY=.\+" "$PROJECT_ROOT/.env" 2>/dev/null; then + print_ok "FERNET_KEY is set" + else + print_warn "FERNET_KEY appears to be empty" + print_info "Generate with: python -c \"from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())\"" + fi + + if grep -q "^DATABASE_URL=" "$PROJECT_ROOT/.env" 2>/dev/null; then + print_ok "DATABASE_URL is set" + else + print_warn "DATABASE_URL is not set" + fi + + if grep -q "^MINIO_ENDPOINT=" "$PROJECT_ROOT/.env" 2>/dev/null; then + print_ok "MINIO_ENDPOINT is set" + else + print_info "MINIO_ENDPOINT not in .env (will use defaults)" + fi +else + print_error ".env file not found" + print_info "Copy from template: cp .env.example .env" + print_info "Then edit .env and set required values" +fi + +# ============================================================================ +# Check Port Availability +# ============================================================================ +print_header "Port Availability" + +check_port() { + local port=$1 + local service=$2 + + if command -v ss &> /dev/null; then + if ss -tuln | grep -q ":$port "; then + PROCESS=$(ss -tulnp 2>/dev/null | grep ":$port " | awk '{print $NF}' | head -1) + print_warn "Port $port ($service) is in use: $PROCESS" + else + print_ok "Port $port ($service) is available" + fi + elif command -v netstat &> /dev/null; then + if netstat -tuln | grep -q ":$port "; then + print_warn "Port $port ($service) is in use" + else + print_ok "Port $port ($service) is available" + fi + else + print_info "Cannot check port $port - ss/netstat not available" + fi +} + +check_port 8000 "Backend API" +check_port 3000 "Frontend Dev" +check_port 9000 "MinIO S3" +check_port 9001 "MinIO Console" + +# ============================================================================ +# Summary +# ============================================================================ +print_header "Summary" + +if [[ $ERRORS -eq 0 ]] && [[ $WARNINGS -eq 0 ]]; then + echo -e "${GREEN}All checks passed! Environment is ready.${NC}" + exit 0 +elif [[ $ERRORS -eq 0 ]]; then + echo -e "${YELLOW}$WARNINGS warning(s) found. Environment may work but review warnings above.${NC}" + exit 0 +else + echo -e "${RED}$ERRORS error(s) and $WARNINGS warning(s) found.${NC}" + echo -e "${RED}Please fix the errors above before starting development.${NC}" + exit 1 +fi diff --git a/openspec/changes/archive/2025-12-01-add-dev-scripts/proposal.md b/openspec/changes/archive/2025-12-01-add-dev-scripts/proposal.md new file mode 100644 index 0000000..095f3f0 --- /dev/null +++ b/openspec/changes/archive/2025-12-01-add-dev-scripts/proposal.md @@ -0,0 +1,28 @@ +# Change: Add Development Scripts + +## Why +Developers currently need to manually start multiple services (MinIO, backend, frontend) and verify environment prerequisites before running the application. This is error-prone and time-consuming. Automated scripts will streamline the development workflow and reduce onboarding friction. + +## What Changes +- **NEW**: Environment check script (`check-env.sh`) - Validates all prerequisites +- **NEW**: Unified development startup script (`start-dev.sh`) - Starts all services +- **NEW**: Stop script (`stop-dev.sh`) - Gracefully stops all services + +## Impact +- Affected specs: Creates new `dev-scripts` specification +- Affected code: + - Shell scripts in project root directory + - No changes to existing application code + +## Dependencies +- Existing docker-compose.minio.yml for MinIO +- Python virtual environment (venv/) +- Node.js and npm for frontend + +## Success Criteria +1. `check-env.sh` validates Python 3.10+, Node.js, Docker, required ports +2. `check-env.sh` provides clear error messages for missing prerequisites +3. `start-dev.sh` starts MinIO, backend, and frontend in correct order +4. `start-dev.sh` waits for each service to be healthy before proceeding +5. `stop-dev.sh` gracefully terminates all services +6. Scripts work on Linux/WSL environments diff --git a/openspec/changes/archive/2025-12-01-add-dev-scripts/specs/dev-scripts/spec.md b/openspec/changes/archive/2025-12-01-add-dev-scripts/specs/dev-scripts/spec.md new file mode 100644 index 0000000..44c1efb --- /dev/null +++ b/openspec/changes/archive/2025-12-01-add-dev-scripts/specs/dev-scripts/spec.md @@ -0,0 +1,124 @@ +# dev-scripts Specification + +## Purpose +Shell scripts to automate development environment setup, validation, and service orchestration for the Task Reporter system. + +## ADDED Requirements + +### Requirement: Environment Validation +The check-env script SHALL validate all prerequisites required to run the development environment. + +#### Scenario: Check Python version +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify Python 3.10 or higher is installed + - Display the detected Python version + - Exit with error if Python version is insufficient + +#### Scenario: Check Node.js and npm +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify Node.js is installed (v18+ recommended) + - Verify npm is available + - Display detected versions + +#### Scenario: Check Docker availability +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify Docker daemon is running + - Verify docker-compose is available + - Display Docker version + +#### Scenario: Check virtual environment +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify venv/ directory exists + - Suggest creation command if missing: `python -m venv venv` + +#### Scenario: Check environment file +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify .env file exists + - Suggest copying from .env.example if missing + - Warn if critical variables appear empty (FERNET_KEY) + +#### Scenario: Check port availability +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Check if ports 8000, 3000, 9000, 9001 are available + - Display which ports are in use and by what process + - Warn but continue if ports are occupied + +### Requirement: Development Server Startup +The start-dev script SHALL orchestrate the startup of all development services in the correct order. + +#### Scenario: Pre-flight validation +- **WHEN** the start-dev script runs +- **THEN** the system SHALL: + - Execute check-env.sh first + - Abort startup if critical checks fail + +#### Scenario: Start MinIO +- **WHEN** start-dev begins service startup +- **THEN** the system SHALL: + - Start MinIO using docker-compose -f docker-compose.minio.yml up -d + - Wait for MinIO health check to pass (up to 30 seconds) + - Display MinIO console URL (http://localhost:9001) + +#### Scenario: Start backend server +- **WHEN** MinIO is healthy +- **THEN** the system SHALL: + - Activate the virtual environment + - Install/update requirements if requirements.txt is newer than last install + - Start uvicorn in background: uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 + - Wait for backend to respond (up to 15 seconds) + - Display backend URL (http://localhost:8000) + +#### Scenario: Start frontend dev server +- **WHEN** backend is healthy +- **THEN** the system SHALL: + - Check if node_modules exists, run npm install if missing + - Start frontend dev server: npm run dev + - Display frontend URL (http://localhost:3000) + +#### Scenario: Display startup summary +- **WHEN** all services are running +- **THEN** the system SHALL: + - Display summary table with all service URLs + - Display log file locations + - Display instructions for stopping services + +#### Scenario: Handle graceful shutdown +- **WHEN** user presses Ctrl+C during startup or operation +- **THEN** the system SHALL: + - Trap the SIGINT signal + - Execute stop-dev.sh to clean up + - Display shutdown confirmation + +### Requirement: Development Server Shutdown +The stop-dev script SHALL gracefully terminate all development services. + +#### Scenario: Stop frontend server +- **WHEN** stop-dev script runs +- **THEN** the system SHALL: + - Find and terminate the Vite dev server process + - Confirm termination or report if not running + +#### Scenario: Stop backend server +- **WHEN** stop-dev script runs +- **THEN** the system SHALL: + - Find and terminate the uvicorn process + - Confirm termination or report if not running + +#### Scenario: Stop MinIO +- **WHEN** stop-dev script runs +- **THEN** the system SHALL: + - Run docker-compose -f docker-compose.minio.yml down + - Preserve data volumes (do not use -v flag) + - Confirm MinIO container stopped + +#### Scenario: Display shutdown summary +- **WHEN** all services are stopped +- **THEN** the system SHALL: + - Display confirmation message for each service + - Report any services that failed to stop diff --git a/openspec/changes/archive/2025-12-01-add-dev-scripts/tasks.md b/openspec/changes/archive/2025-12-01-add-dev-scripts/tasks.md new file mode 100644 index 0000000..966c1cf --- /dev/null +++ b/openspec/changes/archive/2025-12-01-add-dev-scripts/tasks.md @@ -0,0 +1,74 @@ +# Implementation Tasks + +## 1. Project Structure +- [x] 1.1 Scripts placed in project root directory + +## 2. Environment Check Script +- [x] 2.1 Create `check-env.sh` with executable permissions +- [x] 2.2 Implement Python version check (3.10+) +- [x] 2.3 Implement Node.js and npm check +- [x] 2.4 Implement Docker availability check +- [x] 2.5 Implement virtual environment check (venv/) +- [x] 2.6 Implement .env file check with template guidance +- [x] 2.7 Implement port availability check (8000, 3000, 9000, 9001) +- [x] 2.8 Add colored output and clear error messages + +## 3. Start Development Script +- [x] 3.1 Create `start-dev.sh` with executable permissions +- [x] 3.2 Call check-env.sh before starting services +- [x] 3.3 Start MinIO via docker-compose (with health check wait) +- [x] 3.4 Activate venv and start backend (uvicorn in background) +- [x] 3.5 Wait for backend to be healthy (curl localhost:8000/health or similar) +- [x] 3.6 Install frontend dependencies if node_modules missing +- [x] 3.7 Start frontend dev server (npm run dev in background) +- [x] 3.8 Display service URLs when all services are running +- [x] 3.9 Handle Ctrl+C to trigger graceful shutdown + +## 4. Stop Development Script +- [x] 4.1 Create `stop-dev.sh` with executable permissions +- [x] 4.2 Stop frontend dev server +- [x] 4.3 Stop backend uvicorn process +- [x] 4.4 Stop MinIO docker container +- [x] 4.5 Display confirmation messages + +## 5. Documentation +- [x] 5.1 Add usage instructions to scripts (--help flag) +- [x] 5.2 Update .env.example with any new required variables if needed + +## Summary + +**Completed:** All 18 tasks across 5 sections + +### Scripts Created (in project root) +``` +./check-env.sh # Environment validation +./start-dev.sh # Start all services +./stop-dev.sh # Stop all services +``` + +### Service Ports +| Service | Port | Description | +|----------|------|-------------| +| Backend | 8000 | FastAPI server | +| Frontend | 3000 | Vite dev server | +| MinIO S3 | 9000 | Object storage API | +| MinIO UI | 9001 | Admin console | + +### Usage + +```bash +# Check environment prerequisites +./check-env.sh + +# Start all services +./start-dev.sh + +# Stop all services +./stop-dev.sh + +# Start without MinIO (use external) +./start-dev.sh --no-minio + +# Stop but keep MinIO running +./stop-dev.sh --keep-minio +``` diff --git a/openspec/specs/dev-scripts/spec.md b/openspec/specs/dev-scripts/spec.md new file mode 100644 index 0000000..527a747 --- /dev/null +++ b/openspec/specs/dev-scripts/spec.md @@ -0,0 +1,123 @@ +# dev-scripts Specification + +## Purpose +TBD - created by archiving change add-dev-scripts. Update Purpose after archive. +## Requirements +### Requirement: Environment Validation +The check-env script SHALL validate all prerequisites required to run the development environment. + +#### Scenario: Check Python version +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify Python 3.10 or higher is installed + - Display the detected Python version + - Exit with error if Python version is insufficient + +#### Scenario: Check Node.js and npm +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify Node.js is installed (v18+ recommended) + - Verify npm is available + - Display detected versions + +#### Scenario: Check Docker availability +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify Docker daemon is running + - Verify docker-compose is available + - Display Docker version + +#### Scenario: Check virtual environment +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify venv/ directory exists + - Suggest creation command if missing: `python -m venv venv` + +#### Scenario: Check environment file +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Verify .env file exists + - Suggest copying from .env.example if missing + - Warn if critical variables appear empty (FERNET_KEY) + +#### Scenario: Check port availability +- **WHEN** the check-env script runs +- **THEN** the system SHALL: + - Check if ports 8000, 3000, 9000, 9001 are available + - Display which ports are in use and by what process + - Warn but continue if ports are occupied + +### Requirement: Development Server Startup +The start-dev script SHALL orchestrate the startup of all development services in the correct order. + +#### Scenario: Pre-flight validation +- **WHEN** the start-dev script runs +- **THEN** the system SHALL: + - Execute check-env.sh first + - Abort startup if critical checks fail + +#### Scenario: Start MinIO +- **WHEN** start-dev begins service startup +- **THEN** the system SHALL: + - Start MinIO using docker-compose -f docker-compose.minio.yml up -d + - Wait for MinIO health check to pass (up to 30 seconds) + - Display MinIO console URL (http://localhost:9001) + +#### Scenario: Start backend server +- **WHEN** MinIO is healthy +- **THEN** the system SHALL: + - Activate the virtual environment + - Install/update requirements if requirements.txt is newer than last install + - Start uvicorn in background: uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 + - Wait for backend to respond (up to 15 seconds) + - Display backend URL (http://localhost:8000) + +#### Scenario: Start frontend dev server +- **WHEN** backend is healthy +- **THEN** the system SHALL: + - Check if node_modules exists, run npm install if missing + - Start frontend dev server: npm run dev + - Display frontend URL (http://localhost:3000) + +#### Scenario: Display startup summary +- **WHEN** all services are running +- **THEN** the system SHALL: + - Display summary table with all service URLs + - Display log file locations + - Display instructions for stopping services + +#### Scenario: Handle graceful shutdown +- **WHEN** user presses Ctrl+C during startup or operation +- **THEN** the system SHALL: + - Trap the SIGINT signal + - Execute stop-dev.sh to clean up + - Display shutdown confirmation + +### Requirement: Development Server Shutdown +The stop-dev script SHALL gracefully terminate all development services. + +#### Scenario: Stop frontend server +- **WHEN** stop-dev script runs +- **THEN** the system SHALL: + - Find and terminate the Vite dev server process + - Confirm termination or report if not running + +#### Scenario: Stop backend server +- **WHEN** stop-dev script runs +- **THEN** the system SHALL: + - Find and terminate the uvicorn process + - Confirm termination or report if not running + +#### Scenario: Stop MinIO +- **WHEN** stop-dev script runs +- **THEN** the system SHALL: + - Run docker-compose -f docker-compose.minio.yml down + - Preserve data volumes (do not use -v flag) + - Confirm MinIO container stopped + +#### Scenario: Display shutdown summary +- **WHEN** all services are stopped +- **THEN** the system SHALL: + - Display confirmation message for each service + - Report any services that failed to stop + diff --git a/start-dev.sh b/start-dev.sh new file mode 100755 index 0000000..55c63b1 --- /dev/null +++ b/start-dev.sh @@ -0,0 +1,278 @@ +#!/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" + +# 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:9000 (API), http://localhost:9001 (Console)" + echo " - Backend (FastAPI) - http://localhost:8000" + echo " - Frontend (Vite) - http://localhost:3000" +} + +# 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:9000/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:9001 (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 8000 > "$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:8000/api/health > /dev/null 2>&1 || curl -s http://localhost:8000/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:8000" +print_info "API Docs: http://localhost:8000/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:3000" +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:3000" +echo -e " ${CYAN}Backend API:${NC} http://localhost:8000" +echo -e " ${CYAN}API Docs:${NC} http://localhost:8000/docs" +echo -e " ${CYAN}MinIO Console:${NC} http://localhost:9001" +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 diff --git a/stop-dev.sh b/stop-dev.sh new file mode 100755 index 0000000..e765c4f --- /dev/null +++ b/stop-dev.sh @@ -0,0 +1,193 @@ +#!/bin/bash +# ============================================================================ +# Development Server Stop Script for Task Reporter +# Gracefully stops all services: Frontend, Backend, MinIO +# ============================================================================ + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Script directory (scripts are in project root) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$SCRIPT_DIR" + +# PID file locations +PID_DIR="$PROJECT_ROOT/.pids" +BACKEND_PID_FILE="$PID_DIR/backend.pid" +FRONTEND_PID_FILE="$PID_DIR/frontend.pid" + +# 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 "${BLUE}[INFO]${NC} $1" +} + +# Show help +show_help() { + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Stops all development services for Task Reporter." + echo "" + echo "Options:" + echo " -h, --help Show this help message" + echo " --keep-minio Don't stop MinIO container" + echo " --keep-data Alias for --keep-minio" + echo "" + echo "Services stopped:" + echo " - Frontend (Vite dev server)" + echo " - Backend (uvicorn)" + echo " - MinIO (Docker container)" +} + +# Parse arguments +KEEP_MINIO=false + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + --keep-minio|--keep-data) + KEEP_MINIO=true + shift + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +echo -e "${BLUE}============================================${NC}" +echo -e "${BLUE} Task Reporter - Stopping Services${NC}" +echo -e "${BLUE}============================================${NC}" + +# ============================================================================ +# Stop Frontend +# ============================================================================ +print_header "Stopping Frontend" + +if [[ -f "$FRONTEND_PID_FILE" ]]; then + FRONTEND_PID=$(cat "$FRONTEND_PID_FILE") + if kill -0 "$FRONTEND_PID" 2>/dev/null; then + kill "$FRONTEND_PID" 2>/dev/null || true + # Also kill any child processes (npm spawns node) + pkill -P "$FRONTEND_PID" 2>/dev/null || true + sleep 1 + # Force kill if still running + if kill -0 "$FRONTEND_PID" 2>/dev/null; then + kill -9 "$FRONTEND_PID" 2>/dev/null || true + fi + print_ok "Frontend stopped (was PID: $FRONTEND_PID)" + else + print_info "Frontend was not running" + fi + rm -f "$FRONTEND_PID_FILE" +else + # Try to find and kill vite process + VITE_PID=$(pgrep -f "vite.*frontend" 2>/dev/null | head -1) + if [[ -n "$VITE_PID" ]]; then + kill "$VITE_PID" 2>/dev/null || true + print_ok "Frontend stopped (found PID: $VITE_PID)" + else + print_info "Frontend was not running" + fi +fi + +# ============================================================================ +# Stop Backend +# ============================================================================ +print_header "Stopping Backend" + +if [[ -f "$BACKEND_PID_FILE" ]]; then + BACKEND_PID=$(cat "$BACKEND_PID_FILE") + if kill -0 "$BACKEND_PID" 2>/dev/null; then + kill "$BACKEND_PID" 2>/dev/null || true + sleep 1 + # Force kill if still running + if kill -0 "$BACKEND_PID" 2>/dev/null; then + kill -9 "$BACKEND_PID" 2>/dev/null || true + fi + print_ok "Backend stopped (was PID: $BACKEND_PID)" + else + print_info "Backend was not running" + fi + rm -f "$BACKEND_PID_FILE" +else + # Try to find and kill uvicorn process + UVICORN_PID=$(pgrep -f "uvicorn app.main:app" 2>/dev/null | head -1) + if [[ -n "$UVICORN_PID" ]]; then + kill "$UVICORN_PID" 2>/dev/null || true + print_ok "Backend stopped (found PID: $UVICORN_PID)" + else + print_info "Backend was not running" + fi +fi + +# ============================================================================ +# Stop MinIO +# ============================================================================ +if [[ "$KEEP_MINIO" == "false" ]]; then + print_header "Stopping MinIO" + + cd "$PROJECT_ROOT" + + if docker ps --format '{{.Names}}' | grep -q "task-reporter-minio"; then + if command -v docker-compose &> /dev/null; then + docker-compose -f docker-compose.minio.yml down + else + docker compose -f docker-compose.minio.yml down + fi + print_ok "MinIO stopped (data preserved)" + else + print_info "MinIO was not running" + fi +else + print_header "MinIO" + print_info "Keeping MinIO running (--keep-minio)" +fi + +# ============================================================================ +# Cleanup +# ============================================================================ +print_header "Cleanup" + +# Remove PID directory if empty +if [[ -d "$PID_DIR" ]] && [[ -z "$(ls -A "$PID_DIR")" ]]; then + rmdir "$PID_DIR" + print_ok "Cleaned up PID directory" +fi + +# ============================================================================ +# Summary +# ============================================================================ +print_header "Summary" + +echo -e "${GREEN}All services have been stopped.${NC}" +echo "" +if [[ "$KEEP_MINIO" == "true" ]]; then + echo -e " ${YELLOW}Note:${NC} MinIO is still running (use without --keep-minio to stop)" +fi +echo -e " ${BLUE}Tip:${NC} Run ./scripts/start-dev.sh to start services again" +echo ""