You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: stop multi-server workspaces provisioning and routing over each other
Three bugs made a workspace with more than one server unsafe. Each is
independently reachable today; together they make the multi-server path
unusable, and replication would multiply all three.
Managed services were installed on every host. `database` and `redis` are
workspace-level, and configForServer spread the whole config onto each
scoped copy, so setup's localhost guard fired once per server: a 3-server
workspace installed and initialised Postgres three times, same user, same
database name. Both now carry an `on` target and are stripped from the
servers that do not host them.
Cloudflare init repointed every domain at whichever host ran last. The
orchestrator iterated the entire workspace app list, so DNS, ingress,
firewall lockdown and audit all described apps that live elsewhere; the
final CNAME upsert won and the other server's apps 404'd through the
tunnel catch-all. It now requires a server-scoped config and the commands
fan out. Two consequences fall out of that: sshHostname is one workspace
name, so exactly one tunnel may claim it, and an explicit tunnelName shared
across several tunnel-needing servers is rejected up front rather than
failing halfway through on the missing-credentials guard.
Servers were visited in the order they appear in the `servers` literal, and
each starts only its own accessories. Declare the app server before the
database server and the app deploys and health-checks before the database
it depends on exists — reordering two lines silently fixed it. getServerTargets
now sorts by dependsOn, declaration order breaking ties. Cycles fall back to
declaration order instead of throwing, since two servers can legitimately
host accessories the other consumes. The cross-server reachability warning
also moves out of --dry-run into the real deploy path, resolved against the
whole workspace because a per-server config cannot see other servers'
accessories.
runRemoteCommandForTargets had no test coverage at all — its mocked config
did not even carry a `servers` key. Traversal order, per-server scoping, the
includeEmpty skip, connection lifecycle and --app validation are now pinned.
The abort-on-failure test documents current behaviour: the try/catch sits
outside the loop, so one server failing abandons the rest with no account of
what succeeded. That is left deliberately visible for the fleet work to change.
One behaviour change beyond the fix: backup reads config.database, so a
database is now dumped only on the server that hosts it, instead of every
server attempting a pg_dump of a database only one of them has.
0 commit comments