feat(release): concurrency lock to prevent racing ferrflow release runs#517
Open
BryanFRD wants to merge 1 commit into
Open
feat(release): concurrency lock to prevent racing ferrflow release runs#517BryanFRD wants to merge 1 commit into
BryanFRD wants to merge 1 commit into
Conversation
First half of #514. Closes the lock concern; the checkpoint/resume piece stays open (heavier design, separate PR). ## Problem Two concurrent ferrflow release invocations on the same repo (typical scenario: manually-triggered release racing the cron-driven auto-release workflow, or two CI runners on the same commit) competed on git refs. Observed symptoms: non-fast-forward rejects, half-pushed tag sets, draft releases created twice. ## Fix New src/monorepo/run/lock.rs: RAII lock guard backed by .git/ferrflow.lock created via O_CREAT|O_EXCL. Atomic. Released on drop, including panic unwind. Acquired at the top of run_release_logic for non-dry-run only. Read-only commands (check, status, version, tag) are not affected. ## Stale lock recovery A lockfile older than STALE_LOCK_TTL (30 min, longer than any realistic release) is treated as orphaned (process crashed without releasing) and taken over with a warning. Beyond TTL the user can also force-unlock manually by deleting the file; future PR may expose this via --force-unlock CLI flag. ## Tests - 6 unit tests in src/monorepo/run/lock.rs::tests: - acquire on clean repo succeeds - drop removes lockfile - second acquire fails while first held - force unlock takes over active lock - missing .git dir errors out cleanly - lockfile content starts with PID - 521 lib + 635 bin tests pass overall - cargo clippy -D warnings clean ## Out of scope The checkpoint/resume mechanism from #514 (write release-state.json at each step, resume if interrupted) is deferred — needs separate design review around atomic write + invalidation rules. Issue stays open.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #516. First half of #514 (the lock); checkpoint/resume stays open as a heavier follow-up.
Problem
Two concurrent `ferrflow release` invocations on the same repo (manually-triggered racing the cron-driven `auto-release` workflow, or two CI runners on the same commit) competed on git refs. Observed symptoms: non-fast-forward rejects, half-pushed tag sets, draft releases created twice.
Fix
New `src/monorepo/run/lock.rs`: RAII lock guard backed by `.git/ferrflow.lock` created via O_CREAT|O_EXCL — atomic, released on drop including panic unwind. Acquired at the top of `run_release_logic` for non-dry-run only. Read-only commands (`check`, `status`, `version`, `tag`) are unaffected.
Stale lock recovery
A lockfile older than 30 min is treated as orphaned (process crashed without releasing) and taken over with a warning. Beyond that, the `acquire_force` path exists for an eventual `--force-unlock` CLI flag (kept private for now).
Test plan