mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-26 08:01:38 +00:00
Improve workmux dev workflow scripts and docs (#8078)
- Add CARGO_FEATURES passthrough: backend pane reads from .env.local, wm-cursor supports --features flag on add/open commands - Fix node_modules copy in worktrees: use cp -a to preserve .bin/ symlinks that cp -r would dereference (fixes openapi-ts errors) - Fix EE repo discovery from worktrees: resolve main repo root via git-common-dir, search multiple candidate paths - Add cursor session cleanup to worktree-cleanup (pre_remove hook) - Use workmux -b flag in wmc add, remove npm install from frontend pane - Change openBrowserOnce for Cursor port forwarding - Document cargo features usage and fix stale files.symlink reference in README Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -57,9 +57,9 @@ panes:
|
||||
When restarting backend or frontend, make sure to use the ports listed in .env.local.\n
|
||||
Because we are running backend with cargo watch, to verify your changes, just check the logs in the backend pane. No need for cargo check."
|
||||
focus: true
|
||||
- command: 'ROOT="$(git rev-parse --show-toplevel)"; [ -f "$ROOT/.env.local" ] && source "$ROOT/.env.local"; cd "$ROOT/backend" && PORT=${BACKEND_PORT:-8000} cargo watch -x run'
|
||||
- command: 'ROOT="$(git rev-parse --show-toplevel)"; [ -f "$ROOT/.env.local" ] && source "$ROOT/.env.local"; cd "$ROOT/backend" && PORT=${BACKEND_PORT:-8000} cargo watch -x "run ${CARGO_FEATURES:+--features $CARGO_FEATURES}"'
|
||||
split: horizontal
|
||||
- command: 'ROOT="$(git rev-parse --show-toplevel)"; [ -f "$ROOT/.env.local" ] && source "$ROOT/.env.local"; cd "$ROOT/frontend" && npm install && npm run generate-backend-client && REMOTE=${REMOTE:-http://localhost:${BACKEND_PORT:-8000}} npm run dev -- --port ${FRONTEND_PORT:-3000} --host 0.0.0.0'
|
||||
- command: 'ROOT="$(git rev-parse --show-toplevel)"; [ -f "$ROOT/.env.local" ] && source "$ROOT/.env.local"; cd "$ROOT/frontend" && npm run generate-backend-client && REMOTE=${REMOTE:-http://localhost:${BACKEND_PORT:-8000}} npm run dev -- --port ${FRONTEND_PORT:-3000} --host 0.0.0.0'
|
||||
split: vertical
|
||||
|
||||
files:
|
||||
|
||||
+30
-1
@@ -170,7 +170,8 @@ The setup is defined in `.workmux.yaml` at the repo root. Key sections:
|
||||
- **`post_create`**: Runs `scripts/worktree-env` to generate `.env.local` with port assignments
|
||||
- **`panes`**: Defines the tmux layout (agent, backend, frontend)
|
||||
- **`files.copy`**: Copies `backend/.env` and `scripts/` into each worktree
|
||||
- **`files.symlink`**: Symlinks `node_modules` and `.svelte-kit` to avoid reinstalling per worktree
|
||||
|
||||
The `post_create` hook also copies `frontend/node_modules` using `cp -a` (preserves `.bin/` symlinks that `cp -r` would dereference).
|
||||
|
||||
## Enterprise (EE) Code Access
|
||||
|
||||
@@ -247,6 +248,34 @@ wmc close my-feature
|
||||
|
||||
This kills the grouped tmux session and calls `workmux close` to close the tmux window. The worktree and branch are preserved. Grouped sessions are also automatically cleaned up when you `workmux rm` a worktree (via `scripts/worktree-cleanup`).
|
||||
|
||||
## Cargo Features
|
||||
|
||||
To build the backend with specific Cargo features (e.g., `enterprise`, `parquet`), pass them via `CARGO_FEATURES`. The backend pane reads this from `.env.local` and appends `--features <value>` to the `cargo watch` command.
|
||||
|
||||
**With `wm` (workmux):**
|
||||
|
||||
Set `CARGO_FEATURES` as an environment variable before creating the worktree:
|
||||
|
||||
```bash
|
||||
CARGO_FEATURES="enterprise,parquet" wm add my-feature
|
||||
```
|
||||
|
||||
This gets written to `.env.local` by the `post_create` hook (`scripts/worktree-env`), and the backend pane picks it up automatically.
|
||||
|
||||
**With `wmc` (wm-cursor):**
|
||||
|
||||
Use the `--features` flag:
|
||||
|
||||
```bash
|
||||
# Create a new worktree with features
|
||||
wmc add --features "enterprise,parquet" -A -p "implement feature X"
|
||||
|
||||
# Open an existing worktree with different features
|
||||
wmc open my-feature --features "enterprise,parquet"
|
||||
```
|
||||
|
||||
The `--features` flag exports `CARGO_FEATURES` so the `post_create` hook writes it to `.env.local`. When using `wmc open`, it updates the existing `.env.local` with the new features.
|
||||
|
||||
## Login
|
||||
|
||||
Default credentials: `admin@windmill.dev` / `changeme`
|
||||
|
||||
+56
-11
@@ -81,7 +81,7 @@ setup_grouped_session() {
|
||||
},
|
||||
"remote.portsAttributes": {
|
||||
"'$backend_port'": { "label": "Backend", "onAutoForward": "silent" },
|
||||
"'$frontend_port'": { "label": "Frontend", "onAutoForward": "openBrowser" }
|
||||
"'$frontend_port'": { "label": "Frontend", "onAutoForward": "openBrowserOnce" }
|
||||
}'
|
||||
fi
|
||||
fi
|
||||
@@ -102,18 +102,47 @@ SETTINGS
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Feature flag parsing ---
|
||||
# Extracts --features <value> from args, exports CARGO_FEATURES, returns remaining args.
|
||||
# Usage: parse_features_flag "$@"; set -- "${remaining_args[@]}"
|
||||
|
||||
parse_features_flag() {
|
||||
remaining_args=()
|
||||
while (( $# )); do
|
||||
case $1 in
|
||||
--features)
|
||||
if (( $# < 2 )); then
|
||||
print -u2 "Error: --features requires a value"
|
||||
exit 1
|
||||
fi
|
||||
export CARGO_FEATURES=$2
|
||||
shift 2
|
||||
;;
|
||||
--features=*)
|
||||
export CARGO_FEATURES=${1#--features=}
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
remaining_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# --- Subcommands ---
|
||||
|
||||
cmd_add() {
|
||||
ensure_tmux
|
||||
check_dev_db
|
||||
|
||||
parse_features_flag "$@"
|
||||
set -- "${remaining_args[@]}"
|
||||
|
||||
# Snapshot worktree list before
|
||||
local -a before=("${(@f)$(git worktree list --porcelain | grep '^worktree ')}")
|
||||
local prev_window=$(tmux display-message -p '#I')
|
||||
|
||||
workmux add "$@"
|
||||
tmux select-window -t $prev_window
|
||||
workmux add -b "$@"
|
||||
|
||||
# Diff to find the new entry
|
||||
local -a after=("${(@f)$(git worktree list --porcelain | grep '^worktree ')}")
|
||||
@@ -140,11 +169,24 @@ cmd_open() {
|
||||
ensure_tmux
|
||||
check_dev_db
|
||||
|
||||
parse_features_flag "$@"
|
||||
set -- "${remaining_args[@]}"
|
||||
|
||||
# Write CARGO_FEATURES to .env.local if specified
|
||||
if [[ -n ${CARGO_FEATURES-} ]]; then
|
||||
local wt_env=$(workmux path $name)/.env.local
|
||||
if [[ -f $wt_env ]]; then
|
||||
# Remove existing CARGO_FEATURES line and append new one
|
||||
sed -i '/^CARGO_FEATURES=/d' $wt_env
|
||||
echo "CARGO_FEATURES=$CARGO_FEATURES" >> $wt_env
|
||||
fi
|
||||
fi
|
||||
|
||||
local wt_path=$(workmux path $name)
|
||||
local prev_window=$(tmux display-message -p '#I')
|
||||
local prev_target=$(tmux display-message -p '#{session_name}:#{window_index}')
|
||||
|
||||
workmux open $name "$@"
|
||||
tmux select-window -t $prev_window
|
||||
tmux select-window -t $prev_target
|
||||
setup_grouped_session $name $wt_path
|
||||
$cursor_bin -n $wt_path
|
||||
print "Opened Cursor for ${name}"
|
||||
@@ -210,7 +252,7 @@ TASKS
|
||||
},
|
||||
"remote.portsAttributes": {
|
||||
"8000": { "label": "Backend", "onAutoForward": "silent" },
|
||||
"3000": { "label": "Frontend", "onAutoForward": "openBrowser" },
|
||||
"3000": { "label": "Frontend", "onAutoForward": "openBrowserOnce" },
|
||||
"5432": { "label": "PostgreSQL", "onAutoForward": "silent" }
|
||||
}
|
||||
}'
|
||||
@@ -257,10 +299,13 @@ case ${1-} in
|
||||
print -u2 "Usage: wm-cursor <add|open|close|setup> [args...]"
|
||||
print -u2 ""
|
||||
print -u2 "Subcommands:"
|
||||
print -u2 " add [workmux-add-args...] Create worktree + open Cursor"
|
||||
print -u2 " open <name> Open Cursor for existing worktree"
|
||||
print -u2 " close <name> Clean up grouped tmux session"
|
||||
print -u2 " setup <repo-root> Set up .vscode settings, tasks + wmc alias"
|
||||
print -u2 " add [--features <f>] [workmux-add-args...] Create worktree + open Cursor"
|
||||
print -u2 " open <name> [--features <f>] Open Cursor for existing worktree"
|
||||
print -u2 " close <name> Clean up grouped tmux session"
|
||||
print -u2 " setup <repo-root> Set up .vscode settings, tasks + wmc alias"
|
||||
print -u2 ""
|
||||
print -u2 "Options:"
|
||||
print -u2 " --features <features> Cargo features for the backend (e.g. \"enterprise,parquet\")"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
+26
-8
@@ -46,8 +46,20 @@ 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"
|
||||
|
||||
# --- Copy frontend/node_modules preserving symlinks ---
|
||||
# cp -a preserves .bin/ symlinks that cp -r would dereference, breaking require() paths
|
||||
main_repo_root="$(cd "$(git rev-parse --git-common-dir 2>/dev/null)/.." && pwd)"
|
||||
if [[ -n "$main_repo_root" && -d "$main_repo_root/frontend/node_modules" ]]; then
|
||||
cp -a "$main_repo_root/frontend/node_modules" frontend/
|
||||
echo "Copied frontend/node_modules (with symlinks preserved)"
|
||||
fi
|
||||
|
||||
# --- Allow direnv so the nix devshell activates in pane commands ---
|
||||
if command -v direnv &>/dev/null && [ -f .envrc ]; then
|
||||
direnv allow
|
||||
@@ -55,14 +67,20 @@ if command -v direnv &>/dev/null && [ -f .envrc ]; then
|
||||
fi
|
||||
|
||||
# --- Create matching windmill-ee-private worktree ---
|
||||
# Check parent directory first (sibling to worktree root), then fall back to home
|
||||
parent_dir="$(cd "$(pwd)/.." && pwd)"
|
||||
if [ -d "${parent_dir}/windmill-ee-private" ]; then
|
||||
ee_repo="${parent_dir}/windmill-ee-private"
|
||||
else
|
||||
ee_repo="${HOME}/windmill-ee-private"
|
||||
fi
|
||||
if [ -d "$ee_repo" ]; then
|
||||
# Find ee repo: sibling to the main worktree (git toplevel of the main checkout),
|
||||
# then try parent of cwd, then fall back to home
|
||||
ee_repo=""
|
||||
for candidate in \
|
||||
"${main_repo_root:+${main_repo_root}/../windmill-ee-private}" \
|
||||
"$(pwd)/../windmill-ee-private" \
|
||||
"${HOME}/windmill-ee-private" \
|
||||
"${HOME}/projects/windmill-ee-private"; do
|
||||
if [ -n "$candidate" ] && [ -d "$candidate" ]; then
|
||||
ee_repo="$(cd "$candidate" && pwd)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -n "$ee_repo" ]; then
|
||||
branch=$(git branch --show-current 2>/dev/null || true)
|
||||
wt_basename=$(basename "$(pwd)")
|
||||
ee_worktree_dir="${ee_repo}__worktrees/${wt_basename}"
|
||||
|
||||
Reference in New Issue
Block a user