mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 00:01:55 +00:00
chore: share worktree port assignment across worktree tooling
The slot scan and the .env.local writer existed twice, once inline in scripts/worktree-env and once in scripts/post-create.sh. Both are now wm_assign_ports and wm_write_env_local in scripts/worktree-common.sh, so a third caller cannot drift from the other two. wm_assign_ports takes the worktree root instead of reading the process cwd, which lets it run from outside the worktree, and prints its slot line to stderr so stdout carries only the port pair. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-11
@@ -11,15 +11,5 @@ if [[ -z "$backend_port" || -z "$frontend_port" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > .env.local <<EOF
|
||||
BACKEND_PORT=$backend_port
|
||||
FRONTEND_PORT=$frontend_port
|
||||
REMOTE=http://localhost:$backend_port
|
||||
EOF
|
||||
|
||||
if [[ -n "${CARGO_FEATURES:-}" ]]; then
|
||||
echo "CARGO_FEATURES=$CARGO_FEATURES" >> .env.local
|
||||
fi
|
||||
|
||||
echo "Created .env.local with ports: backend=$backend_port, frontend=$frontend_port"
|
||||
wm_write_env_local "$(pwd)" "$backend_port" "$frontend_port"
|
||||
wm_shared_post_create "$(pwd)"
|
||||
|
||||
@@ -13,6 +13,65 @@ wm_main_repo_root() {
|
||||
cd "$(git -C "$repo_root" rev-parse --git-common-dir 2>/dev/null)/.." && pwd
|
||||
}
|
||||
|
||||
wm_port_in_use() {
|
||||
lsof -nP -iTCP:"$1" -sTCP:LISTEN &>/dev/null
|
||||
}
|
||||
|
||||
# Prints "<backend_port> <frontend_port>" for the lowest free slot. Slots are read from
|
||||
# each worktree's .env.local rather than from position in `git worktree list`: removing a
|
||||
# worktree in the middle would otherwise hand its slot to a new one while a live
|
||||
# neighbour still listens on those ports. Slot 0 belongs to the main checkout.
|
||||
wm_assign_ports() {
|
||||
local repo_root=$1
|
||||
local slot=${WM_SLOT:-}
|
||||
local used_slots=() wt_path backend_port frontend_port bp
|
||||
|
||||
if [[ -z "$slot" ]]; then
|
||||
while IFS= read -r wt_path; do
|
||||
[[ "$wt_path" == "$repo_root" ]] && continue
|
||||
[[ -f "$wt_path/.env.local" ]] || continue
|
||||
bp=$(grep '^BACKEND_PORT=' "$wt_path/.env.local" | cut -d= -f2 || true)
|
||||
if [[ -n "$bp" && "$bp" -gt 8000 ]]; then
|
||||
used_slots+=("$(( (bp - 8000) / 10 ))")
|
||||
fi
|
||||
done < <(git -C "$repo_root" worktree list --porcelain | sed -n 's/^worktree //p')
|
||||
|
||||
slot=1
|
||||
while [[ " ${used_slots[*]:-} " == *" $slot "* ]]; do
|
||||
((slot++))
|
||||
done
|
||||
echo "Auto-assigned slot $slot (used: ${used_slots[*]:-none})" >&2
|
||||
fi
|
||||
|
||||
backend_port=$((8000 + slot * 10))
|
||||
frontend_port=$((3000 + slot * 10))
|
||||
|
||||
if wm_port_in_use "$backend_port" || wm_port_in_use "$frontend_port"; then
|
||||
echo "WARNING: slot $slot ports ($backend_port/$frontend_port) already in use" >&2
|
||||
fi
|
||||
|
||||
printf '%s %s\n' "$backend_port" "$frontend_port"
|
||||
}
|
||||
|
||||
wm_write_env_local() {
|
||||
local repo_root=$1
|
||||
local backend_port=$2
|
||||
local frontend_port=$3
|
||||
local env_file="${repo_root}/.env.local"
|
||||
|
||||
cat > "$env_file" <<EOF
|
||||
BACKEND_PORT=$backend_port
|
||||
FRONTEND_PORT=$frontend_port
|
||||
REMOTE=http://localhost:$backend_port
|
||||
EOF
|
||||
|
||||
if [[ -n "${CARGO_FEATURES:-}" ]]; then
|
||||
echo "CARGO_FEATURES=$CARGO_FEATURES" >> "$env_file"
|
||||
fi
|
||||
|
||||
echo "Created .env.local with ports: backend=$backend_port, frontend=$frontend_port"
|
||||
}
|
||||
|
||||
wm_setup_database() {
|
||||
local repo_root=$1
|
||||
local env_file=$2
|
||||
|
||||
+2
-50
@@ -3,54 +3,6 @@ set -euo pipefail
|
||||
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/worktree-common.sh"
|
||||
|
||||
port_in_use() {
|
||||
lsof -nP -iTCP:"$1" -sTCP:LISTEN &>/dev/null
|
||||
}
|
||||
|
||||
if [[ -z "${WM_SLOT:-}" ]]; then
|
||||
# Scan .env.local files of existing worktrees to find which slots are claimed,
|
||||
# then pick the lowest free slot. This avoids collisions when worktrees are
|
||||
# removed and new ones created (position-based indexing would re-use slots
|
||||
# still held by surviving worktrees).
|
||||
used_slots=()
|
||||
current_dir="$(pwd)"
|
||||
while IFS= read -r wt_path; do
|
||||
[[ "$wt_path" == "$current_dir" ]] && continue
|
||||
if [[ -f "$wt_path/.env.local" ]]; then
|
||||
bp=$(grep '^BACKEND_PORT=' "$wt_path/.env.local" | cut -d= -f2 || true)
|
||||
if [[ -n "$bp" && "$bp" -gt 8000 ]]; then
|
||||
used_slots+=("$(( (bp - 8000) / 10 ))")
|
||||
fi
|
||||
fi
|
||||
done < <(git worktree list --porcelain | sed -n 's/^worktree //p')
|
||||
|
||||
# Find lowest available slot (slot 0 = 8000/3000 is reserved for main)
|
||||
WM_SLOT=1
|
||||
while [[ " ${used_slots[*]:-} " == *" $WM_SLOT "* ]]; do
|
||||
((WM_SLOT++))
|
||||
done
|
||||
echo "Auto-assigned slot $WM_SLOT (used: ${used_slots[*]:-none})"
|
||||
fi
|
||||
|
||||
# Slot-based: predictable ports for SSH forwarding
|
||||
# Slot 0 = 8000/3000, slot 1 = 8010/3010, slot 2 = 8020/3020, etc.
|
||||
backend_port=$((8000 + WM_SLOT * 10))
|
||||
frontend_port=$((3000 + WM_SLOT * 10))
|
||||
|
||||
if port_in_use "$backend_port" || port_in_use "$frontend_port"; then
|
||||
echo "WARNING: Slot $WM_SLOT ports ($backend_port/$frontend_port) already in use" >&2
|
||||
fi
|
||||
|
||||
# Generate .env.local with port overrides
|
||||
cat > .env.local <<EOF
|
||||
BACKEND_PORT=$backend_port
|
||||
FRONTEND_PORT=$frontend_port
|
||||
REMOTE=http://localhost:$backend_port
|
||||
EOF
|
||||
|
||||
if [[ -n "${CARGO_FEATURES:-}" ]]; then
|
||||
echo "CARGO_FEATURES=$CARGO_FEATURES" >> .env.local
|
||||
fi
|
||||
|
||||
echo "Created .env.local with ports: backend=$backend_port, frontend=$frontend_port"
|
||||
read -r backend_port frontend_port < <(wm_assign_ports "$(pwd)")
|
||||
wm_write_env_local "$(pwd)" "$backend_port" "$frontend_port"
|
||||
wm_shared_post_create "$(pwd)"
|
||||
|
||||
Reference in New Issue
Block a user