Skip to content

engage: add -r flag to reload config of a running squadron#103

Open
mlund01 wants to merge 1 commit into
mainfrom
engage-reload-flag
Open

engage: add -r flag to reload config of a running squadron#103
mlund01 wants to merge 1 commit into
mainfrom
engage-reload-flag

Conversation

@mlund01
Copy link
Copy Markdown
Owner

@mlund01 mlund01 commented May 19, 2026

Summary

  • A second squadron engage against a config dir that already has a running instance now errors out with a clear hint, instead of forking and dying later in daemon.Fork's IsRunning check.
  • New --reload / -r flag: signals the running daemon (SIGHUP) to re-read and validate its config. The reload goes through the same wsbridge.Client.ReloadConfig path the command center uses, so it inherits the validate-then-atomic-swap semantics — a broken config is rejected and the running daemon keeps its previous config.
  • -r with no running daemon is a no-op: prints a message and proceeds with normal startup.

Behavior matrix

Running? -r? Result
no no normal startup
no yes prints Squadron is not running — ignoring -r and starting it now., then normal startup
yes no Error: squadron is already running (PID N). + suggestion to use -r or disengage, exits 1
yes yes reload flow (success → Config reloaded successfully.; failure → error printed, daemon keeps previous config)

What the user sees on -r

Success:

Squadron is already running (PID 12345). Reloading config from /path/to/config...
⠋ Validating and applying
Config reloaded successfully.

Failure (validation error in new HCL):

Squadron is already running (PID 12345). Reloading config from /path/to/config...
Config reload failed: <validation error>
Squadron is still running with the previous config (PID 12345). Fix the error above and re-run 'squadron engage'.

Implementation notes

  • daemon.Reload(configPath) (int, error) sends SIGHUP to the PID recorded in engage.pid.
  • Foreground engage path registers a SIGHUP handler that calls client.ReloadConfig() (existing function — same one the command center's TypeReloadConfig handler calls). On validation failure the handler writes SignalFailed to the ready file; on success the existing OnConfigLoaded callback writes SignalReady.
  • Parent engage -r clears the ready file, sends SIGHUP via daemon.Reload, then WaitReadys for the daemon's result with a 30s timeout.

Test plan

  • go build ./...
  • go test ./internal/daemon/ ./cmd/
  • New tests cover: missing PID file, malformed PID file, stale PID, actual SIGHUP delivery
  • Manual: start squadron, run squadron engage → see already-running error
  • Manual: edit HCL, run squadron engage -r → see reload succeed
  • Manual: introduce HCL syntax error, run squadron engage -r → see error + confirmation old config still active
  • Manual: squadron engage -r with nothing running → see "ignoring -r" message and normal startup

A second `squadron engage` against a config dir that already has a
running instance now errors out with a hint, instead of attempting a
fork that would have failed later in daemon.Fork's IsRunning check.

Passing `-r` / `--reload` to a second `engage` signals the running
daemon over SIGHUP to re-read and validate its config. The reload runs
through the same wsbridge.Client.ReloadConfig path the command center
uses, so it inherits the validate-then-atomic-swap semantics: a broken
config is rejected and the running daemon keeps its previous config.

If `-r` is passed when nothing is running, the flag is noted and ignored
and engage starts squadron normally.

Includes tests for daemon.Reload covering: missing PID file, malformed
PID file, stale PID, and actual SIGHUP delivery to a live process.
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