Audit fixes: a compat verdict must never be able to brick a working box
CI / shell (shellcheck + syntax) (push) Successful in 8s
CI / python 3.11 (push) Successful in 12s
CI / python 3.12 (push) Successful in 14s
CI / python 3.13 (push) Successful in 13s
TrueNAS compatibility / compat (push) Successful in 38s

The audit found the new machinery could do more harm than the bugs it prevents.

- apply.sh reused the 'nothing left to do' exit -- which touches the PERMANENT
  kill switch, cleared only by install.sh, never by update.sh -- for the
  incompatible case. On TrueNAS 26 (providers ok, nested opt-out) both modules go
  quiet, so the switch would fire and the release that fixed 26 could never
  re-enable itself. Retirement and incompatibility now take different exits.
- A network blip, a re-export, or a conditional def all read as BROKEN. Each is
  now 'unknown', which changes nothing, rather than evidence strong enough to
  disable a module.
- 'native' outranked BROKEN everywhere but apply.sh, so a TrueNAS that reworded
  the guard AND reshaped the functions rendered as good news.
- compat.py --tree read B2_BLOCK's own 'restic = True' as native support, so the
  documented way to check a live box lied on every patched machine.
- The signature check was a name-subset test. It passed reorders, kw-only
  conversions, and added required params -- and it had already passed a real bug:
  restic_backup takes 4 args on 24.10/25.04, and the wrapper forwarded 5. Nested
  backups have been raising TypeError on those releases the whole time. The
  wrapper now forwards *args/**kwargs.
- release.sh --promote was unreachable: it died if the tag existed, the gate died
  if it did not. The tests hid it by always tagging first.
This commit is contained in:
2026-07-13 17:58:15 +00:00
parent f927773f81
commit ea090c7f72
10 changed files with 773 additions and 100 deletions
+36 -3
View File
@@ -65,6 +65,33 @@ def repo(tmp_path):
return r
class TestTheBarrierBeforeTheTagExists:
"""release.sh calls the gate BEFORE creating the stable tag.
Every other test here tags first, and that is what let a fatal bug ship green:
`check_promotable` began with `commit_for(vX.Y.Z)` and returned "does not exist",
while release.sh's own guard refuses to run at all IF the tag exists. The two
conditions were mutually exclusive, so `--promote` could never succeed -- the
only way to cut a stable release was to hand-tag, bypassing every gate.
A gate that can only be satisfied after the thing it gates is not a gate.
"""
def test_promote_is_allowed_when_head_was_a_candidate_and_the_tag_is_absent(self, repo):
repo.git("tag", "v1.0.0-rc1") # rc on HEAD, no stable tag yet
assert check_promotable("v1.0.0", cwd=str(repo)) == []
def test_promote_is_refused_when_head_was_never_a_candidate(self, repo):
assert check_promotable("v1.0.0", cwd=str(repo))
def test_promote_is_refused_when_head_moved_past_the_candidate(self, repo):
repo.git("tag", "v1.0.0-rc1")
repo.commit("one more little fix") # HEAD is no longer the candidate
problems = check_promotable("v1.0.0", cwd=str(repo))
assert problems
assert "no release candidate does" in problems[0]
class TestTheBarrier:
def test_a_tag_with_no_candidate_is_refused(self, repo):
repo.git("tag", "v1.0.0")
@@ -109,9 +136,15 @@ class TestTheBarrier:
repo.git("tag", "v1.0.0")
assert check_promotable("v1.0.0", cwd=str(repo)) == []
def test_missing_tag_is_reported_not_crashed(self, repo):
problems = check_promotable("v9.9.9", cwd=str(repo))
assert problems and "does not exist" in problems[0]
def test_a_tag_the_numbering_does_not_understand_is_not_a_candidate(self, repo):
# `v1.0.0-rc*` also globs `v1.0.0-rc1-hotfix`, which _rc_number reads as 0.
# The barrier must be satisfied only by something that really was a candidate.
repo.git("tag", "v1.0.0-rc1-hotfix")
repo.git("tag", "v1.0.0")
problems = check_promotable("v1.0.0", cwd=str(repo))
assert problems
assert "never a release candidate" in problems[0]
assert rc_tags("1.0.0", cwd=str(repo)) == []
class TestRcNumbering: