Remove CLI backend assumptions and add docker fallback prompt #434
Reference in New Issue
Block a user
Delete Branch "remove-cli-backend-assumptions"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #344.
Summary
--backendflag fromcli.py start: backend selection is now driven exclusively byBOT_BOTTLE_BACKENDenv var or two-tier auto-selection.resumeand./cli.py backendstill accept explicit names.cli.py cleanup: skip unavailable backends (e.g.macos-containeron Linux) rather than callingprepare_cleanup()which calledrequire_container()and died.--backend=macos-containerfromfirecracker/util.pyerror message.[i]nstall instructions / [d]ocker anyway / [q]uitprompt. When docker is also absent, print VM install instructions and exit.The VM preference is platform-aware:
macos-containeron macOS,firecrackeron KVM-capable Linux. A KVM-capable host without thefirecrackerbinary still selectsfirecracker(unchanged) so its preflight prints an install pointer instead of silently falling back to docker.@@ -669,3 +669,3 @@def _default_backend_name() -> str:def _read_tty_line() -> str:This logic is undoubtably used other places, should be called from a util script/consolidate where this logic is defined
@@ -669,3 +669,3 @@def _default_backend_name() -> str:def _read_tty_line() -> str:Good call — the same logic lives in
cli/_common.py::read_tty_line. Will move it tobot_bottle/util.pyso both the CLI layer and the backend can import from one place.Found one blocking issue:
start --headlesscan now block on an interactive backend prompt. The headless launch eventually callsget_bottle_backend()without conveying that it is non-interactive. On a Docker-only host with noBOT_BOTTLE_BACKEND,_auto_select_backend()reads/dev/ttyfor the[i/d/q]choice. This violates the documented headless contract and can hang CI, webhook dispatch, and orchestrators. Headless selection should either fail immediately with an actionable message or select Docker according to an explicit non-interactive policy; it must not prompt.The focused suite passed (67 tests via unittest), but the headless tests mock
_launch_bottlebefore backend resolution, so they do not exercise this path._auto_select_backend gains a prompt parameter (default True). When prompt=False the docker-fallback [i/d/q] menu is skipped and the call dies immediately with an actionable message ("set BOT_BOTTLE_BACKEND=docker or install a VM backend"), preventing hangs in CI, webhook dispatch, and orchestrator launches. prepare_with_preflight passes prompt=not spec.headless so the headless start path can never block waiting for TTY input it cannot receive.Fixed in
d9e685e._auto_select_backendnow acceptsprompt: bool = True. Whenprompt=Falsethe docker-fallback[i/d/q]menu is replaced by an immediatedie()with an actionable message ("set BOT_BOTTLE_BACKEND=docker or install the VM backend"), so no TTY read can block a headless caller.prepare_with_preflightpassesprompt=not spec.headless, wiring the flag fromBottleSpecinto backend selection without threading a new parameter through_launch_bottle. Addedtest_docker_fallback_non_interactive_diesto cover the new branch.@@ -682,0 +726,4 @@"docker is less secure than VM backends — ""containers share the host kernel.")if not prompt:Added
if not prompt: die(...)here. Whenprompt=False(headless / CI) the docker-fallback prompt is bypassed entirely —die()emits an actionable message and exits instead of blocking onread_tty_line().Re-reviewed at
c7375051fd3b0afb5a9e825c7dc6cd7d6063cacc. The prior blocking issue is resolved: headless launches now passprompt=Falseinto backend auto-selection, which exits with actionable guidance instead of reading from a TTY, and the selector has direct regression coverage. No new findings. The 68 focused affected tests pass.Re-reviewed at
c7375051fd3b0afb5a9e825c7dc6cd7d6063cacc. The prior blocking issue is resolved and I found no new issues. The 68 focused affected tests pass.