|
| 1 | +# Better Testing Server Setup (init.sh) |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +Make init.sh suitable for running multiple dev environments concurrently (across different repo clones/worktrees) and improve the Go backend development loop with auto-recompile on file changes. |
| 6 | + |
| 7 | +## Use Case |
| 8 | + |
| 9 | +Multiple repos/worktrees running dev environments simultaneously. Each gets its own randomized ports so there are no collisions. |
| 10 | + |
| 11 | +## Changes |
| 12 | + |
| 13 | +### 1. PID File Management |
| 14 | + |
| 15 | +**Current:** `--stop` uses `pgrep -f` / `pkill -f` with name patterns (e.g. `"bin/backend"`, `"webpack serve"`). Fragile, can kill processes from other repos. |
| 16 | + |
| 17 | +**New:** |
| 18 | + |
| 19 | +- PID files stored in `.dev-pids/` directory (created on startup) |
| 20 | +- Files: `backend.pid`, `webpack.pid`, `backend-watcher.pid` |
| 21 | +- Console container ID stored in `.dev-pids/console.cid` (via `podman run --cidfile`) |
| 22 | +- Each `start_*` function writes `$!` (backgrounded PID) to its PID file |
| 23 | +- Each `stop_*` function reads the PID file, sends SIGTERM, waits briefly, removes the PID file |
| 24 | +- `--stop` iterates over whatever PID/CID files exist (safe if only some services are running) |
| 25 | + |
| 26 | +### 2. Port Randomization |
| 27 | + |
| 28 | +**Current:** Hardcoded ports: backend 8080, webpack 9001, console 9000. |
| 29 | + |
| 30 | +**New:** |
| 31 | + |
| 32 | +- By default, init.sh uses the same hardcoded defaults as today (8080, 9001, 9000) so human testers are not surprised |
| 33 | +- When `--randomize-ports` flag is passed, init.sh picks three random available ports from range 10000-60000 |
| 34 | +- A `random_free_port()` helper function loops until it finds an unused port (TCP probe check) |
| 35 | +- `.dev-env.json` is always written at project root, regardless of whether ports are randomized or default: |
| 36 | + ```json |
| 37 | + { |
| 38 | + "backendPort": 12345, |
| 39 | + "pluginPort": 12346, |
| 40 | + "consolePort": 12347 |
| 41 | + } |
| 42 | + ``` |
| 43 | +- `--stop` removes `.dev-env.json` |
| 44 | + |
| 45 | +### 3. Go Backend Auto-Recompile |
| 46 | + |
| 47 | +**Current:** `start_backend` builds once and runs the binary. Changes require manual restart. |
| 48 | + |
| 49 | +**New:** |
| 50 | + |
| 51 | +- After backend starts, init.sh spawns a watcher process in the background |
| 52 | +- Watcher uses `inotifywait -m -r -e modify,create,delete,move --include '\.(go|mod|sum)$' backend/` to monitor for Go source and module changes |
| 53 | +- On each event, debounce (1 second) to let rapid successive changes settle |
| 54 | +- Rebuild strategy (build-then-swap): |
| 55 | + 1. Build to temporary binary: `go build -buildvcs=false -o ../bin/backend-tmp .` |
| 56 | + 2. If build fails: log error to `.dev-logs/backend.log`, keep current backend running, continue watching |
| 57 | + 3. If build succeeds: kill current backend (via PID file), move `backend-tmp` to `backend`, start new process, write new PID to `.dev-pids/backend.pid` |
| 58 | +- Watcher gets its own PID file: `.dev-pids/backend-watcher.pid` |
| 59 | +- init.sh checks for `inotifywait` at startup. If missing, prints warning and skips the watcher (backend still works, no auto-reload) |
| 60 | + |
| 61 | +### 4. Port Passing to Downstream Scripts |
| 62 | + |
| 63 | +**start-console.sh:** |
| 64 | + |
| 65 | +- Accepts CLI arguments: `--backend-port`, `--plugin-port`, `--console-port` |
| 66 | +- Each argument falls back to the current hardcoded default (8080, 9001, 9000) so the script works standalone |
| 67 | +- Replaces hardcoded port values in `BRIDGE_PLUGINS`, `BRIDGE_PLUGIN_PROXY`, and the `-p` container port flag |
| 68 | + |
| 69 | +**webpack.config.ts:** |
| 70 | + |
| 71 | +- Dev server port changes from hardcoded `9001` to `Number(process.env.PLUGIN_PORT) || 9001` |
| 72 | +- init.sh exports `PLUGIN_PORT` before running `yarn start` |
| 73 | + |
| 74 | +**init.sh invocations:** |
| 75 | + |
| 76 | +```bash |
| 77 | +PLUGIN_PORT="$PLUGIN_PORT" yarn start > "$LOG_DIR/webpack.log" 2>&1 & |
| 78 | + |
| 79 | +./start-console.sh \ |
| 80 | + --backend-port "$BACKEND_PORT" \ |
| 81 | + --plugin-port "$PLUGIN_PORT" \ |
| 82 | + --console-port "$CONSOLE_PORT" \ |
| 83 | + > "$LOG_DIR/console.log" 2>&1 & |
| 84 | +``` |
| 85 | + |
| 86 | +### 5. Agent Awareness |
| 87 | + |
| 88 | +Agents need to know where the dev server is running so they can connect to it (e.g. for browser testing or API calls). |
| 89 | + |
| 90 | +- **CLAUDE.md**: Add `.dev-env.json` and `.dev-logs/` to the knowledge base table, noting dev server ports and log file locations respectively |
| 91 | +- **WORKFLOW.md**: Add a step to the Startup Sequence (after "Run `./init.sh`") to read `.dev-env.json` and note the ports |
| 92 | +- **`.claude/commands/init-session.md`**: Add a step to read `.dev-env.json` and report the ports to the user |
| 93 | + |
| 94 | +## Files Modified |
| 95 | + |
| 96 | +| File | Change | |
| 97 | +|------|--------| |
| 98 | +| `init.sh` | PID files, `--randomize-ports` flag, `.dev-env.json` output, inotifywait backend watcher, pass ports downstream, `--stop` reads PIDs/CID | |
| 99 | +| `start-console.sh` | Accept `--backend-port`, `--plugin-port`, `--console-port` CLI args with fallback defaults | |
| 100 | +| `webpack.config.ts` | Read `PLUGIN_PORT` env var with fallback to 9001 | |
| 101 | +| `.gitignore` | Add `.dev-pids/` and `.dev-env.json` | |
| 102 | +| `.dockerignore` | Add `.dev-pids/` and `.dev-env.json` | |
| 103 | +| `CLAUDE.md` | Add `.dev-env.json` and `.dev-logs/` to knowledge base table | |
| 104 | +| `docs/WORKFLOW.md` | Add port discovery step to Startup Sequence | |
| 105 | +| `.claude/commands/init-session.md` | Add step to read and report dev server ports | |
| 106 | + |
| 107 | +No new files created (besides runtime artifacts which are gitignored/dockerignored). |
| 108 | + |
| 109 | +## Backwards Compatibility |
| 110 | + |
| 111 | +All three modified files retain current default behavior when invoked without the new arguments/env vars. Running `./start-console.sh` directly or `yarn start` without init.sh produces the same ports as today. |
| 112 | + |
| 113 | +## Prerequisites |
| 114 | + |
| 115 | +- `inotify-tools` package for the Go backend watcher. Gracefully degrades if missing (warning printed, watcher skipped). |
0 commit comments