Skip to content

feat(cli): hint at a foreground server when 'server down' has no pid file#146

Merged
Sootopolis merged 1 commit into
mainfrom
wip
Jul 4, 2026
Merged

feat(cli): hint at a foreground server when 'server down' has no pid file#146
Sootopolis merged 1 commit into
mainfrom
wip

Conversation

@Sootopolis

Copy link
Copy Markdown
Owner

What

ccas server down now, when it finds no detached server to SIGTERM (no pid file / corrupt / stale-dead pid), probes the server port and — if a server still answers — prints a hint pointing at the likely foreground ccas server up (which writes no pid file, so down can't reach it via the pid file). Exit code stays 1.

Why

ccas server status HTTP-probes /health, so it reports any server up — including a foreground one. down only consults the pid file. Against a foreground server, status said "running" while down said "no/stale pid file" and exited, reading as if the two disagree. The hint closes that gap.

How

  • New HealthProbe (port resolution + /health probe) shared by Status and Stop, so the "hint fires exactly when status says running" invariant is structural, not copy-paste. Status refactored onto it (dropped its private probe/timeouts/port constant).
  • Stop.run takes an injected liveServerPort: UIO[Option[Int]] seam; the public run supplies the real probe, unit tests supply a fixed Some/None → pid-file branches tested with no network.
  • Hint wording points at find-pid-then-kill (lsof -ti tcp:<port>), not a blind kill $(…).
  • Main applies the ccas.env overlay before down (port parity with status).

Testing

  • Full sbt test: 1000 passed, 0 failed (pre-push hook + local).
  • TestServeLifecycle Stop.run suite made hermetic (injected seam) + a positive hint-path test added.
  • Live-verified the staged binary: hint fires against a server on 8080, silent when none, renders the new wording.

Fixes

No open issue — follow-up to the server up/down rename (#145); surfaced when a foreground server ran while down was invoked.

🤖 Generated with Claude Code

…file

`ccas server status` HTTP-probes /health, so it reports *any* server up —
including a foreground `ccas server up`, which writes no pid file. `down`
only consults the pid file, so against a foreground server it printed
"no/stale pid file" and exited, reading as if status and down disagree.

The three no-detached-pid branches now probe the port too and, when a
server still answers, point the user at the likely foreground instance
the pid file can't reach (Ctrl-C, or find-pid-and-kill — not a blind
`kill $(lsof)`). Exit code stays 1: down stopped nothing it manages.

Probe + port resolution are extracted to a shared HealthProbe used by
both Status and Stop, so the "hint fires exactly when status says
running" invariant is structural, not a copy-paste promise. Stop.run
takes an injected liveServerPort seam so its unit tests exercise the
pid-file branches with no network. Main applies the ccas.env overlay
before down (port parity with status).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Sootopolis Sootopolis merged commit c67eaa5 into main Jul 4, 2026
1 check passed
Sootopolis added a commit that referenced this pull request Jul 4, 2026
…ePort

The `server.port` resolution was the third copy after #146 gave Status
and Stop a shared HealthProbe. Route Detach's detached-launch readiness
probe through HealthProbe.resolvePort too, so the one config key lives
in one place. Behaviour-identical: application.conf defaults `port =
8080`, so the key always resolves and resolvePort's 8080 fallback (which
Detach's bare getInt lacked) can never actually differ. Drops the now
unused ConfigFactory import.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sootopolis added a commit that referenced this pull request Jul 4, 2026
…ePort (#148)

The `server.port` resolution was the third copy after #146 gave Status
and Stop a shared HealthProbe. Route Detach's detached-launch readiness
probe through HealthProbe.resolvePort too, so the one config key lives
in one place. Behaviour-identical: application.conf defaults `port =
8080`, so the key always resolves and resolvePort's 8080 fallback (which
Detach's bare getInt lacked) can never actually differ. Drops the now
unused ConfigFactory import.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant