mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-07-25 12:01:04 +02:00
chore: auto-assign per-worktree backend port via VS Code folderOpen task
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6937e01b49
commit
58af010e60
4 changed files with 108 additions and 1 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
|
@ -23,6 +23,8 @@
|
|||
"api.app:app",
|
||||
"--reload",
|
||||
"--host", "0.0.0.0"
|
||||
// Port comes from UVICORN_PORT in api/.env (per-worktree);
|
||||
// unset -> uvicorn's default 8000. See scripts/worktree-assign-port.sh.
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"envFile": "${workspaceFolder}/api/.env",
|
||||
|
|
|
|||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
|
|
@ -1,3 +1,9 @@
|
|||
{
|
||||
"python.defaultInterpreterPath": "${workspaceFolder}/venv/bin/python"
|
||||
"python.defaultInterpreterPath": "${workspaceFolder}/venv/bin/python",
|
||||
"git.detectWorktrees": true,
|
||||
"git.worktreeIncludeFiles": [
|
||||
"api/.env",
|
||||
"api/.env.test",
|
||||
"ui/.env.local"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
23
.vscode/tasks.json
vendored
Normal file
23
.vscode/tasks.json
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
// Auto-runs when a worktree folder is opened. The first time, VS Code asks
|
||||
// to "Allow Automatic Tasks in Folder" (or run it via the command palette:
|
||||
// "Tasks: Allow Automatic Tasks in Folder"). Assigns this worktree a unique
|
||||
// backend port and points the UI env at it — see scripts/worktree-assign-port.sh.
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Assign worktree port",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/scripts/worktree-assign-port.sh",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"panel": "shared",
|
||||
"close": true
|
||||
},
|
||||
"runOptions": {
|
||||
"runOn": "folderOpen"
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
76
scripts/worktree-assign-port.sh
Executable file
76
scripts/worktree-assign-port.sh
Executable file
|
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env bash
|
||||
# Assign a unique backend port to this git worktree and rewrite the env files
|
||||
# that depend on it. Runs automatically as a VS Code "folderOpen" task (see
|
||||
# .vscode/tasks.json), so it executes once per worktree when you open it.
|
||||
#
|
||||
# Scheme:
|
||||
# - The MAIN worktree is left untouched (backend stays on uvicorn's default 8000).
|
||||
# - Each linked worktree gets the next free backend port: 8001, 8002, ...
|
||||
# - api/.env : UVICORN_PORT -> the assigned backend port
|
||||
# - ui/.env.local : BACKEND_URL -> http://localhost:<port>
|
||||
# NEXT_PUBLIC_BACKEND_URL -> http://localhost:<port>
|
||||
#
|
||||
# CORS is intentionally NOT touched: local dev runs DEPLOYMENT_MODE="oss", where
|
||||
# the API forces allow_origins=["*"] and ignores CORS_ALLOWED_ORIGINS entirely.
|
||||
#
|
||||
# Idempotent: re-running keeps an already-assigned, non-colliding port. The UI
|
||||
# dev server is left alone — `npm run dev` auto-selects a free port (3000, 3001…).
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(git rev-parse --show-toplevel)"
|
||||
MAIN="$(git worktree list --porcelain | sed -n '1s/^worktree //p')"
|
||||
[ "$ROOT" = "$MAIN" ] && { echo "[worktree] main worktree -> backend 8000 (untouched)"; exit 0; }
|
||||
|
||||
AENV="$ROOT/api/.env"
|
||||
UENV="$ROOT/ui/.env.local"
|
||||
[ -f "$AENV" ] || { echo "[worktree] no api/.env yet; skipping"; exit 0; }
|
||||
|
||||
# Echo the UVICORN_PORT value from an env file (empty if unset/missing).
|
||||
port_of() { { grep -E '^[[:space:]]*UVICORN_PORT=' "$1" 2>/dev/null | tail -1 | sed -E 's/^[^=]*=//; s/[[:space:]]//g'; } || true; }
|
||||
|
||||
# Ports already in use by OTHER worktrees (main implicitly uses 8000).
|
||||
used=(8000)
|
||||
while IFS= read -r line; do
|
||||
case "$line" in
|
||||
"worktree "*)
|
||||
wt="${line#worktree }"
|
||||
[ "$wt" = "$ROOT" ] && continue
|
||||
p="$(port_of "$wt/api/.env")"
|
||||
[ -n "$p" ] && used+=("$p")
|
||||
;;
|
||||
esac
|
||||
done < <(git worktree list --porcelain)
|
||||
|
||||
mine="$(port_of "$AENV")"
|
||||
|
||||
# Keep my port if it's set and not claimed by another worktree; else take max+1.
|
||||
reassign=1
|
||||
if [ -n "$mine" ]; then
|
||||
reassign=0
|
||||
for u in "${used[@]}"; do [ "$u" = "$mine" ] && reassign=1; done
|
||||
fi
|
||||
if [ "$reassign" -eq 1 ]; then
|
||||
max=0
|
||||
for u in "${used[@]}"; do [ "$u" -gt "$max" ] && max="$u"; done
|
||||
B=$((max + 1))
|
||||
else
|
||||
B="$mine"
|
||||
fi
|
||||
|
||||
# Insert or update KEY=VALUE in an env file, preserving everything else.
|
||||
upsert() {
|
||||
local key="$1" val="$2" file="$3"
|
||||
if grep -qE "^[[:space:]]*${key}=" "$file"; then
|
||||
sed -i.bak -E "s|^[[:space:]]*${key}=.*|${key}=${val}|" "$file" && rm -f "$file.bak"
|
||||
else
|
||||
printf '\n%s=%s\n' "$key" "$val" >> "$file"
|
||||
fi
|
||||
}
|
||||
|
||||
upsert UVICORN_PORT "$B" "$AENV"
|
||||
if [ -f "$UENV" ]; then
|
||||
upsert BACKEND_URL "http://localhost:$B" "$UENV"
|
||||
upsert NEXT_PUBLIC_BACKEND_URL "http://localhost:$B" "$UENV"
|
||||
fi
|
||||
|
||||
echo "[worktree] $(basename "$ROOT"): backend=$B (UI auto-port via 'npm run dev')"
|
||||
Loading…
Add table
Add a link
Reference in a new issue