PR #522 follow-ups: dead test assertions, dry-run tail fidelity nf-m1k2 ← Beads

open priority 2 task unassigned

Twinned from https://github.com/cfsh/ninefold/issues/533 by tools/beads/import_github.py's reconcile pass.

Suggestions from ninefold-reviewer's review of #522 (release.py, design 001 piece 10). All are advisory-minor — #522 converged with them outstanding, and none blocks anything.

---

1. Two dead assertions inside assertRaises blocks — the same class as that PR's own F6

tools/tests/test_release.py:149-151 and :170-172:

```python with self.assertRaises(rel.Refused): _, _, errs = capture(rel.release, self.root, git, [], runner) self.assertIn("manifest generation failed", errs) # never runs ```

capture(...) raises, so the assertIn on the next line is unreachable. The error message is therefore not checked in either test — "manifest generation failed for {plat}" and "{pck} export failed" could both be silently changed or dropped.

Impact is small because the outer assertRaises does the real work: both mutations (removing the .ok check in the manifest loop, and removing not packed.ok or in the pack loop) still die. Only the message half is dead.

Worth recording because these were introduced in the commit that fixed F6, which was itself "two tests assert less than they read as asserting". Third instance of the class in the file.

Fix shape:

```python with self.assertRaises(rel.Refused): capture(rel.release, self.root, git, [], runner) ```

with the message check hoisted out (contextlib.redirect_stderr around the assertRaises, or assert on runner.commands() as test_a_failed_manifest_stops_before_the_sync already does on its last line).

2. The dry-run tail is not the shell's 2>&1 | tail -5

tools/release/release.py:320:

```python tail = (result.out + result.err).splitlines()[-5:] ```

Two differences from … --stats-one-line -v 2>&1 | tail -5:

Low impact in practice — rclone logs to stderr, so out is usually empty. (result.out + "\n" + result.err) or [*result.out.splitlines(), *result.err.splitlines()][-5:] says it directly.

3. The installer copy step is still non-atomic (pre-existing, faithful to the shell)

release.py:359-368 publishes the two copyto keys sequentially. If the win copy succeeds and the linux one fails, R2 holds a new win installer beside the previous linux one — the mismatched public pair that #522's F3 fix eliminated for the *publish* step. The shell had the same window, so this is not a port defect; noting it because those are the two keys the itch page links, and the blast radius is the same one F3 was about.

4. release.py lands 100644

Its docstring advertises ./tools/release/release.py as an entry point. Matches every ported sibling except poll.py (100755), so this is a tier-wide consistency question rather than a bug in this PR — probably piece 11's to settle.

Dependencies

None.

Comments

No comments.

Add a comment