Skip to content

feat(cli): honest first run — wait for the backend, diagnose Docker failures, show image progress - #98

Merged
Derssa merged 3 commits into
mainfrom
feat/honest-start
Sep 4, 2026
Merged

Derssa merged 3 commits into
mainfrom
feat/honest-start

Conversation

@OthmaneZ05

Copy link
Copy Markdown
Collaborator

Summary of Changes

torollo start used to be blind on a first run: it only checked docker info's exit code, spawned the backend with its output discarded, printed "ready" immediately and opened the browser 1.2 s later — before the backend listened, and while the backend was pulling five images (minutes) with no signal. Three real failures were misreported: Docker Desktop on macOS (the docker CLI follows contexts, the backend's dockerode does not, so docker info passed while the backend hit socket_not_found), a user outside the docker group (reduced to "not installed"), and rootless Docker (host forwarding rules failed silently, breaking subnets/NAT/security groups without a word).

This PR makes the first run honest:

  • Backend — a small startupState records what the startup routine is doing (network, host forwarding, image by image with pull/build action). GET /health now exposes it as startup, plus checks.docker.rootless and checks.network (ok / unsupported (rootless) / failed). The daemon ping is bounded (10 s → timeout reason). ensureHostForwarding now waits for the privileged container's exit code instead of logging "applied successfully" unconditionally, and skips it on rootless daemons. The three duplicated local-build blocks (Mongo/Redis/RabbitMQ) collapse into one table-driven helper that also checks the apk/apt exit code. Existing response fields are unchanged, so the frontend probe and telemetry are untouched.
  • CLI — bin/cli.js is split into small testable modules under bin/lib/. start now: resolves the Docker endpoint the way the backend will (DOCKER_HOST, else the active docker context, handed down as DOCKER_HOST so both sides target the same daemon); starts the backend with its output in ~/.torollo/logs/backend.log; waits for /health (30 s timeout); gives a starting daemon a 20 s grace; on failure prints one diagnosis per reason with the fix command for the OS (socket_not_found, permission_denied, connection_refused, timeout, unknown); follows the image preloading with one line per image ("Downloading the Redis image (4/5)...", "Building the RabbitMQ image locally (5/5)...") and a heartbeat every 30 s; warns clearly on rootless Docker; prints "ready" and opens the browser only once both the backend and the frontend answer. A crashed backend after startup is reported with the log path instead of leaving a dead URL. New flag: --no-open.
  • Repo — root npm test (Node's built-in test runner, no new dependency) with a cli-test CI job; test files excluded from the npm package; engines.node >= 18; README gets a short "If torollo start stops with an error" table.

Adjacent findings, not addressed here: derssa/backend-lab-rabbitmq:v1 is not on Docker Hub, so every first run rebuilds it locally (publishing it would shorten the first run); the published derssa/* images are amd64-only.

Types of Changes

  • New feature / node type addition
  • Bug fix (non-breaking change resolving an issue)
  • Refactoring / structural cleanup
  • Documentation update

Verification & Testing

Automated Checks

  • Run npm run lint successfully with no errors (backend clean; frontend: 5 pre-existing warnings in untouched files)
  • Run npm run build successfully with no compilation errors (backend + frontend)
  • Run npm test successfully (all tests pass) — root 32 (new), backend 509, frontend 367

Manual Verification

Played node bin/cli.js start --no-open against real Docker states on Linux (Fedora, rootless daemon + a root-owned /var/run/docker.sock the user cannot open), each with a scratch HOME:

State What the CLI printed Exit
Docker OK (rootless) Docker is running (rootless). → rootless network warning → ready banner in ~2 s stays up
DOCKER_HOST unset, active context = rootless endpoint taken from docker context, backend reaches the same daemon (before: docker info passed, backend got EACCES on /var/run/docker.sock) stays up
DOCKER_HOST=unix:///tmp/nope.sock 20 s grace, then Docker's socket was not found (…) + "DOCKER_HOST points at a socket that does not exist" 1
DOCKER_HOST unset, no context, /var/run/docker.sock root:docker Your user is not allowed to open Docker's socket + sudo usermod -aG docker $USER + relogin, no grace wait 1
unix socket with no listener Docker is not running. + sudo systemctl start docker 1
DOCKER_HOST=tcp://10.255.255.1:2375 (blackhole) backend answers timeout after 10 s, CLI: Docker is not answering. 1
backend cannot bind (TOROLLO_HOST invalid) The Torollo backend did not start. + log path, within 1.5 s 1
first run: derssa/backend-lab-redis:v1 and …-rabbitmq:v1 removed First run: downloading… → Downloading the Redis image (4/5)... (Hub) → Downloading the RabbitMQ image (5/5)... → Building the RabbitMQ image locally (5/5)… (no Hub tag) → Node images are ready. → banner; both tags back, no leftover build container stays up
backend killed after ready The Torollo backend stopped unexpectedly (SIGKILL). + log path 1

Also confirmed on this host that the privileged host-forwarding container fails under rootless Docker (iptables: Permission denied (you must be root)) — which the old code logged as a success.

Checklist

  • My code follows the repository's code style and lint standards
  • I have updated the documentation or instructions if necessary
  • All unit and integration tests are passing

@OthmaneZ05
OthmaneZ05 requested a review from Derssa as a code owner September 4, 2026 00:31
@Derssa
Derssa merged commit dd79fcd into main Sep 4, 2026
4 checks passed
@Derssa
Derssa deleted the feat/honest-start branch September 4, 2026 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants