#!/bin/bash set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration CONFIG_FILE="${CONFIG_FILE:-config.e2e.yaml}" LOG_DIR="./tests/logs" PID_DIR="./tests/pids" # Detect database schema from config file if possible DETECTED_SCHEMA="" if [ -f "$CONFIG_FILE" ]; then DETECTED_SCHEMA=$(grep -E '^\s*schema:' "$CONFIG_FILE" | sed -E 's/^\s*schema:\s*"?([^"]+)"?.*/\1/' | tr -d ' ') fi # Service ports (from config.e2e.yaml) API_PORT=8080 NOTIFIER_WS_PORT=8081 echo -e "${GREEN}=== Attune E2E Services Startup ===${NC}\n" # Display configuration info echo -e "${BLUE}Configuration:${NC}" echo -e " • Config file: ${YELLOW}$CONFIG_FILE${NC}" if [ -n "$DETECTED_SCHEMA" ]; then echo -e " • Database schema: ${YELLOW}$DETECTED_SCHEMA${NC}" else echo -e " • Database schema: ${YELLOW}attune${NC} (default)" fi echo "" # Create necessary directories mkdir -p "$LOG_DIR" mkdir -p "$PID_DIR" mkdir -p "./tests/artifacts" mkdir -p "./tests/venvs" # Function to check if a service is running is_service_running() { local pid_file="$PID_DIR/$1.pid" if [ -f "$pid_file" ]; then local pid=$(cat "$pid_file") if ps -p $pid > /dev/null 2>&1; then return 0 else rm -f "$pid_file" return 1 fi fi return 1 } # Function to stop a service stop_service() { local service_name=$1 local pid_file="$PID_DIR/$service_name.pid" if [ -f "$pid_file" ]; then local pid=$(cat "$pid_file") echo -e "${YELLOW}→${NC} Stopping $service_name (PID: $pid)..." kill $pid 2>/dev/null || true sleep 2 if ps -p $pid > /dev/null 2>&1; then echo -e "${YELLOW}!${NC} Forcefully killing $service_name..." kill -9 $pid 2>/dev/null || true fi rm -f "$pid_file" echo -e "${GREEN}✓${NC} $service_name stopped" fi } # Function to start a service start_service() { local service_name=$1 local binary_name=$2 local log_file="$LOG_DIR/$service_name.log" local pid_file="$PID_DIR/$service_name.pid" echo -e "${YELLOW}→${NC} Starting $service_name..." # Build the service if not already built if [ ! -f "./target/debug/$binary_name" ]; then echo -e "${BLUE} Building $binary_name...${NC}" cargo build --bin $binary_name 2>&1 | tee "$LOG_DIR/$service_name-build.log" fi # Start the service # Only set ATTUNE__ENVIRONMENT if using default e2e config # Otherwise, let the config file determine the environment if [ "$CONFIG_FILE" = "config.e2e.yaml" ]; then ATTUNE__ENVIRONMENT=e2e ATTUNE_CONFIG="$CONFIG_FILE" ./target/debug/$binary_name > "$log_file" 2>&1 & else ATTUNE_CONFIG="$CONFIG_FILE" ./target/debug/$binary_name > "$log_file" 2>&1 & fi local pid=$! echo $pid > "$pid_file" # Wait a moment and check if it's still running sleep 2 if ps -p $pid > /dev/null 2>&1; then echo -e "${GREEN}✓${NC} $service_name started (PID: $pid)" echo -e " Log: ${BLUE}$log_file${NC}" return 0 else echo -e "${RED}✗${NC} $service_name failed to start" echo -e " Check log: ${RED}$log_file${NC}" tail -20 "$log_file" return 1 fi } # Function to check service health check_service_health() { local service_name=$1 local health_url=$2 local max_attempts=${3:-30} local attempt=0 echo -e "${YELLOW}→${NC} Checking $service_name health..." while [ $attempt -lt $max_attempts ]; do if curl -s -f "$health_url" > /dev/null 2>&1; then echo -e "${GREEN}✓${NC} $service_name is healthy" return 0 fi attempt=$((attempt + 1)) sleep 1 done echo -e "${RED}✗${NC} $service_name health check failed after $max_attempts attempts" return 1 } # Check for existing services and stop them echo -e "${YELLOW}Checking for running E2E services...${NC}" for service in api executor worker sensor notifier; do if is_service_running $service; then stop_service $service fi done echo "" # Check dependencies echo -e "${YELLOW}Checking dependencies...${NC}" # Check PostgreSQL echo -e "${YELLOW}→${NC} Checking PostgreSQL..." echo -e " Attempting connection to: ${BLUE}postgresql://postgres@localhost:5432/attune_e2e${NC}" PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d attune_e2e -c '\q' 2>/tmp/pg_check_error.txt PG_EXIT=$? if [ $PG_EXIT -eq 0 ]; then echo -e "${GREEN}✓${NC} PostgreSQL connection successful" else echo -e "${RED}✗${NC} Cannot connect to PostgreSQL database 'attune_e2e'" echo "" echo -e "${YELLOW}Diagnostic Information:${NC}" # Check if PostgreSQL is running at all if ! pg_isready -h localhost -p 5432 > /dev/null 2>&1; then echo -e " ${RED}✗${NC} PostgreSQL server is not running on localhost:5432" echo -e " Start it with: ${YELLOW}sudo systemctl start postgresql${NC}" else echo -e " ${GREEN}✓${NC} PostgreSQL server is running" # Check if the database exists if ! PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -lqt 2>/dev/null | cut -d \| -f 1 | grep -qw attune_e2e; then echo -e " ${RED}✗${NC} Database 'attune_e2e' does not exist" echo -e " Create it with: ${YELLOW}./scripts/setup-e2e-db.sh${NC}" else echo -e " ${GREEN}✓${NC} Database 'attune_e2e' exists" echo -e " ${RED}✗${NC} Connection failed for another reason" # Show the actual error if [ -f /tmp/pg_check_error.txt ] && [ -s /tmp/pg_check_error.txt ]; then echo -e "\n${YELLOW}Error details:${NC}" cat /tmp/pg_check_error.txt | sed 's/^/ /' fi fi fi rm -f /tmp/pg_check_error.txt exit 1 fi # Check RabbitMQ echo -e "${YELLOW}→${NC} Checking RabbitMQ..." echo -e " Testing connection to: ${BLUE}localhost:5672 (AMQP)${NC}" if nc -z localhost 5672 2>/dev/null || timeout 1 bash -c 'cat < /dev/null > /dev/tcp/localhost/5672' 2>/dev/null; then echo -e "${GREEN}✓${NC} RabbitMQ is running (AMQP port 5672)" else echo -e "${RED}✗${NC} RabbitMQ is not running on port 5672" echo "" echo -e "${YELLOW}Diagnostic Information:${NC}" # Check if RabbitMQ process is running if pgrep -x rabbitmq-server > /dev/null || pgrep -x beam.smp > /dev/null; then echo -e " ${YELLOW}!${NC} RabbitMQ process is running but port 5672 is not accessible" echo -e " The service may still be starting up" echo -e " Check status: ${YELLOW}sudo rabbitmq-diagnostics status${NC}" echo -e " View logs: ${YELLOW}sudo journalctl -u rabbitmq-server -n 50${NC}" else echo -e " ${RED}✗${NC} RabbitMQ process is not running" echo -e " Start it with: ${YELLOW}sudo systemctl start rabbitmq-server${NC}" echo -e " Or: ${YELLOW}sudo service rabbitmq-server start${NC}" fi # Check if port might be in use by something else if netstat -tuln 2>/dev/null | grep -q :5672 || ss -tuln 2>/dev/null | grep -q :5672; then echo -e " ${YELLOW}!${NC} Port 5672 appears to be in use" echo -e " Check what's using it: ${YELLOW}sudo lsof -i :5672${NC}" fi exit 1 fi echo "" # Build all services first echo -e "${YELLOW}Building all services...${NC}" echo -e " Building binaries: ${BLUE}api, executor, worker, sensor, notifier${NC}" echo -e " This may take a few moments..." cargo build --bins 2>&1 | tee "$LOG_DIR/build.log" BUILD_EXIT=${PIPESTATUS[0]} if [ $BUILD_EXIT -ne 0 ]; then echo -e "${RED}✗${NC} Build failed" echo "" echo -e "${YELLOW}Last 30 lines of build output:${NC}" tail -30 "$LOG_DIR/build.log" | sed 's/^/ /' echo "" echo -e "Full build log: ${RED}$LOG_DIR/build.log${NC}" exit 1 fi echo -e "${GREEN}✓${NC} All services built successfully\n" # Start services in order echo -e "${GREEN}=== Starting Services ===${NC}\n" # 1. Start API service if ! start_service "api" "attune-api"; then echo -e "${RED}Failed to start API service${NC}" exit 1 fi sleep 2 # Check API health if ! check_service_health "API" "http://127.0.0.1:$API_PORT/health"; then echo -e "${RED}API service is not healthy${NC}" echo "" echo -e "${YELLOW}Last 20 lines of API log:${NC}" tail -20 "$LOG_DIR/api.log" | sed 's/^/ /' echo "" echo -e "Full log: ${RED}$LOG_DIR/api.log${NC}" exit 1 fi echo "" # 2. Start Executor service if ! start_service "executor" "attune-executor"; then echo -e "${RED}Failed to start Executor service${NC}" echo "" echo -e "${YELLOW}Last 20 lines of Executor log:${NC}" tail -20 "$LOG_DIR/executor.log" | sed 's/^/ /' echo "" echo -e "Full log: ${RED}$LOG_DIR/executor.log${NC}" exit 1 fi sleep 2 echo "" # 3. Start Worker service if ! start_service "worker" "attune-worker"; then echo -e "${RED}Failed to start Worker service${NC}" echo "" echo -e "${YELLOW}Last 20 lines of Worker log:${NC}" tail -20 "$LOG_DIR/worker.log" | sed 's/^/ /' echo "" echo -e "Full log: ${RED}$LOG_DIR/worker.log${NC}" exit 1 fi sleep 2 echo "" # 4. Start Sensor service if ! start_service "sensor" "attune-sensor"; then echo -e "${RED}Failed to start Sensor service${NC}" echo "" echo -e "${YELLOW}Last 20 lines of Sensor log:${NC}" tail -20 "$LOG_DIR/sensor.log" | sed 's/^/ /' echo "" echo -e "Full log: ${RED}$LOG_DIR/sensor.log${NC}" exit 1 fi sleep 2 echo "" # 5. Start Notifier service if ! start_service "notifier" "attune-notifier"; then echo -e "${RED}Failed to start Notifier service${NC}" echo "" echo -e "${YELLOW}Last 20 lines of Notifier log:${NC}" tail -20 "$LOG_DIR/notifier.log" | sed 's/^/ /' echo "" echo -e "Full log: ${RED}$LOG_DIR/notifier.log${NC}" exit 1 fi sleep 2 echo "" # Display running services echo -e "${GREEN}=== All Services Started ===${NC}\n" echo -e "${GREEN}Running Services:${NC}" for service in api executor worker sensor notifier; do pid_file="$PID_DIR/$service.pid" if [ -f "$pid_file" ]; then pid=$(cat "$pid_file") echo -e " • ${GREEN}$service${NC} (PID: $pid)" fi done echo -e "\n${GREEN}Service Endpoints:${NC}" echo -e " • API: ${BLUE}http://127.0.0.1:$API_PORT${NC}" echo -e " • Health: ${BLUE}http://127.0.0.1:$API_PORT/health${NC}" echo -e " • Docs: ${BLUE}http://127.0.0.1:$API_PORT/docs${NC}" echo -e " • WebSocket: ${BLUE}ws://127.0.0.1:$NOTIFIER_WS_PORT${NC}" echo -e "\n${GREEN}Logs:${NC}" for service in api executor worker sensor notifier; do echo -e " • $service: ${BLUE}$LOG_DIR/$service.log${NC}" done echo -e "\n${GREEN}Management:${NC}" echo -e " • View logs: ${YELLOW}tail -f $LOG_DIR/.log${NC}" echo -e " • Stop all: ${YELLOW}./scripts/stop-e2e-services.sh${NC}" echo -e " • Run tests: ${YELLOW}cargo test --test integration${NC}" echo -e "\n${GREEN}Test User:${NC}" echo -e " • Login: ${YELLOW}test@attune.local${NC}" echo -e " • Password: ${YELLOW}TestPass123!${NC}" echo -e "\n${GREEN}Quick Test:${NC}" echo -e " ${YELLOW}curl http://127.0.0.1:$API_PORT/health" echo -e " ${YELLOW}curl -X POST http://127.0.0.1:$API_PORT/auth/login \\" echo -e " ${YELLOW} -H 'Content-Type: application/json' \\" echo -e " ${YELLOW} -d '{\"login\":\"test@attune.local\",\"password\":\"TestPass123!\"}'${NC}" echo ""