release-v1.sh: direct push can move v1 backwards; annotated v1 wedges both writers #29

Open
opened 2026-09-22 23:13:24 +00:00 by claude · 0 comments
Collaborator

Found by

PR #28's final review (review 1394). Neither item can be reached from either workflow today, so the PR merged without them. Each is a small hardening of scripts/release-v1.sh.

1. push_leased can move v1 backwards when called directly

release-v1.sh push <A> <B> with v1 = B, where B is already ahead of A, moves v1 back to A. The reviewer reproduced this. Neither workflow can reach it, because sweep-check only sets needed=true when v1 does not cover the tip, and merge mode's own pre-check exits first. It still contradicts the script header's "never backwards", which should hold for the script, not only for its current callers.

Fix: in push_leased, return 0 (a green skip) when covers "$sha" "$expect" is true, before the first push.

2. An annotated v1 wedges both writers red

The lease compares against the tag object's SHA, but fetch_v1 returns the peeled commit (refs/tags/v1^{commit}), so every push is rejected and reported as "not a lost lease". This fails safe, and the live v1 is lightweight. It matters if #27's annotated-tag idea is ever adopted.

Fix: lease against the tag ref's own value (git ls-remote origin refs/tags/v1), and keep using the peeled commit for ancestry checks.

Acceptance criteria

  1. release-v1-selftest.sh gains a scenario for each item, and each fails against the current script.
  2. The header's "never backwards" holds for any direct invocation.
  3. An annotated v1 either releases correctly or fails with a message naming the annotation, not "not a lost lease".
## Found by PR #28's final review (review 1394). Neither item can be reached from either workflow today, so the PR merged without them. Each is a small hardening of `scripts/release-v1.sh`. ## 1. `push_leased` can move `v1` backwards when called directly `release-v1.sh push <A> <B>` with `v1` = B, where B is already ahead of A, moves `v1` back to A. The reviewer reproduced this. Neither workflow can reach it, because `sweep-check` only sets `needed=true` when `v1` does not cover the tip, and merge mode's own pre-check exits first. It still contradicts the script header's "never backwards", which should hold for the script, not only for its current callers. **Fix:** in `push_leased`, return 0 (a green skip) when `covers "$sha" "$expect"` is true, before the first push. ## 2. An annotated `v1` wedges both writers red The lease compares against the tag object's SHA, but `fetch_v1` returns the peeled commit (`refs/tags/v1^{commit}`), so every push is rejected and reported as "not a lost lease". This fails safe, and the live `v1` is lightweight. It matters if #27's annotated-tag idea is ever adopted. **Fix:** lease against the tag ref's own value (`git ls-remote origin refs/tags/v1`), and keep using the peeled commit for ancestry checks. ## Acceptance criteria 1. `release-v1-selftest.sh` gains a scenario for each item, and each fails against the current script. 2. The header's "never backwards" holds for any direct invocation. 3. An annotated `v1` either releases correctly or fails with a message naming the annotation, not "not a lost lease".
claude added the bug label 2026-09-22 23:13:24 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: daniel/gitdan-actions#29