Files
managing-apps/scripts/vibe-kanban/cleanup-api-workers.sh
cryptooda ab08e0241b Update Vibe Kanban setup and scripts
- Added new entries to .gitignore for environment files and dynamically generated Docker Compose files.
- Updated documentation to reflect the new path for the Vibe Kanban dev server script.
- Enhanced task composition scripts to extract TASK_SLOT from TASK_ID, ensuring unique Orleans ports and preventing conflicts.
- Removed the old vibe-dev-server script, consolidating functionality into the new structure.
2025-12-31 04:36:20 +07:00

362 lines
14 KiB
Bash
Executable File

#!/bin/bash
# scripts/vibe-kanban/cleanup-api-workers.sh
# Cleanup script for Vibe Kanban - stops API and Workers processes only
# Usage: bash scripts/vibe-kanban/cleanup-api-workers.sh <TASK_ID>
TASK_ID=$1
# Detect worktree root (similar to vibe-setup.sh)
WORKTREE_ROOT="$(pwd)"
# Check if we're in a nested structure (Vibe Kanban worktree)
if [ -d "$WORKTREE_ROOT/managing-apps" ] && [ -d "$WORKTREE_ROOT/managing-apps/src/Managing.Api" ]; then
WORKTREE_PROJECT_ROOT="$WORKTREE_ROOT/managing-apps"
elif [ -d "$WORKTREE_ROOT/src/Managing.Api" ]; then
WORKTREE_PROJECT_ROOT="$WORKTREE_ROOT"
else
WORKTREE_PROJECT_ROOT=""
fi
# Determine project root
if [ -n "$VIBE_WORKTREE_ROOT" ] && [ -d "$VIBE_WORKTREE_ROOT/src/Managing.Api" ]; then
PROJECT_ROOT="$VIBE_WORKTREE_ROOT"
WORKTREE_PROJECT_ROOT="$VIBE_WORKTREE_ROOT"
echo "📁 Using Vibe Kanban worktree: $PROJECT_ROOT"
elif [ -n "$WORKTREE_PROJECT_ROOT" ]; then
PROJECT_ROOT="$WORKTREE_PROJECT_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
# TASK_ID file to ensure consistency (same as vibe-setup.sh)
TASK_ID_FILE="$WORKTREE_PROJECT_ROOT/.vibe-task-id"
# Try to get TASK_ID from various sources
if [ -z "$TASK_ID" ]; then
# First, check if we have a stored TASK_ID for this worktree (ensures consistency)
if [ -n "$WORKTREE_PROJECT_ROOT" ] && [ -f "$TASK_ID_FILE" ]; then
STORED_TASK_ID=$(cat "$TASK_ID_FILE" 2>/dev/null | tr -d '[:space:]')
if [ -n "$STORED_TASK_ID" ]; then
TASK_ID="$STORED_TASK_ID"
echo "📋 Using stored TASK_ID from .vibe-task-id: $TASK_ID"
fi
fi
# Try environment variables (Vibe Kanban might set these)
if [ -z "$TASK_ID" ]; then
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
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)
WORKTREE_PATH_TO_CHECK="$WORKTREE_ROOT"
if [ -z "$WORKTREE_PATH_TO_CHECK" ] && [ -n "$VIBE_WORKTREE_ROOT" ]; then
WORKTREE_PATH_TO_CHECK="$VIBE_WORKTREE_ROOT"
fi
if [ -n "$WORKTREE_PATH_TO_CHECK" ]; then
# Try UUID format first (Vibe Kanban might use UUIDs)
DETECTED_TASK=$(echo "$WORKTREE_PATH_TO_CHECK" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | head -1)
# If no UUID, try task ID pattern (e.g., DEV-123, TASK-456)
if [ -z "$DETECTED_TASK" ]; then
DETECTED_TASK=$(echo "$WORKTREE_PATH_TO_CHECK" | grep -oE '[A-Z]+-[0-9]+' | head -1)
fi
# If still no match, try to get the last directory name (might be task name)
if [ -z "$DETECTED_TASK" ]; then
LAST_DIR=$(basename "$WORKTREE_PATH_TO_CHECK")
# Skip common directory names
if [ "$LAST_DIR" != "managing-apps" ] && [ "$LAST_DIR" != "worktrees" ] && [ "$LAST_DIR" != "Projects" ]; then
# Generate a numeric ID from the directory name (hash-based for consistency)
HASH=$(echo -n "$LAST_DIR" | shasum -a 256 | cut -d' ' -f1 | head -c 8)
NUMERIC_ID=$((0x$HASH % 9999 + 1))
DETECTED_TASK="TASK-$NUMERIC_ID"
echo "📋 Generated numeric TASK_ID from worktree directory '$LAST_DIR': $DETECTED_TASK"
fi
fi
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 "$WORKTREE_PROJECT_ROOT" ]; then
PID_DIR_CHECK="$WORKTREE_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 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)"
# Try UUID format first
DETECTED_TASK=$(echo "$CURRENT_DIR" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | head -1)
# If no UUID, try task ID pattern
if [ -z "$DETECTED_TASK" ]; then
DETECTED_TASK=$(echo "$CURRENT_DIR" | grep -oE '[A-Z]+-[0-9]+' | head -1)
fi
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 <TASK_ID>"
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 " WORKTREE_ROOT: ${WORKTREE_ROOT:-not set}"
echo " WORKTREE_PROJECT_ROOT: ${WORKTREE_PROJECT_ROOT:-not set}"
echo " VIBE_WORKTREE_ROOT: ${VIBE_WORKTREE_ROOT:-not set}"
echo " PROJECT_ROOT: $PROJECT_ROOT"
if [ -n "$WORKTREE_PROJECT_ROOT" ]; then
echo " TASK_ID_FILE: $TASK_ID_FILE"
if [ -f "$TASK_ID_FILE" ]; then
echo " Stored TASK_ID: $(cat "$TASK_ID_FILE" 2>/dev/null | tr -d '[:space:]')"
else
echo " TASK_ID_FILE: (not found)"
fi
fi
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 <TASK_ID>"
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"