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.
This commit is contained in:
40
.cursor/commands/vibe-kanban.md
Normal file
40
.cursor/commands/vibe-kanban.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# vibe-kanban
|
||||||
|
|
||||||
|
Quick reference for Vibe Kanban MCP interactions.
|
||||||
|
|
||||||
|
## Available Projects
|
||||||
|
|
||||||
|
- `gmx-interface`: 574c1123-facf-4a8d-a6dd-1789db369fbf
|
||||||
|
- `kaigen-web`: cd0907b5-0933-4f6c-9516-aac4d5d360bc
|
||||||
|
- `managing-apps`: 1a4fdbff-8b23-49d5-9953-2476846cbcc2
|
||||||
|
|
||||||
|
## Common Operations
|
||||||
|
|
||||||
|
### List Tasks
|
||||||
|
List all tasks in a project:
|
||||||
|
- Use `list_tasks` with `project_id: "1a4fdbff-8b23-49d5-9953-2476846cbcc2"` for managing-apps
|
||||||
|
|
||||||
|
### Create Task
|
||||||
|
Create new task:
|
||||||
|
- Use `create_task` with `project_id` and `title` (description optional)
|
||||||
|
|
||||||
|
### Update Task
|
||||||
|
Update task status/title/description:
|
||||||
|
- Use `update_task` with `task_id` and optional `status`, `title`, `description`
|
||||||
|
- Statuses: `todo`, `inprogress`, `inreview`, `done`, `cancelled`
|
||||||
|
|
||||||
|
### Get Task Details
|
||||||
|
Get full task info:
|
||||||
|
- Use `get_task` with `task_id`
|
||||||
|
|
||||||
|
### Delete Task
|
||||||
|
Remove task:
|
||||||
|
- Use `delete_task` with `task_id`
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Always pass `project_id` or `task_id` where required
|
||||||
|
- Use `list_projects` to get project IDs
|
||||||
|
- Use `list_tasks` to get task IDs
|
||||||
|
- See `docs/VIBE_KANBAN_QUICK_START.md` for full documentation
|
||||||
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -395,3 +395,9 @@ scripts/privy/privy-users.csv
|
|||||||
.vibe-kanban/*.sqlite
|
.vibe-kanban/*.sqlite
|
||||||
# Task process PID files and logs
|
# Task process PID files and logs
|
||||||
.task-pids/
|
.task-pids/
|
||||||
|
|
||||||
|
.vibe-setup.env
|
||||||
|
.vibe-task-id
|
||||||
|
|
||||||
|
# Task-specific Docker Compose files (generated dynamically)
|
||||||
|
src/Managing.Docker/docker-compose.task-*.yml
|
||||||
|
|||||||
122
docs/API_AND_WORKERS_PROCESSES.md
Normal file
122
docs/API_AND_WORKERS_PROCESSES.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
# API and Workers Processes
|
||||||
|
|
||||||
|
This document lists all processes that run when the API and Workers are started.
|
||||||
|
|
||||||
|
## Process Hierarchy
|
||||||
|
|
||||||
|
### 1. API Process (`dotnet run` for Managing.Api)
|
||||||
|
|
||||||
|
**Parent Process:**
|
||||||
|
- `dotnet run` - The .NET CLI process that starts the API
|
||||||
|
- PID stored in: `.task-pids/api-${TASK_ID}.pid`
|
||||||
|
|
||||||
|
**Child Process:**
|
||||||
|
- `Managing.Api` executable - The actual API application
|
||||||
|
- Location: `src/Managing.Api/bin/Debug/net8.0/Managing.Api`
|
||||||
|
- This is the main ASP.NET Core application
|
||||||
|
|
||||||
|
**Background Services (within the API process):**
|
||||||
|
All of these run as `IHostedService` within the same API process:
|
||||||
|
|
||||||
|
1. **GrainInitializer** - Initializes Orleans grains
|
||||||
|
2. **DiscordService** - Discord bot service
|
||||||
|
3. **PricesFifteenMinutesWorker** - Updates prices every 15 minutes (if enabled)
|
||||||
|
4. **PricesOneHourWorker** - Updates prices every hour (if enabled)
|
||||||
|
5. **PricesFourHoursWorker** - Updates prices every 4 hours (if enabled)
|
||||||
|
6. **PricesOneDayWorker** - Updates prices every day (if enabled)
|
||||||
|
7. **PricesFiveMinutesWorker** - Updates prices every 5 minutes (if enabled)
|
||||||
|
8. **SpotlightWorker** - Spotlight feature worker (if enabled)
|
||||||
|
9. **TraderWatcher** - Watches traders (if enabled)
|
||||||
|
10. **LeaderboardWorker** - Updates leaderboard (if enabled)
|
||||||
|
11. **FundingRatesWatcher** - Watches funding rates (if enabled)
|
||||||
|
12. **GeneticAlgorithmWorker** - Genetic algorithm worker (if enabled)
|
||||||
|
13. **NotifyBundleBacktestWorker** - Notifies about bundle backtests (if enabled)
|
||||||
|
|
||||||
|
**Orleans Components (within the API process):**
|
||||||
|
- Orleans Silo - Runs on port `11111 + (TASK_SLOT - 1) * 10`
|
||||||
|
- Orleans Gateway - Runs on port `30000 + (TASK_SLOT - 1) * 10`
|
||||||
|
- Orleans Dashboard - Runs on port `9999 + (TASK_SLOT - 1)` (development only)
|
||||||
|
|
||||||
|
### 2. Workers Process (`dotnet run` for Managing.Workers)
|
||||||
|
|
||||||
|
**Parent Process:**
|
||||||
|
- `dotnet run` - The .NET CLI process that starts the Workers
|
||||||
|
- PID stored in: `.task-pids/workers-${TASK_ID}.pid`
|
||||||
|
|
||||||
|
**Child Process:**
|
||||||
|
- `Managing.Workers` executable - The actual Workers application
|
||||||
|
- Location: `src/Managing.Workers/bin/Debug/net8.0/Managing.Workers`
|
||||||
|
- This is a .NET Host application
|
||||||
|
|
||||||
|
**Background Services (within the Workers process):**
|
||||||
|
All of these run as `BackgroundService` within the same Workers process:
|
||||||
|
|
||||||
|
1. **BacktestComputeWorker** - Processes backtest jobs (if enabled)
|
||||||
|
2. **GeneticComputeWorker** - Processes genetic algorithm jobs (if enabled)
|
||||||
|
3. **BundleBacktestHealthCheckWorker** - Health check for bundle backtests (if enabled, only on TASK_SLOT=1)
|
||||||
|
|
||||||
|
## Process Management
|
||||||
|
|
||||||
|
### Starting Processes
|
||||||
|
Processes are started by `scripts/start-api-and-workers.sh`:
|
||||||
|
- API: `cd src/Managing.Api && dotnet run &`
|
||||||
|
- Workers: `cd src/Managing.Workers && dotnet run &`
|
||||||
|
|
||||||
|
### Stopping Processes
|
||||||
|
Processes are stopped by `scripts/stop-task-docker.sh` or the cleanup script:
|
||||||
|
1. Read PID from `.task-pids/api-${TASK_ID}.pid`
|
||||||
|
2. Kill the parent `dotnet run` process
|
||||||
|
3. Kill any orphaned child processes
|
||||||
|
4. Read PID from `.task-pids/workers-${TASK_ID}.pid`
|
||||||
|
5. Kill the parent `dotnet run` process
|
||||||
|
6. Kill any orphaned child processes
|
||||||
|
|
||||||
|
### Finding All Related Processes
|
||||||
|
|
||||||
|
To find all processes related to a specific task:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find by PID file
|
||||||
|
TASK_ID="YOUR_TASK_ID"
|
||||||
|
API_PID=$(cat .task-pids/api-${TASK_ID}.pid 2>/dev/null)
|
||||||
|
WORKERS_PID=$(cat .task-pids/workers-${TASK_ID}.pid 2>/dev/null)
|
||||||
|
|
||||||
|
# Find child processes
|
||||||
|
ps -ef | grep $API_PID
|
||||||
|
ps -ef | grep $WORKERS_PID
|
||||||
|
|
||||||
|
# Find by executable name
|
||||||
|
ps aux | grep "Managing.Api"
|
||||||
|
ps aux | grep "Managing.Workers"
|
||||||
|
ps aux | grep "dotnet run"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Finding Processes by Port
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find API process by port
|
||||||
|
lsof -i :5000 # Default API port
|
||||||
|
lsof -i :$((5000 + PORT_OFFSET)) # With port offset
|
||||||
|
|
||||||
|
# Find Orleans processes by port
|
||||||
|
lsof -i :11111 # Orleans Silo (default)
|
||||||
|
lsof -i :30000 # Orleans Gateway (default)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
1. **Single Process Architecture**: All background services run within the same process as the API or Workers. They are not separate processes.
|
||||||
|
|
||||||
|
2. **PID Files**: The PID files store the parent `dotnet run` process PID, not the child executable PID.
|
||||||
|
|
||||||
|
3. **Orphaned Processes**: If the parent `dotnet run` process is killed, the child `Managing.Api` or `Managing.Workers` process may become orphaned. The cleanup script should handle this.
|
||||||
|
|
||||||
|
4. **Port Conflicts**: Each task uses unique ports based on `PORT_OFFSET`:
|
||||||
|
- API: `5000 + PORT_OFFSET`
|
||||||
|
- PostgreSQL: `5432 + PORT_OFFSET`
|
||||||
|
- Redis: `6379 + PORT_OFFSET`
|
||||||
|
- Orleans Silo: `11111 + (TASK_SLOT - 1) * 10`
|
||||||
|
- Orleans Gateway: `30000 + (TASK_SLOT - 1) * 10`
|
||||||
|
|
||||||
|
5. **Worker Consolidation**: Most workers have been consolidated into the API process. The separate `Managing.Workers` project now only runs compute-intensive workers (BacktestComputeWorker, GeneticComputeWorker).
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ Vibe Kanban runs the dev server script from a different working directory than e
|
|||||||
In the Vibe Kanban dev server script field, use the **absolute path** to the wrapper script:
|
In the Vibe Kanban dev server script field, use the **absolute path** to the wrapper script:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh
|
bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Alternative: If Relative Path is Required
|
## Alternative: If Relative Path is Required
|
||||||
@@ -17,7 +17,7 @@ bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh
|
|||||||
If Vibe Kanban requires a relative path and you know it runs from `/Users/oda/Desktop`, use:
|
If Vibe Kanban requires a relative path and you know it runs from `/Users/oda/Desktop`, use:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash Projects/managing-apps/scripts/vibe-dev-server.sh
|
bash Projects/managing-apps/scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## What the Wrapper Script Does
|
## What the Wrapper Script Does
|
||||||
@@ -36,7 +36,7 @@ You can test the script manually:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# From any directory
|
# From any directory
|
||||||
bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh TEST-001 0
|
bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-kanban/vibe-dev-server.sh TEST-001 0
|
||||||
```
|
```
|
||||||
|
|
||||||
## Debug Output
|
## Debug Output
|
||||||
@@ -54,17 +54,17 @@ This helps identify if Vibe Kanban is running from an unexpected directory.
|
|||||||
|
|
||||||
1. Verify the script exists:
|
1. Verify the script exists:
|
||||||
```bash
|
```bash
|
||||||
ls -la /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh
|
ls -la /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Check permissions:
|
2. Check permissions:
|
||||||
```bash
|
```bash
|
||||||
chmod +x /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh
|
chmod +x /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Try running it directly:
|
3. Try running it directly:
|
||||||
```bash
|
```bash
|
||||||
bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh TEST-001
|
bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-kanban/vibe-dev-server.sh TEST-001
|
||||||
```
|
```
|
||||||
|
|
||||||
### Error: "Cannot change to project root"
|
### Error: "Cannot change to project root"
|
||||||
@@ -76,7 +76,7 @@ This helps identify if Vibe Kanban is running from an unexpected directory.
|
|||||||
|
|
||||||
**Dev Server Script Field:**
|
**Dev Server Script Field:**
|
||||||
```
|
```
|
||||||
bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh
|
bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
**Health Check URL:**
|
**Health Check URL:**
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ In the **QA** or **Testing** section, configure:
|
|||||||
|
|
||||||
**Dev Environment Script:**
|
**Dev Environment Script:**
|
||||||
```
|
```
|
||||||
managing-apps/scripts/vibe-dev-server.sh
|
managing-apps/scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
**Or use absolute path:**
|
**Or use absolute path:**
|
||||||
```
|
```
|
||||||
/Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh
|
/Users/oda/Desktop/Projects/managing-apps/scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** This path is relative to `/Users/oda/Desktop/Projects` (the Projects folder root)
|
**Note:** This path is relative to `/Users/oda/Desktop/Projects` (the Projects folder root)
|
||||||
|
|||||||
291
scripts/cleanup-api-workers.sh
Normal file
291
scripts/cleanup-api-workers.sh
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
#!/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>
|
||||||
|
|
||||||
|
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 <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 " 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 <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"
|
||||||
|
|
||||||
@@ -17,8 +17,17 @@ DB_NAME="managing_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
|||||||
ORLEANS_DB_NAME="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
ORLEANS_DB_NAME="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
||||||
TASK_ID_LOWER="$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
TASK_ID_LOWER="$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
|
||||||
# Calculate unique task slot based on port offset (for Orleans clustering)
|
# Extract TASK_SLOT from TASK_ID numeric part (e.g., TASK-5439 -> 5439)
|
||||||
TASK_SLOT=$((PORT_OFFSET / 10 + 1))
|
# This ensures unique Orleans ports for each task and prevents port conflicts
|
||||||
|
TASK_SLOT=$(echo "$TASK_ID" | grep -oE '[0-9]+' | head -1)
|
||||||
|
if [ -z "$TASK_SLOT" ] || [ "$TASK_SLOT" = "0" ]; then
|
||||||
|
# Fallback: use port offset calculation if TASK_ID doesn't contain numbers
|
||||||
|
TASK_SLOT=$((PORT_OFFSET / 10 + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Calculate Orleans ports based on TASK_SLOT (for display purposes)
|
||||||
|
ORLEANS_SILO_PORT_CALC=$((11111 + (TASK_SLOT - 1) * 10))
|
||||||
|
ORLEANS_GATEWAY_PORT_CALC=$((30000 + (TASK_SLOT - 1) * 10))
|
||||||
|
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||||
@@ -75,8 +84,8 @@ echo "✅ Created $COMPOSE_FILE"
|
|||||||
echo " PostgreSQL: localhost:$POSTGRES_PORT"
|
echo " PostgreSQL: localhost:$POSTGRES_PORT"
|
||||||
echo " Redis: localhost:$REDIS_PORT"
|
echo " Redis: localhost:$REDIS_PORT"
|
||||||
echo " API will run via dotnet run on port: $API_PORT"
|
echo " API will run via dotnet run on port: $API_PORT"
|
||||||
echo " Orleans Silo: localhost:$ORLEANS_SILO_PORT"
|
echo " Orleans Silo: localhost:$ORLEANS_SILO_PORT_CALC (based on TASK_SLOT=$TASK_SLOT)"
|
||||||
echo " Orleans Gateway: localhost:$ORLEANS_GATEWAY_PORT"
|
echo " Orleans Gateway: localhost:$ORLEANS_GATEWAY_PORT_CALC (based on TASK_SLOT=$TASK_SLOT)"
|
||||||
echo " InfluxDB: Using main instance at localhost:8086"
|
echo " InfluxDB: Using main instance at localhost:8086"
|
||||||
echo " Task Slot: $TASK_SLOT"
|
echo " Task Slot: $TASK_SLOT (extracted from TASK_ID: $TASK_ID)"
|
||||||
|
|
||||||
|
|||||||
147
scripts/list-api-workers-processes.sh
Executable file
147
scripts/list-api-workers-processes.sh
Executable file
@@ -0,0 +1,147 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# scripts/list-api-workers-processes.sh
|
||||||
|
# Lists all processes related to API and Workers for a given task
|
||||||
|
|
||||||
|
TASK_ID=$1
|
||||||
|
|
||||||
|
# Try to get TASK_ID from environment if not provided
|
||||||
|
if [ -z "$TASK_ID" ] && [ -n "$VIBE_TASK_ID" ]; then
|
||||||
|
TASK_ID="$VIBE_TASK_ID"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine project root
|
||||||
|
if [ -n "$VIBE_WORKTREE_ROOT" ] && [ -d "$VIBE_WORKTREE_ROOT/src/Managing.Api" ]; then
|
||||||
|
PROJECT_ROOT="$VIBE_WORKTREE_ROOT"
|
||||||
|
elif [ -d "$(pwd)/scripts" ] && [ -f "$(pwd)/scripts/start-api-and-workers.sh" ]; then
|
||||||
|
PROJECT_ROOT="$(pwd)"
|
||||||
|
else
|
||||||
|
MAIN_REPO="/Users/oda/Desktop/Projects/managing-apps"
|
||||||
|
if [ -d "$MAIN_REPO/scripts" ]; then
|
||||||
|
PROJECT_ROOT="$MAIN_REPO"
|
||||||
|
else
|
||||||
|
echo "❌ Error: Cannot find project root"
|
||||||
|
exit 1
|
||||||
|
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 "📋 Listing ALL API and Workers processes..."
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo "🔍 All dotnet run processes:"
|
||||||
|
ps aux | grep "dotnet run" | grep -v grep || echo " (none found)"
|
||||||
|
echo ""
|
||||||
|
echo "🔍 All Managing.Api processes:"
|
||||||
|
ps aux | grep "Managing.Api" | grep -v grep || echo " (none found)"
|
||||||
|
echo ""
|
||||||
|
echo "🔍 All Managing.Workers processes:"
|
||||||
|
ps aux | grep "Managing.Workers" | grep -v grep || echo " (none found)"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
echo "💡 To list processes for a specific task, run: $0 <TASK_ID>"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📋 Listing processes for task: $TASK_ID"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
|
||||||
|
# Check API processes
|
||||||
|
if [ -f "$API_PID_FILE" ]; then
|
||||||
|
API_PID=$(cat "$API_PID_FILE")
|
||||||
|
echo "📊 API Process (from PID file):"
|
||||||
|
echo " PID File: $API_PID_FILE"
|
||||||
|
echo " Stored PID: $API_PID"
|
||||||
|
|
||||||
|
if ps -p "$API_PID" > /dev/null 2>&1; then
|
||||||
|
echo " ✅ Process is running"
|
||||||
|
echo " Process details:"
|
||||||
|
ps -p "$API_PID" -o pid,ppid,user,%cpu,%mem,etime,command | head -2
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Find child processes
|
||||||
|
echo " Child processes:"
|
||||||
|
CHILD_PIDS=$(pgrep -P "$API_PID" 2>/dev/null)
|
||||||
|
if [ -n "$CHILD_PIDS" ]; then
|
||||||
|
for CHILD_PID in $CHILD_PIDS; do
|
||||||
|
ps -p "$CHILD_PID" -o pid,ppid,user,%cpu,%mem,etime,command 2>/dev/null | tail -1
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " (no child processes found)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ⚠️ Process not running (stale PID file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "📊 API Process:"
|
||||||
|
echo " ⚠️ PID file not found: $API_PID_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check Workers processes
|
||||||
|
if [ -f "$WORKERS_PID_FILE" ]; then
|
||||||
|
WORKERS_PID=$(cat "$WORKERS_PID_FILE")
|
||||||
|
echo "📊 Workers Process (from PID file):"
|
||||||
|
echo " PID File: $WORKERS_PID_FILE"
|
||||||
|
echo " Stored PID: $WORKERS_PID"
|
||||||
|
|
||||||
|
if ps -p "$WORKERS_PID" > /dev/null 2>&1; then
|
||||||
|
echo " ✅ Process is running"
|
||||||
|
echo " Process details:"
|
||||||
|
ps -p "$WORKERS_PID" -o pid,ppid,user,%cpu,%mem,etime,command | head -2
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Find child processes
|
||||||
|
echo " Child processes:"
|
||||||
|
CHILD_PIDS=$(pgrep -P "$WORKERS_PID" 2>/dev/null)
|
||||||
|
if [ -n "$CHILD_PIDS" ]; then
|
||||||
|
for CHILD_PID in $CHILD_PIDS; do
|
||||||
|
ps -p "$CHILD_PID" -o pid,ppid,user,%cpu,%mem,etime,command 2>/dev/null | tail -1
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " (no child processes found)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ⚠️ Process not running (stale PID file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "📊 Workers Process:"
|
||||||
|
echo " ⚠️ PID file not found: $WORKERS_PID_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
|
||||||
|
# Find processes by executable name (in case PID files are missing)
|
||||||
|
echo "🔍 Searching for processes by executable name:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
API_PROCESSES=$(ps aux | grep "Managing.Api" | grep -v grep | grep "$TASK_ID\|worktree" || true)
|
||||||
|
if [ -n "$API_PROCESSES" ]; then
|
||||||
|
echo "📊 Found Managing.Api processes:"
|
||||||
|
echo "$API_PROCESSES" | while read line; do
|
||||||
|
echo " $line"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "📊 Managing.Api processes: (none found)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
WORKERS_PROCESSES=$(ps aux | grep "Managing.Workers" | grep -v grep | grep "$TASK_ID\|worktree" || true)
|
||||||
|
if [ -n "$WORKERS_PROCESSES" ]; then
|
||||||
|
echo "📊 Found Managing.Workers processes:"
|
||||||
|
echo "$WORKERS_PROCESSES" | while read line; do
|
||||||
|
echo " $line"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "📊 Managing.Workers processes: (none found)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
|
||||||
@@ -29,8 +29,23 @@ ORLEANS_GATEWAY_PORT=$((30000 + PORT_OFFSET))
|
|||||||
DB_NAME="managing_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
DB_NAME="managing_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
||||||
ORLEANS_DB_NAME="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
ORLEANS_DB_NAME="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
|
||||||
# Calculate unique task slot based on port offset (for Orleans clustering)
|
# Extract TASK_SLOT from TASK_ID numeric part (e.g., TASK-5439 -> 5439)
|
||||||
TASK_SLOT=$((PORT_OFFSET / 10 + 1))
|
# This ensures unique Orleans ports for each task and prevents port conflicts
|
||||||
|
# Use TASK_SLOT from environment if already set (from vibe-setup.sh config), otherwise extract from TASK_ID
|
||||||
|
if [ -z "$TASK_SLOT" ] || [ "$TASK_SLOT" = "0" ]; then
|
||||||
|
TASK_SLOT=$(echo "$TASK_ID" | grep -oE '[0-9]+' | head -1)
|
||||||
|
if [ -z "$TASK_SLOT" ] || [ "$TASK_SLOT" = "0" ]; then
|
||||||
|
# Fallback: use port offset calculation if TASK_ID doesn't contain numbers
|
||||||
|
TASK_SLOT=$((PORT_OFFSET / 10 + 1))
|
||||||
|
echo "⚠️ TASK_ID doesn't contain a number, using port offset-based TASK_SLOT: $TASK_SLOT"
|
||||||
|
else
|
||||||
|
echo "📊 TASK_SLOT extracted from TASK_ID: $TASK_SLOT"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "📊 Using TASK_SLOT from configuration: $TASK_SLOT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TASK_SLOT determines Orleans ports: Silo = 11111 + (TASK_SLOT - 1) * 10, Gateway = 30000 + (TASK_SLOT - 1) * 10
|
||||||
|
|
||||||
# PID files for process management
|
# PID files for process management
|
||||||
PID_DIR="$PROJECT_ROOT/.task-pids"
|
PID_DIR="$PROJECT_ROOT/.task-pids"
|
||||||
@@ -44,6 +59,10 @@ export ASPNETCORE_URLS="http://localhost:${API_PORT}"
|
|||||||
export RUN_ORLEANS_GRAINS=true
|
export RUN_ORLEANS_GRAINS=true
|
||||||
export SILO_ROLE=Trading
|
export SILO_ROLE=Trading
|
||||||
export TASK_SLOT=${TASK_SLOT}
|
export TASK_SLOT=${TASK_SLOT}
|
||||||
|
export TASK_ID=${TASK_ID}
|
||||||
|
export PORT_OFFSET=${PORT_OFFSET}
|
||||||
|
# Orleans ports are calculated from TASK_SLOT in the application
|
||||||
|
# These exports are kept for reference but not used (TASK_SLOT is the source of truth)
|
||||||
export PostgreSql__ConnectionString="Host=localhost;Port=${POSTGRES_PORT};Database=${DB_NAME};Username=postgres;Password=postgres"
|
export PostgreSql__ConnectionString="Host=localhost;Port=${POSTGRES_PORT};Database=${DB_NAME};Username=postgres;Password=postgres"
|
||||||
export PostgreSql__Orleans="Host=localhost;Port=${POSTGRES_PORT};Database=${ORLEANS_DB_NAME};Username=postgres;Password=postgres"
|
export PostgreSql__Orleans="Host=localhost;Port=${POSTGRES_PORT};Database=${ORLEANS_DB_NAME};Username=postgres;Password=postgres"
|
||||||
export InfluxDb__Url="http://localhost:8086/"
|
export InfluxDb__Url="http://localhost:8086/"
|
||||||
@@ -75,6 +94,7 @@ fi
|
|||||||
echo "🚀 Starting API on port $API_PORT..."
|
echo "🚀 Starting API on port $API_PORT..."
|
||||||
echo "📁 Running from: $PROJECT_ROOT"
|
echo "📁 Running from: $PROJECT_ROOT"
|
||||||
cd "$PROJECT_ROOT/src/Managing.Api"
|
cd "$PROJECT_ROOT/src/Managing.Api"
|
||||||
|
# Write all output to log file (warnings will be filtered when displaying)
|
||||||
dotnet run > "$PID_DIR/api-${TASK_ID}.log" 2>&1 &
|
dotnet run > "$PID_DIR/api-${TASK_ID}.log" 2>&1 &
|
||||||
API_PID=$!
|
API_PID=$!
|
||||||
echo $API_PID > "$API_PID_FILE"
|
echo $API_PID > "$API_PID_FILE"
|
||||||
@@ -86,6 +106,7 @@ sleep 3
|
|||||||
echo "🚀 Starting Workers..."
|
echo "🚀 Starting Workers..."
|
||||||
cd "$PROJECT_ROOT/src/Managing.Workers"
|
cd "$PROJECT_ROOT/src/Managing.Workers"
|
||||||
# Set workers environment variables (separate from API)
|
# Set workers environment variables (separate from API)
|
||||||
|
# Write all output to log file (warnings will be filtered when displaying)
|
||||||
ASPNETCORE_ENVIRONMENT=Development \
|
ASPNETCORE_ENVIRONMENT=Development \
|
||||||
PostgreSql__ConnectionString="Host=localhost;Port=${POSTGRES_PORT};Database=${DB_NAME};Username=postgres;Password=postgres" \
|
PostgreSql__ConnectionString="Host=localhost;Port=${POSTGRES_PORT};Database=${DB_NAME};Username=postgres;Password=postgres" \
|
||||||
InfluxDb__Url="http://localhost:8086/" \
|
InfluxDb__Url="http://localhost:8086/" \
|
||||||
|
|||||||
126
scripts/vibe-kanban/README.md
Normal file
126
scripts/vibe-kanban/README.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# Vibe Kanban Scripts
|
||||||
|
|
||||||
|
This directory contains all scripts specifically for Vibe Kanban integration.
|
||||||
|
|
||||||
|
## Scripts
|
||||||
|
|
||||||
|
### `vibe-setup.sh`
|
||||||
|
**Purpose:** Sets up the database and Docker services for a Vibe Kanban task environment.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
bash scripts/vibe-kanban/vibe-setup.sh [TASK_ID] [PORT_OFFSET]
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
- Detects or generates a consistent TASK_ID for the worktree
|
||||||
|
- Auto-detects available port offset
|
||||||
|
- Creates Docker Compose file for the task
|
||||||
|
- Starts PostgreSQL and Redis containers
|
||||||
|
- Copies database from main repository
|
||||||
|
- Saves configuration to `.vibe-setup.env`
|
||||||
|
|
||||||
|
**Configuration saved:**
|
||||||
|
- Task ID
|
||||||
|
- Port offsets
|
||||||
|
- Database names
|
||||||
|
- All connection details
|
||||||
|
|
||||||
|
**Note:** This script runs in the "setup" section of Vibe Kanban.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `vibe-dev-server.sh`
|
||||||
|
**Purpose:** Starts the API and Workers processes (assumes database is already set up).
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
bash scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
- Loads configuration from `.vibe-setup.env` (created by vibe-setup.sh)
|
||||||
|
- Verifies database is ready
|
||||||
|
- Starts API and Workers using `start-api-and-workers.sh`
|
||||||
|
- Displays logs with filtered warnings
|
||||||
|
- Shows API and Workers logs in real-time
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
- Must run `vibe-setup.sh` first to create the database environment
|
||||||
|
- Configuration file `.vibe-setup.env` must exist
|
||||||
|
|
||||||
|
**Note:** This script runs in the "dev server" section of Vibe Kanban.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `cleanup-api-workers.sh`
|
||||||
|
**Purpose:** Stops API and Workers processes for a specific task.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
bash scripts/vibe-kanban/cleanup-api-workers.sh <TASK_ID>
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
- Stops API process (and child processes)
|
||||||
|
- Stops Workers process (and child processes)
|
||||||
|
- Kills orphaned processes
|
||||||
|
- Removes PID files
|
||||||
|
- Preserves log files for debugging
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Graceful shutdown (SIGTERM) with fallback to force kill (SIGKILL)
|
||||||
|
- Handles orphaned processes
|
||||||
|
- Works with Vibe Kanban worktrees
|
||||||
|
- Supports environment variables for TASK_ID
|
||||||
|
|
||||||
|
**Note:** This script is used by Vibe Kanban for cleanup operations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. **Setup Phase** (Vibe Kanban "setup" section):
|
||||||
|
```bash
|
||||||
|
bash scripts/vibe-kanban/vibe-setup.sh
|
||||||
|
```
|
||||||
|
- Sets up database and Docker services
|
||||||
|
- Creates configuration file
|
||||||
|
|
||||||
|
2. **Dev Server Phase** (Vibe Kanban "dev server" section):
|
||||||
|
```bash
|
||||||
|
bash scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
|
```
|
||||||
|
- Starts API and Workers
|
||||||
|
- Shows logs
|
||||||
|
|
||||||
|
3. **Cleanup Phase** (Vibe Kanban cleanup):
|
||||||
|
```bash
|
||||||
|
bash scripts/vibe-kanban/cleanup-api-workers.sh <TASK_ID>
|
||||||
|
```
|
||||||
|
- Stops all processes
|
||||||
|
- Cleans up
|
||||||
|
|
||||||
|
## Configuration Files
|
||||||
|
|
||||||
|
These scripts create/use the following files in the worktree:
|
||||||
|
|
||||||
|
- `.vibe-task-id` - Stores the persistent TASK_ID for the worktree
|
||||||
|
- `.vibe-setup.env` - Stores all setup configuration (ports, database names, etc.)
|
||||||
|
- `.task-pids/` - Directory containing PID files and logs
|
||||||
|
|
||||||
|
## Paths
|
||||||
|
|
||||||
|
All paths in these scripts are relative to the main repository:
|
||||||
|
- Main repo: `/Users/oda/Desktop/Projects/managing-apps`
|
||||||
|
- Scripts: `scripts/vibe-kanban/`
|
||||||
|
- Worktree: Detected automatically from current directory
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
These scripts support the following environment variables:
|
||||||
|
|
||||||
|
- `VIBE_TASK_ID` - Task ID from Vibe Kanban
|
||||||
|
- `VIBE_TASK_NAME` - Task name from Vibe Kanban
|
||||||
|
- `VIBE_WORKTREE_ROOT` - Worktree root path (set automatically)
|
||||||
|
|
||||||
361
scripts/vibe-kanban/cleanup-api-workers.sh
Executable file
361
scripts/vibe-kanban/cleanup-api-workers.sh
Executable file
@@ -0,0 +1,361 @@
|
|||||||
|
#!/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"
|
||||||
|
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# scripts/vibe-dev-server.sh
|
# scripts/vibe-kanban/vibe-dev-server.sh
|
||||||
# Minimal script for Vibe Kanban worktrees
|
# Simplified script for Vibe Kanban - starts API and Workers only
|
||||||
# This script runs from the worktree and uses main repo scripts for Docker setup
|
# Assumes database setup is already done by vibe-setup.sh
|
||||||
|
|
||||||
TASK_ID=${1:-"DEV-$(date +%Y%m%d-%H%M%S)"}
|
|
||||||
PORT_OFFSET=${2:-0}
|
|
||||||
|
|
||||||
# Detect worktree root
|
# Detect worktree root
|
||||||
WORKTREE_ROOT="$(pwd)"
|
WORKTREE_ROOT="$(pwd)"
|
||||||
@@ -22,16 +19,77 @@ fi
|
|||||||
|
|
||||||
echo "📁 Worktree project root: $WORKTREE_PROJECT_ROOT"
|
echo "📁 Worktree project root: $WORKTREE_PROJECT_ROOT"
|
||||||
|
|
||||||
# Find main repository (try common locations)
|
# TASK_ID file to ensure consistency (same as vibe-setup.sh)
|
||||||
|
TASK_ID_FILE="$WORKTREE_PROJECT_ROOT/.vibe-task-id"
|
||||||
|
|
||||||
|
# Load setup configuration if available
|
||||||
|
SETUP_CONFIG_FILE="$WORKTREE_PROJECT_ROOT/.vibe-setup.env"
|
||||||
|
if [ -f "$SETUP_CONFIG_FILE" ]; then
|
||||||
|
echo "📋 Loading setup configuration from: $SETUP_CONFIG_FILE"
|
||||||
|
source "$SETUP_CONFIG_FILE"
|
||||||
|
echo " Task ID: $TASK_ID"
|
||||||
|
echo " Task Slot: ${TASK_SLOT:-not set}"
|
||||||
|
echo " Port offset: $PORT_OFFSET"
|
||||||
|
echo " API Port: $API_PORT"
|
||||||
|
else
|
||||||
|
echo "⚠️ Setup configuration not found: $SETUP_CONFIG_FILE"
|
||||||
|
echo "💡 Run scripts/vibe-kanban/vibe-setup.sh first to set up the database"
|
||||||
|
|
||||||
|
# Try to get TASK_ID from stored file (ensures consistency)
|
||||||
|
if [ -f "$TASK_ID_FILE" ]; then
|
||||||
|
TASK_ID=$(cat "$TASK_ID_FILE" 2>/dev/null | tr -d '[:space:]')
|
||||||
|
if [ -n "$TASK_ID" ]; then
|
||||||
|
echo "📋 Using stored TASK_ID: $TASK_ID"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try command line argument
|
||||||
|
if [ -z "$TASK_ID" ]; then
|
||||||
|
TASK_ID=${1:-""}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try environment variables
|
||||||
|
if [ -z "$TASK_ID" ]; then
|
||||||
|
if [ -n "$VIBE_TASK_ID" ]; then
|
||||||
|
TASK_ID="$VIBE_TASK_ID"
|
||||||
|
elif [ -n "$VIBE_TASK_NAME" ]; then
|
||||||
|
TASK_ID="$VIBE_TASK_NAME"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
PORT_OFFSET=${2:-0}
|
||||||
|
|
||||||
|
if [ -z "$TASK_ID" ]; then
|
||||||
|
echo "❌ TASK_ID is required"
|
||||||
|
echo "💡 Usage: $0 <TASK_ID> [PORT_OFFSET]"
|
||||||
|
echo "💡 Or run scripts/vibe-kanban/vibe-setup.sh first to create setup configuration"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
API_PORT=$((5000 + PORT_OFFSET))
|
||||||
|
# Extract TASK_SLOT from TASK_ID if not in config
|
||||||
|
if [ -z "$TASK_SLOT" ]; then
|
||||||
|
TASK_SLOT=$(echo "$TASK_ID" | grep -oE '[0-9]+' | head -1)
|
||||||
|
if [ -z "$TASK_SLOT" ] || [ "$TASK_SLOT" = "0" ]; then
|
||||||
|
TASK_SLOT=$((PORT_OFFSET / 10 + 1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo " Using Task ID: $TASK_ID"
|
||||||
|
echo " Using Task Slot: $TASK_SLOT"
|
||||||
|
echo " Using Port offset: $PORT_OFFSET"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find main repository
|
||||||
MAIN_REPO_PATHS=(
|
MAIN_REPO_PATHS=(
|
||||||
"/Users/oda/Desktop/Projects/managing-apps"
|
"/Users/oda/Desktop/Projects/managing-apps"
|
||||||
"$(git -C "$WORKTREE_PROJECT_ROOT" rev-parse --show-toplevel 2>/dev/null || echo '')"
|
"$(git -C "$WORKTREE_PROJECT_ROOT" rev-parse --show-toplevel 2>/dev/null || echo '')"
|
||||||
"$(dirname "$WORKTREE_ROOT" 2>/dev/null)/managing-apps"
|
"$(dirname "$WORKTREE_ROOT" 2>/dev/null)/managing-apps"
|
||||||
|
"${MAIN_REPO:-}"
|
||||||
)
|
)
|
||||||
|
|
||||||
MAIN_REPO=""
|
MAIN_REPO=""
|
||||||
for path in "${MAIN_REPO_PATHS[@]}"; do
|
for path in "${MAIN_REPO_PATHS[@]}"; do
|
||||||
if [ -n "$path" ] && [ -d "$path" ] && [ -d "$path/scripts" ] && [ -f "$path/scripts/start-task-docker.sh" ]; then
|
if [ -n "$path" ] && [ -d "$path" ] && [ -d "$path/scripts" ] && [ -f "$path/scripts/start-api-and-workers.sh" ]; then
|
||||||
MAIN_REPO="$path"
|
MAIN_REPO="$path"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@@ -39,23 +97,30 @@ done
|
|||||||
|
|
||||||
if [ -z "$MAIN_REPO" ]; then
|
if [ -z "$MAIN_REPO" ]; then
|
||||||
echo "❌ Cannot find main repository with scripts"
|
echo "❌ Cannot find main repository with scripts"
|
||||||
echo "💡 Tried:"
|
|
||||||
for path in "${MAIN_REPO_PATHS[@]}"; do
|
|
||||||
echo " - $path"
|
|
||||||
done
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "📁 Main repository: $MAIN_REPO"
|
echo "📁 Main repository: $MAIN_REPO"
|
||||||
echo "🚀 Starting dev environment..."
|
echo "🚀 Starting API and Workers..."
|
||||||
echo " Task ID: $TASK_ID"
|
echo " Task ID: $TASK_ID"
|
||||||
echo " Port offset: $PORT_OFFSET"
|
echo " Port offset: $PORT_OFFSET"
|
||||||
|
|
||||||
|
# Verify database is ready
|
||||||
|
if [ -n "$POSTGRES_PORT" ]; then
|
||||||
|
echo "🔍 Verifying database is ready on port $POSTGRES_PORT..."
|
||||||
|
if ! PGPASSWORD=postgres psql -h localhost -p $POSTGRES_PORT -U postgres -d postgres -c '\q' 2>/dev/null; then
|
||||||
|
echo "❌ Database is not ready on port $POSTGRES_PORT"
|
||||||
|
echo "💡 Run scripts/vibe-kanban/vibe-setup.sh first to set up the database"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✅ Database is ready"
|
||||||
|
fi
|
||||||
|
|
||||||
# Export worktree path so main repo scripts know where to run dotnet from
|
# Export worktree path so main repo scripts know where to run dotnet from
|
||||||
export VIBE_WORKTREE_ROOT="$WORKTREE_PROJECT_ROOT"
|
export VIBE_WORKTREE_ROOT="$WORKTREE_PROJECT_ROOT"
|
||||||
|
|
||||||
# Call main repo's start script
|
# Start API and Workers only (database setup is already done)
|
||||||
bash "$MAIN_REPO/scripts/start-task-docker.sh" "$TASK_ID" "$PORT_OFFSET"
|
bash "$MAIN_REPO/scripts/start-api-and-workers.sh" "$TASK_ID" "$PORT_OFFSET"
|
||||||
|
|
||||||
# Determine log file paths (logs are created in the worktree root)
|
# Determine log file paths (logs are created in the worktree root)
|
||||||
PID_DIR="$WORKTREE_PROJECT_ROOT/.task-pids"
|
PID_DIR="$WORKTREE_PROJECT_ROOT/.task-pids"
|
||||||
@@ -113,17 +178,17 @@ else
|
|||||||
# Simple approach: tail both files with prefixes
|
# Simple approach: tail both files with prefixes
|
||||||
# Use a subshell to manage background processes
|
# Use a subshell to manage background processes
|
||||||
(
|
(
|
||||||
# Start tailing API logs in background
|
# Start tailing API logs in background (filter out NuGet build warnings)
|
||||||
if [ -f "$API_LOG" ]; then
|
if [ -f "$API_LOG" ]; then
|
||||||
tail -f "$API_LOG" 2>/dev/null | while IFS= read -r line; do
|
tail -f "$API_LOG" 2>/dev/null | grep -vE "(warning NU|\.csproj : warning)" | while IFS= read -r line; do
|
||||||
echo "[API] $line"
|
echo "[API] $line"
|
||||||
done &
|
done &
|
||||||
TAIL_API_PID=$!
|
TAIL_API_PID=$!
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Start tailing Workers logs in background
|
# Start tailing Workers logs in background (filter out NuGet build warnings)
|
||||||
if [ -f "$WORKERS_LOG" ]; then
|
if [ -f "$WORKERS_LOG" ]; then
|
||||||
tail -f "$WORKERS_LOG" 2>/dev/null | while IFS= read -r line; do
|
tail -f "$WORKERS_LOG" 2>/dev/null | grep -vE "(warning NU|\.csproj : warning)" | while IFS= read -r line; do
|
||||||
echo "[WORKERS] $line"
|
echo "[WORKERS] $line"
|
||||||
done &
|
done &
|
||||||
TAIL_WORKERS_PID=$!
|
TAIL_WORKERS_PID=$!
|
||||||
312
scripts/vibe-kanban/vibe-setup.sh
Executable file
312
scripts/vibe-kanban/vibe-setup.sh
Executable file
@@ -0,0 +1,312 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# scripts/vibe-kanban/vibe-setup.sh
|
||||||
|
# Setup script for Vibe Kanban - sets up database and Docker services
|
||||||
|
# This script runs in the "setup" section of Vibe Kanban
|
||||||
|
# Usage: bash scripts/vibe-kanban/vibe-setup.sh [TASK_ID] [PORT_OFFSET]
|
||||||
|
# TASK_ID can also come from environment variables or worktree path
|
||||||
|
|
||||||
|
PORT_OFFSET=${2:-0}
|
||||||
|
|
||||||
|
# Detect worktree root
|
||||||
|
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
|
||||||
|
echo "❌ Cannot find project structure in worktree"
|
||||||
|
echo " Current directory: $WORKTREE_ROOT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📁 Worktree project root: $WORKTREE_PROJECT_ROOT"
|
||||||
|
|
||||||
|
# TASK_ID file to ensure consistency across runs
|
||||||
|
TASK_ID_FILE="$WORKTREE_PROJECT_ROOT/.vibe-task-id"
|
||||||
|
|
||||||
|
# Try to get TASK_ID from various sources
|
||||||
|
TASK_ID=$1
|
||||||
|
|
||||||
|
# First, check if we have a stored TASK_ID for this worktree (ensures consistency)
|
||||||
|
if [ -z "$TASK_ID" ] && [ -f "$TASK_ID_FILE" ]; then
|
||||||
|
TASK_ID=$(cat "$TASK_ID_FILE" 2>/dev/null | tr -d '[:space:]')
|
||||||
|
if [ -n "$TASK_ID" ]; then
|
||||||
|
echo "📋 Using stored TASK_ID from previous setup: $TASK_ID"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
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 "$VIBE_TASK_NAME" ]; then
|
||||||
|
TASK_ID="$VIBE_TASK_NAME"
|
||||||
|
echo "📋 Found TASK_ID from VIBE_TASK_NAME: $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
|
||||||
|
|
||||||
|
# Try to extract from worktree path (Vibe Kanban worktrees often contain task ID/name)
|
||||||
|
if [ -z "$TASK_ID" ]; then
|
||||||
|
# Extract task ID from worktree path (e.g., /path/to/worktrees/TASK-123/... or /path/to/worktrees/ticket-name/...)
|
||||||
|
# Try UUID format first (Vibe Kanban might use UUIDs)
|
||||||
|
DETECTED_TASK=$(echo "$WORKTREE_ROOT" | 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_ROOT" | 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_ROOT")
|
||||||
|
# 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)
|
||||||
|
# This ensures the same ticket name always gets the same numeric ID
|
||||||
|
HASH=$(echo -n "$LAST_DIR" | shasum -a 256 | cut -d' ' -f1 | head -c 8)
|
||||||
|
# Convert hex to decimal and take modulo to get a number between 1-9999
|
||||||
|
NUMERIC_ID=$((0x$HASH % 9999 + 1))
|
||||||
|
DETECTED_TASK="TASK-$NUMERIC_ID"
|
||||||
|
echo "📋 Generated numeric TASK_ID from ticket name '$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
|
||||||
|
|
||||||
|
# Fallback to numeric ID based on worktree path hash (ensures consistency)
|
||||||
|
if [ -z "$TASK_ID" ]; then
|
||||||
|
# Generate a consistent numeric ID from worktree path
|
||||||
|
HASH=$(echo -n "$WORKTREE_ROOT" | shasum -a 256 | cut -d' ' -f1 | head -c 8)
|
||||||
|
NUMERIC_ID=$((0x$HASH % 9999 + 1))
|
||||||
|
TASK_ID="TASK-$NUMERIC_ID"
|
||||||
|
echo "📋 Generated consistent numeric TASK_ID from worktree path: $TASK_ID"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Store TASK_ID for future use (ensures same worktree always uses same TASK_ID)
|
||||||
|
echo "$TASK_ID" > "$TASK_ID_FILE"
|
||||||
|
echo "💾 Stored TASK_ID for future use: $TASK_ID"
|
||||||
|
|
||||||
|
# Find main repository (try common locations)
|
||||||
|
MAIN_REPO_PATHS=(
|
||||||
|
"/Users/oda/Desktop/Projects/managing-apps"
|
||||||
|
"$(git -C "$WORKTREE_PROJECT_ROOT" rev-parse --show-toplevel 2>/dev/null || echo '')"
|
||||||
|
"$(dirname "$WORKTREE_ROOT" 2>/dev/null)/managing-apps"
|
||||||
|
)
|
||||||
|
|
||||||
|
MAIN_REPO=""
|
||||||
|
for path in "${MAIN_REPO_PATHS[@]}"; do
|
||||||
|
if [ -n "$path" ] && [ -d "$path" ] && [ -d "$path/scripts" ] && [ -f "$path/scripts/start-task-docker.sh" ]; then
|
||||||
|
MAIN_REPO="$path"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$MAIN_REPO" ]; then
|
||||||
|
echo "❌ Cannot find main repository with scripts"
|
||||||
|
echo "💡 Tried:"
|
||||||
|
for path in "${MAIN_REPO_PATHS[@]}"; do
|
||||||
|
echo " - $path"
|
||||||
|
done
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📁 Main repository: $MAIN_REPO"
|
||||||
|
echo "🔧 Setting up environment for task: $TASK_ID"
|
||||||
|
|
||||||
|
SCRIPT_DIR="$MAIN_REPO/scripts"
|
||||||
|
|
||||||
|
# Auto-detect port offset if 0 is provided
|
||||||
|
if [ "$PORT_OFFSET" = "0" ]; then
|
||||||
|
echo "🔍 Auto-detecting available port offset..."
|
||||||
|
PORT_OFFSET_FOUND=0
|
||||||
|
for offset in $(seq 1 100); do
|
||||||
|
POSTGRES_TEST=$((5432 + offset))
|
||||||
|
REDIS_TEST=$((6379 + offset))
|
||||||
|
API_TEST=$((5000 + offset))
|
||||||
|
ORLEANS_SILO_TEST=$((11111 + offset))
|
||||||
|
ORLEANS_GATEWAY_TEST=$((30000 + offset))
|
||||||
|
|
||||||
|
POSTGRES_FREE=true
|
||||||
|
REDIS_FREE=true
|
||||||
|
API_FREE=true
|
||||||
|
ORLEANS_SILO_FREE=true
|
||||||
|
ORLEANS_GATEWAY_FREE=true
|
||||||
|
|
||||||
|
if command -v lsof >/dev/null 2>&1; then
|
||||||
|
if lsof -Pi :$POSTGRES_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then
|
||||||
|
POSTGRES_FREE=false
|
||||||
|
fi
|
||||||
|
if lsof -Pi :$REDIS_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then
|
||||||
|
REDIS_FREE=false
|
||||||
|
fi
|
||||||
|
if lsof -Pi :$API_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then
|
||||||
|
API_FREE=false
|
||||||
|
fi
|
||||||
|
if lsof -Pi :$ORLEANS_SILO_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then
|
||||||
|
ORLEANS_SILO_FREE=false
|
||||||
|
fi
|
||||||
|
if lsof -Pi :$ORLEANS_GATEWAY_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then
|
||||||
|
ORLEANS_GATEWAY_FREE=false
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$POSTGRES_FREE" = "true" ] && [ "$REDIS_FREE" = "true" ] && [ "$API_FREE" = "true" ] && [ "$ORLEANS_SILO_FREE" = "true" ] && [ "$ORLEANS_GATEWAY_FREE" = "true" ]; then
|
||||||
|
PORT_OFFSET=$offset
|
||||||
|
PORT_OFFSET_FOUND=1
|
||||||
|
echo "✅ Found available port offset: $PORT_OFFSET"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$PORT_OFFSET_FOUND" = "0" ]; then
|
||||||
|
echo "❌ Could not find available port offset (checked offsets 1-100)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
POSTGRES_PORT=$((5432 + PORT_OFFSET))
|
||||||
|
API_PORT=$((5000 + PORT_OFFSET))
|
||||||
|
REDIS_PORT=$((6379 + PORT_OFFSET))
|
||||||
|
DB_NAME="managing_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
ORLEANS_DB_NAME="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
|
||||||
|
# Extract TASK_SLOT from TASK_ID numeric part (e.g., TASK-5439 -> 5439)
|
||||||
|
# This ensures unique Orleans ports for each task
|
||||||
|
TASK_SLOT=$(echo "$TASK_ID" | grep -oE '[0-9]+' | head -1)
|
||||||
|
if [ -z "$TASK_SLOT" ] || [ "$TASK_SLOT" = "0" ]; then
|
||||||
|
# Fallback: use a hash-based numeric ID if TASK_ID doesn't contain numbers
|
||||||
|
HASH=$(echo -n "$TASK_ID" | shasum -a 256 | cut -d' ' -f1 | head -c 8)
|
||||||
|
TASK_SLOT=$((0x$HASH % 9999 + 1))
|
||||||
|
echo "⚠️ TASK_ID doesn't contain a number, generated TASK_SLOT: $TASK_SLOT"
|
||||||
|
else
|
||||||
|
echo "📊 TASK_SLOT extracted from TASK_ID: $TASK_SLOT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Calculate Orleans ports based on TASK_SLOT
|
||||||
|
ORLEANS_SILO_PORT=$((11111 + (TASK_SLOT - 1) * 10))
|
||||||
|
ORLEANS_GATEWAY_PORT=$((30000 + (TASK_SLOT - 1) * 10))
|
||||||
|
ORLEANS_DASHBOARD_PORT=$((9999 + (TASK_SLOT - 1)))
|
||||||
|
|
||||||
|
echo "📊 Port offset: $PORT_OFFSET"
|
||||||
|
echo "📊 PostgreSQL: localhost:$POSTGRES_PORT"
|
||||||
|
echo "📊 Redis: localhost:$REDIS_PORT"
|
||||||
|
echo "📊 API: http://localhost:$API_PORT"
|
||||||
|
echo "💾 Database: $DB_NAME"
|
||||||
|
|
||||||
|
# Verify main database is accessible
|
||||||
|
echo "🔍 Verifying main database connection..."
|
||||||
|
if ! PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d managing -c '\q' 2>/dev/null; then
|
||||||
|
echo "❌ Cannot connect to main database at localhost:5432"
|
||||||
|
echo "💡 Starting main database..."
|
||||||
|
cd "$MAIN_REPO/src/Managing.Docker"
|
||||||
|
if command -v docker &> /dev/null && docker compose version &> /dev/null; then
|
||||||
|
docker compose -f docker-compose.yml -f docker-compose.local.yml up -d postgres
|
||||||
|
else
|
||||||
|
docker-compose -f docker-compose.yml -f docker-compose.local.yml up -d postgres
|
||||||
|
fi
|
||||||
|
echo "⏳ Waiting for database to start..."
|
||||||
|
sleep 15
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create compose file
|
||||||
|
echo "📝 Creating Docker Compose file..."
|
||||||
|
bash "$SCRIPT_DIR/create-task-compose.sh" "$TASK_ID" "$PORT_OFFSET"
|
||||||
|
COMPOSE_FILE="$MAIN_REPO/src/Managing.Docker/docker-compose.task-${TASK_ID}.yml"
|
||||||
|
|
||||||
|
# Start services (PostgreSQL and Redis only)
|
||||||
|
echo "🐳 Starting PostgreSQL and Redis..."
|
||||||
|
cd "$MAIN_REPO/src/Managing.Docker"
|
||||||
|
if command -v docker &> /dev/null && docker compose version &> /dev/null; then
|
||||||
|
docker compose -f "$COMPOSE_FILE" up -d postgres-${TASK_ID} redis-${TASK_ID}
|
||||||
|
else
|
||||||
|
docker-compose -f "$COMPOSE_FILE" up -d postgres-${TASK_ID} redis-${TASK_ID}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wait for PostgreSQL
|
||||||
|
echo "⏳ Waiting for PostgreSQL..."
|
||||||
|
for i in {1..60}; do
|
||||||
|
if PGPASSWORD=postgres psql -h localhost -p $POSTGRES_PORT -U postgres -d postgres -c '\q' 2>/dev/null; then
|
||||||
|
echo "✅ PostgreSQL is ready"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ $i -eq 60 ]; then
|
||||||
|
echo "❌ PostgreSQL not ready after 60 attempts"
|
||||||
|
if command -v docker &> /dev/null && docker compose version &> /dev/null; then
|
||||||
|
docker compose -f "$COMPOSE_FILE" down
|
||||||
|
else
|
||||||
|
docker-compose -f "$COMPOSE_FILE" down
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy database
|
||||||
|
echo "📦 Copying database from main repo..."
|
||||||
|
bash "$SCRIPT_DIR/copy-database-for-task.sh" "$TASK_ID" "localhost" "5432" "localhost" "$POSTGRES_PORT"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "❌ Database copy failed"
|
||||||
|
if command -v docker &> /dev/null && docker compose version &> /dev/null; then
|
||||||
|
docker compose -f "$COMPOSE_FILE" down
|
||||||
|
else
|
||||||
|
docker-compose -f "$COMPOSE_FILE" down
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Store configuration for later use (in worktree)
|
||||||
|
SETUP_CONFIG_FILE="$WORKTREE_PROJECT_ROOT/.vibe-setup.env"
|
||||||
|
echo "💾 Saving setup configuration..."
|
||||||
|
cat > "$SETUP_CONFIG_FILE" <<EOF
|
||||||
|
TASK_ID=$TASK_ID
|
||||||
|
TASK_SLOT=$TASK_SLOT
|
||||||
|
PORT_OFFSET=$PORT_OFFSET
|
||||||
|
POSTGRES_PORT=$POSTGRES_PORT
|
||||||
|
API_PORT=$API_PORT
|
||||||
|
REDIS_PORT=$REDIS_PORT
|
||||||
|
ORLEANS_SILO_PORT=$ORLEANS_SILO_PORT
|
||||||
|
ORLEANS_GATEWAY_PORT=$ORLEANS_GATEWAY_PORT
|
||||||
|
ORLEANS_DASHBOARD_PORT=$ORLEANS_DASHBOARD_PORT
|
||||||
|
DB_NAME=$DB_NAME
|
||||||
|
ORLEANS_DB_NAME=$ORLEANS_DB_NAME
|
||||||
|
VIBE_WORKTREE_ROOT=$WORKTREE_PROJECT_ROOT
|
||||||
|
MAIN_REPO=$MAIN_REPO
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Setup complete!"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo "📋 Configuration Details:"
|
||||||
|
echo " Task ID: $TASK_ID"
|
||||||
|
echo " Task Slot: $TASK_SLOT (from TASK_ID numeric part)"
|
||||||
|
echo " Port Offset: $PORT_OFFSET"
|
||||||
|
echo " PostgreSQL Port: $POSTGRES_PORT"
|
||||||
|
echo " Redis Port: $REDIS_PORT"
|
||||||
|
echo " API Port: $API_PORT (will be used when starting API)"
|
||||||
|
echo " Orleans Silo Port: $ORLEANS_SILO_PORT"
|
||||||
|
echo " Orleans Gateway Port: $ORLEANS_GATEWAY_PORT"
|
||||||
|
echo " Orleans Dashboard Port: $ORLEANS_DASHBOARD_PORT"
|
||||||
|
echo " Database Name: $DB_NAME"
|
||||||
|
echo " Orleans Database: $ORLEANS_DB_NAME"
|
||||||
|
echo " Configuration File: $SETUP_CONFIG_FILE"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
echo "💡 Next step: Start API and Workers using scripts/vibe-kanban/vibe-dev-server.sh"
|
||||||
|
|
||||||
|
# Explicit exit with success code to signal Vibe Kanban that setup is complete
|
||||||
|
exit 0
|
||||||
|
|
||||||
Reference in New Issue
Block a user