#!/bin/bash # scripts/cleanup-api-workers.sh # Cleanup script for Vibe Kanban - stops API and Workers processes only # Usage: bash scripts/cleanup-api-workers.sh TASK_ID=$1 # Try to get TASK_ID from various sources if [ -z "$TASK_ID" ]; then # Try environment variables (Vibe Kanban might set these) if [ -n "$VIBE_TASK_ID" ]; then TASK_ID="$VIBE_TASK_ID" echo "๐Ÿ“‹ Found TASK_ID from VIBE_TASK_ID: $TASK_ID" elif [ -n "$TASK_ID_ENV" ]; then TASK_ID="$TASK_ID_ENV" echo "๐Ÿ“‹ Found TASK_ID from TASK_ID_ENV: $TASK_ID" elif [ -n "$TASK" ]; then TASK_ID="$TASK" echo "๐Ÿ“‹ Found TASK_ID from TASK: $TASK_ID" fi fi # Determine project root if [ -n "$VIBE_WORKTREE_ROOT" ] && [ -d "$VIBE_WORKTREE_ROOT/src/Managing.Api" ]; then PROJECT_ROOT="$VIBE_WORKTREE_ROOT" echo "๐Ÿ“ Using Vibe Kanban worktree: $PROJECT_ROOT" elif [ -d "$(pwd)/scripts" ] && [ -f "$(pwd)/scripts/start-api-and-workers.sh" ]; then PROJECT_ROOT="$(pwd)" echo "๐Ÿ“ Using current directory: $PROJECT_ROOT" else # Try to find main repo MAIN_REPO="/Users/oda/Desktop/Projects/managing-apps" if [ -d "$MAIN_REPO/scripts" ]; then PROJECT_ROOT="$MAIN_REPO" echo "๐Ÿ“ Using main repository: $PROJECT_ROOT" else echo "โŒ Error: Cannot find project root" exit 1 fi fi # If TASK_ID still not found, try to detect from worktree path or PID files if [ -z "$TASK_ID" ]; then # Try to extract from worktree path (Vibe Kanban worktrees often contain task ID) if [ -n "$VIBE_WORKTREE_ROOT" ]; then WORKTREE_PATH="$VIBE_WORKTREE_ROOT" # Try to extract task ID from path (e.g., /path/to/worktrees/TASK-123/...) DETECTED_TASK=$(echo "$WORKTREE_PATH" | grep -oE '[A-Z]+-[0-9]+' | head -1) if [ -n "$DETECTED_TASK" ]; then TASK_ID="$DETECTED_TASK" echo "๐Ÿ“‹ Detected TASK_ID from worktree path: $TASK_ID" fi fi # Try to find from PID files in worktree if [ -z "$TASK_ID" ] && [ -n "$VIBE_WORKTREE_ROOT" ]; then PID_DIR_CHECK="$VIBE_WORKTREE_ROOT/.task-pids" if [ -d "$PID_DIR_CHECK" ]; then # Find the most recent PID file with a running process for pid_file in $(ls -t "$PID_DIR_CHECK"/*.pid 2>/dev/null); do pid=$(cat "$pid_file" 2>/dev/null | tr -d '[:space:]') if [ -n "$pid" ] && ps -p "$pid" > /dev/null 2>&1; then # Extract task ID from filename (e.g., api-DEV-123.pid -> DEV-123) DETECTED_TASK=$(basename "$pid_file" .pid | sed 's/^api-//; s/^workers-//') if [ -n "$DETECTED_TASK" ]; then TASK_ID="$DETECTED_TASK" echo "๐Ÿ“‹ Detected TASK_ID from running process PID file: $TASK_ID" break fi fi done fi fi # Try to find from PID files in main repo if still not found if [ -z "$TASK_ID" ]; then PID_DIR_CHECK="$PROJECT_ROOT/.task-pids" if [ -d "$PID_DIR_CHECK" ]; then # Find the most recent PID file with a running process for pid_file in $(ls -t "$PID_DIR_CHECK"/*.pid 2>/dev/null); do pid=$(cat "$pid_file" 2>/dev/null | tr -d '[:space:]') if [ -n "$pid" ] && ps -p "$pid" > /dev/null 2>&1; then # Extract task ID from filename (e.g., api-DEV-123.pid -> DEV-123) DETECTED_TASK=$(basename "$pid_file" .pid | sed 's/^api-//; s/^workers-//') if [ -n "$DETECTED_TASK" ]; then TASK_ID="$DETECTED_TASK" echo "๐Ÿ“‹ Detected TASK_ID from running process PID file: $TASK_ID" break fi fi done fi fi # Try to find from current directory if it's a worktree if [ -z "$TASK_ID" ]; then CURRENT_DIR="$(pwd)" DETECTED_TASK=$(echo "$CURRENT_DIR" | grep -oE '[A-Z]+-[0-9]+' | head -1) if [ -n "$DETECTED_TASK" ]; then TASK_ID="$DETECTED_TASK" echo "๐Ÿ“‹ Detected TASK_ID from current directory: $TASK_ID" fi fi fi PID_DIR="$PROJECT_ROOT/.task-pids" API_PID_FILE="$PID_DIR/api-${TASK_ID}.pid" WORKERS_PID_FILE="$PID_DIR/workers-${TASK_ID}.pid" if [ -z "$TASK_ID" ]; then echo "" echo "โŒ Error: TASK_ID is required but could not be determined" echo "" echo "๐Ÿ’ก Usage: $0 " echo "๐Ÿ’ก Or set one of these environment variables:" echo " - VIBE_TASK_ID" echo " - TASK_ID_ENV" echo " - TASK" echo "" echo "๐Ÿ’ก Or ensure you're running from a Vibe Kanban worktree with task ID in the path" echo "" echo "๐Ÿ” Debug information:" echo " Current directory: $(pwd)" echo " VIBE_WORKTREE_ROOT: ${VIBE_WORKTREE_ROOT:-not set}" echo " PROJECT_ROOT: $PROJECT_ROOT" if [ -d "$PID_DIR" ]; then echo " Available PID files in $PID_DIR:" ls -1 "$PID_DIR"/*.pid 2>/dev/null | head -5 | while read file; do pid=$(cat "$file" 2>/dev/null | tr -d '[:space:]') task=$(basename "$file" .pid | sed 's/^api-//; s/^workers-//') if [ -n "$pid" ] && ps -p "$pid" > /dev/null 2>&1; then echo " โœ… $file (PID: $pid, Task: $task) - RUNNING" else echo " โš ๏ธ $file (PID: $pid, Task: $task) - not running" fi done || echo " (none found)" fi echo "" echo "๐Ÿ’ก To clean up a specific task, run:" echo " $0 " echo "" echo "๐Ÿ’ก Or set VIBE_TASK_ID environment variable before running the script" exit 1 fi echo "๐Ÿงน Cleaning up API and Workers for task: $TASK_ID" echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" # Function to kill process and its children kill_process_tree() { local pid=$1 local name=$2 if [ -z "$pid" ] || [ "$pid" = "0" ]; then return 0 fi if ! ps -p "$pid" > /dev/null 2>&1; then return 0 fi echo " ๐Ÿ›‘ Stopping $name (PID: $pid)..." # First, try graceful shutdown kill "$pid" 2>/dev/null || true sleep 2 # Check if still running if ps -p "$pid" > /dev/null 2>&1; then echo " โš ๏ธ Process still running, force killing..." kill -9 "$pid" 2>/dev/null || true sleep 1 fi # Kill any child processes local child_pids=$(pgrep -P "$pid" 2>/dev/null) if [ -n "$child_pids" ]; then for child_pid in $child_pids; do echo " ๐Ÿ›‘ Stopping child process (PID: $child_pid)..." kill "$child_pid" 2>/dev/null || true sleep 1 if ps -p "$child_pid" > /dev/null 2>&1; then kill -9 "$child_pid" 2>/dev/null || true fi done fi # Verify process is stopped if ps -p "$pid" > /dev/null 2>&1; then echo " โš ๏ธ Warning: Process $pid may still be running" return 1 else echo " โœ… $name stopped" return 0 fi } # Function to find and kill orphaned processes by name kill_orphaned_processes() { local task_id=$1 local process_name=$2 local found_any=false # Find processes that match the executable name and worktree path local processes=$(ps aux | grep "$process_name" | grep -v grep | grep -E "worktree|$task_id" || true) if [ -n "$processes" ]; then echo " ๐Ÿ” Found orphaned $process_name processes:" echo "$processes" | while read line; do local pid=$(echo "$line" | awk '{print $2}') if [ -n "$pid" ] && ps -p "$pid" > /dev/null 2>&1; then echo " ๐Ÿ›‘ Killing orphaned process (PID: $pid)..." kill "$pid" 2>/dev/null || true sleep 1 if ps -p "$pid" > /dev/null 2>&1; then kill -9 "$pid" 2>/dev/null || true fi found_any=true fi done fi } # Stop API process echo "๐Ÿ“Š Stopping API process..." if [ -f "$API_PID_FILE" ]; then API_PID=$(cat "$API_PID_FILE" 2>/dev/null | tr -d '[:space:]') if [ -n "$API_PID" ] && [ "$API_PID" != "0" ]; then kill_process_tree "$API_PID" "API" else echo " โš ๏ธ Invalid PID in file: $API_PID_FILE" fi rm -f "$API_PID_FILE" else echo " โš ๏ธ API PID file not found: $API_PID_FILE" fi # Kill orphaned Managing.Api processes kill_orphaned_processes "$TASK_ID" "Managing.Api" # Stop Workers process echo "" echo "๐Ÿ“Š Stopping Workers process..." if [ -f "$WORKERS_PID_FILE" ]; then WORKERS_PID=$(cat "$WORKERS_PID_FILE" 2>/dev/null | tr -d '[:space:]') if [ -n "$WORKERS_PID" ] && [ "$WORKERS_PID" != "0" ]; then kill_process_tree "$WORKERS_PID" "Workers" else echo " โš ๏ธ Invalid PID in file: $WORKERS_PID_FILE" fi rm -f "$WORKERS_PID_FILE" else echo " โš ๏ธ Workers PID file not found: $WORKERS_PID_FILE" fi # Kill orphaned Managing.Workers processes kill_orphaned_processes "$TASK_ID" "Managing.Workers" # Kill orphaned dotnet run processes that might be related echo "" echo "๐Ÿ“Š Checking for orphaned dotnet run processes..." DOTNET_RUN_PIDS=$(ps aux | grep "dotnet run" | grep -v grep | awk '{print $2}' || true) if [ -n "$DOTNET_RUN_PIDS" ]; then for pid in $DOTNET_RUN_PIDS; do # Check if this dotnet run is a parent of Managing.Api or Managing.Workers local has_api_child=$(pgrep -P "$pid" | xargs ps -p 2>/dev/null | grep -c "Managing.Api" || echo "0") local has_workers_child=$(pgrep -P "$pid" | xargs ps -p 2>/dev/null | grep -c "Managing.Workers" || echo "0") if [ "$has_api_child" != "0" ] || [ "$has_workers_child" != "0" ]; then echo " ๐Ÿ›‘ Killing orphaned dotnet run process (PID: $pid)..." kill "$pid" 2>/dev/null || true sleep 1 if ps -p "$pid" > /dev/null 2>&1; then kill -9 "$pid" 2>/dev/null || true fi fi done fi # Clean up log files (optional - comment out if you want to keep logs) # echo "" # echo "๐Ÿ“Š Cleaning up log files..." # rm -f "$PID_DIR/api-${TASK_ID}.log" "$PID_DIR/workers-${TASK_ID}.log" 2>/dev/null || true echo "" echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" echo "โœ… Cleanup complete for task: $TASK_ID" echo "" echo "๐Ÿ’ก Note: Log files are preserved in: $PID_DIR" echo "๐Ÿ’ก To remove log files, uncomment the cleanup section in the script"