mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 08:00:59 +00:00
chore: narrow the shared helper to .env.local writing
Slot assignment goes back into worktree-env: it had one caller, and the herdr plugin it was extracted for provisions worktrees before the checkout is usable, so it carries its own copy rather than sourcing one whose contents depend on whichever branch the main checkout sits on. Writing .env.local stays shared - worktree-env and post-create.sh each had the same eleven lines. Also corrects AGENTS.md: .env.local is a shared format rather than a shared function, and WM_DB_NAME comes from it rather than webmux's runtime.env. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -64,9 +64,9 @@ they set disjoint environment variables, so check which one you are in:
|
||||
|
||||
See `backend/AGENTS.md` to restart the backend with different cargo features. Under herdr, `herdr
|
||||
--skill` prints a full reference for inspecting and driving panes and agents, and the plugins that
|
||||
provision worktrees live in `windmill-labs/windmill-herdr` — clone it and run `./setup.sh` to
|
||||
install them and the keybindings they need. The commands below are for a plain checkout with
|
||||
nothing running.
|
||||
provision worktrees live in the private `windmill-labs/windmill-herdr` — clone it and run
|
||||
`./setup.sh` to install them and the keybindings they need. The commands below are for a plain
|
||||
checkout with nothing running.
|
||||
|
||||
- **Backend**: `cargo run` from `backend/` (API at http://localhost:8000)
|
||||
- **Frontend**: `REMOTE=http://localhost:8000 npm run dev` from `frontend/` (port 3000+)
|
||||
@@ -78,9 +78,8 @@ nothing running.
|
||||
### Per-worktree ports and database
|
||||
|
||||
**`.env.local` in the worktree root is the portable answer** — `BACKEND_PORT`,
|
||||
`FRONTEND_PORT`, `REMOTE`, `DATABASE_URL`, `CARGO_FEATURES`, `WM_DB_NAME`. Both managers write it
|
||||
through the same helper (`wm_write_env_local` in `scripts/worktree-common.sh`), so it is correct
|
||||
whichever one you are in, and it is readable despite the name.
|
||||
`FRONTEND_PORT`, `REMOTE`, `DATABASE_URL`, `CARGO_FEATURES`, `WM_DB_NAME`. Both managers write
|
||||
those fields, so it is correct whichever one you are in, and it is readable despite the name.
|
||||
|
||||
webmux additionally writes `$(git rev-parse --git-dir)/webmux/runtime.env`, which every pane
|
||||
sources at startup and which carries the extras `.env.local` lacks: `WEBMUX_*`, `WM_CLONE_DB`,
|
||||
@@ -98,11 +97,12 @@ opt-in via `WM_CLONE_DB` (in `.webmux.yaml` under webmux, or the `windmill.workt
|
||||
|
||||
The database is named after the **worktree directory, not the branch** (`scripts/worktree-common.sh`):
|
||||
`windmill_` + the directory basename with `-` → `_`, which Postgres then truncates at 63
|
||||
characters. Branch `hugo/win-2340-ai-agent-evals-standalone-agent-runs-and-eval-datasets` sits in
|
||||
a worktree directory named `win-2340-…`, so its database is
|
||||
`windmill_win_2340_ai_agent_evals_standalone_agent_runs_and_eval` — no `hugo_`, and the tail
|
||||
chopped. Take `WM_DB_NAME` from `runtime.env` instead of reconstructing the name. Read those, or
|
||||
discover from what is already running:
|
||||
characters. The two managers lay worktrees out differently, so the same branch lands in different
|
||||
directories and therefore different databases: under webmux, branch
|
||||
`hugo/win-2340-ai-agent-evals-standalone-agent-runs-and-eval-datasets` sits in a directory named
|
||||
`win-2340-…`, so its database is `windmill_win_2340_ai_agent_evals_standalone_agent_runs_and_eval`
|
||||
— no `hugo_`, and the tail chopped. Take `WM_DB_NAME` from `.env.local` instead of reconstructing
|
||||
the name. Read that, or discover from what is already running:
|
||||
|
||||
```bash
|
||||
psql postgres://postgres:changeme@localhost:5432/postgres -tAc \
|
||||
|
||||
@@ -13,46 +13,8 @@ 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"
|
||||
}
|
||||
|
||||
# Written by both worktree entry points — `worktree-env` by hand, `post-create.sh` from the
|
||||
# webmux hook — and read by agents to find their own ports, so the two must not drift.
|
||||
wm_write_env_local() {
|
||||
local repo_root=$1
|
||||
local backend_port=$2
|
||||
|
||||
+38
-1
@@ -3,6 +3,43 @@ set -euo pipefail
|
||||
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/worktree-common.sh"
|
||||
|
||||
read -r backend_port frontend_port < <(wm_assign_ports "$(pwd)")
|
||||
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
|
||||
|
||||
wm_write_env_local "$(pwd)" "$backend_port" "$frontend_port"
|
||||
wm_shared_post_create "$(pwd)"
|
||||
|
||||
Reference in New Issue
Block a user