fix(tmux): isolate e2e tests on a throwaway socket, never the live yeschef server#24
Merged
Conversation
…ef` server Root cause: the tmux `-L` socket name was a hard `const TMUX_SOCKET = "yeschef"` in the real backend, and `tests/e2e.rs` mirrored it with its own `"yeschef"` const. So the e2e suite — via both the spawned `yeschef` binary and its direct `tmux` helpers — created and killed sessions on the *same* private server the head chef and every live line cook run on. Running the suite from inside a live yeschef session could tear those sessions down (a stray `kill-server` would nuke the whole brigade). Fix — make the socket configurable and route everything through one source of truth: - `backend::real`: replace the const with `DEFAULT_TMUX_SOCKET` + `resolve_tmux_socket()`, reading `YESCHEF_TMUX_SOCKET` (default `yeschef`). Resolve once per backend in `new` and use it in `cmd()`. Production is unchanged (unset → `yeschef`). - `tests/e2e.rs`: pick a unique, throwaway `-L` socket per run (`yeschef-test-<pid>-<nanos>`), export it as `YESCHEF_TMUX_SOCKET` for every spawned binary, and point the tests' own `tmux`/cleanup helpers at it too. - `docs/tmux-backend-demo-setup.sh`: its reset `kill-server` hit the live `yeschef` socket — pin it to a `yeschef-demo` throwaway socket instead. - Update DEVELOPMENT.md / flake.nix / module docs to describe the configurable socket. Verified: ran the full `--ignored` e2e suite (17 passed) from inside a live yeschef line-cook session. The suite stood up and tore down its own `yeschef-test-…` server; the operator's `yeschef` server (`headchef` + the running line cook) was untouched and this session survived.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
The tmux
-Lsocket name was a hardconst TMUX_SOCKET = "yeschef"in the real backend (src/backend/real.rs), andtests/e2e.rsmirrored it with its own"yeschef"const. So the e2e suite — via both theassert_cmd-spawnedyeschefbinary and its directtmuxhelpers (tmux(),WindowCleanup) — created and killed sessions on the same private server that the head chef and every live line cook run on.Running
cargo test --test e2e -- --ignoredfrom inside a live yeschef session therefore tore down the very tmux server the shell was living in — killing the running line cook and the head chef. A straykill-serveron that socket would nuke the whole brigade. A live footgun of the same shape existed indocs/tmux-backend-demo-setup.sh, whose reset step rantmux -L yeschef kill-server.This was a structural isolation defect: tests (and dev/demo runs) could touch the operator's live tmux server.
The fix
Make the socket configurable and route every tmux invocation through one source of truth:
backend::real— replace the const withDEFAULT_TMUX_SOCKET("yeschef") +resolve_tmux_socket(), which readsYESCHEF_TMUX_SOCKETand falls back to the default when unset/empty. The socket is resolved once per backend innewand used incmd(). Production behavior is unchanged — unset env →yeschef.tests/e2e.rs— pick a unique, throwaway-Lsocket per run (yeschef-test-<pid>-<nanos>, computed once viaOnceLock), export it asYESCHEF_TMUX_SOCKETfor every spawned binary (TestEnv::cmd), and point the tests' owntmux/cleanup helpers at the same name. The suite now stands up and tears down its own private server; no test path can reach theyeschefsocket.docs/tmux-backend-demo-setup.sh— pin the demo (and its resetkill-server) to ayeschef-demothrowaway socket viaYESCHEF_TMUX_SOCKET, so it can never nuke the operator's live server.DEVELOPMENT.md,flake.nixcomments, and the module/e2e headers updated to describe the configurable socket.Verification
Ran the full
--ignorede2e suite from inside a live yeschef line-cook session (TMUX=.../yeschef,...), the exact scenario that used to self-destruct:yeschefserver hadheadchef+yeschef-yeschef-fix-test-socket(this session).cargo test --test e2e -- --ignored --test-threads=1→ 17 passed.yeschefserver was untouched — both sessions still alive, this session survived. The tests ran onyeschef-test-0000cb3e-…, which afterward reportedno server running(stood up and tore itself down).Also clean:
cargo build,cargo fmt --check,cargo clippy --all-targets -- -D warnings -D clippy::pedantic,cargo test --bin yeschef(67 passed), and the flakenixfmtcheck.