feat(deploy): take a host lease so deploys cannot clobber in-flight validation #777
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "deploy-host-lock"
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?
Implements invariant #2 from #775: never clobber validation someone else has in progress. The downgrade guard already covers invariant #1 (never move a host backward unknowingly); this is the other half.
A host runs one generation at a time, so deploying to a host somebody is still verifying silently destroys their work — and the host gives no hint verification was happening.
Key design decision: the lease is held past the deploy
The work being protected is the verification that happens after
deploy-rsexits, not the switch itself. An auto-released lock would leave open exactly the window it exists to close. So:deploy --release-lock --targets ".#beefcake"/run(tmpfs) → a rebooted host starts unlocked, which is correct: nothing can be mid-validation across a rebootHolder identity is per-workspace, not per-user
$USER@$(hostname)would make every agent on this box look likedaniel@dragonand never block each other — defeating the point. Each agent works in its own jj workspace, so the workspace dir name is a natural per-agent identity that's also stable across the severaldeployruns one agent makes while iterating (its own lease re-acquires rather than blocking).Blocked output
Notes
--hostnamewhen a single host is targeted, so the lease lands on the box actually being deployed — deploying beefcake over the LAN (--hostname 192.168.0.9) is the documented norm and must work with the VPN down.ssh … bash -s) — root's login shell on these hosts is fish, which would mis-parse an inline bash one-liner.--force-lock,--release-lock,--no-lock/LYTE_DEPLOY_NO_LOCK,LYTE_DEPLOY_LOCK_TTL,LYTE_DEPLOY_HOLDER.A real wedge found while testing
If an acquire died between the
mkdirand writingmeta(ssh dropping mid-call), the lockdir existed with no valid meta →since=0,ttl=0. The stale check requiresttl > 0, so the lease could never expire and reported a ~56-year age — precisely the failure the TTL exists to prevent. Missing/garbled meta now falls back to the lockdir's mtime for age and the caller's ttl for expiry, so a half-written lease ages out and self-heals.Verification
Extracted the shipped scripts from the built store artifact and drove the state machine:
ACQUIREDHELD|agent-a|0REACQUIRED--force-lockstealsFORCED|agent-a|0NOT_YOURS|agent-bRELEASEDNOT_HELDBROKE_STALE|agent-a|2HELD|unknown (incomplete lease)|0BROKE_STALE→ self-healsArg paths (
--hostnameoverride,--release-locknot deploying,--no-lock) checked viaLYTE_DEPLOY_GUARD_DRYRUN=1. Builds clean throughwriteShellApplication's shellcheck.Not yet exercised against a real host — the remote half is proven by running the shipped scripts locally against a temp lockdir, not over ssh to beefcake. Worth one live acquire/release on a non-critical host before merging.