Skip to content

v0.2.5

Choose a tag to compare

@bradpenney bradpenney released this 17 Sep 00:02
· 13 commits to main since this release
48976f0

v0.2.5 — the roll owns its steps

The first roll on v0.2.4 (2026-09-16, Kairos 4.2.0 → 4.3.0, k0s 1.36.3 → 1.36.4) replaced all five nodes and needed a human four times. This release makes each of those a step in substrate roll, so the operator's terminal stays empty from --yes to roll complete.

Fixed

  • bug-154 — the re-created node's Longhorn disk is re-admitted automatically. Longhorn keeps its node record across a same-name replacement, so every fresh disk came back as DiskNotReady: record diskUUID doesn't match the one on the disk and the three-patch procedure (evict → remove → re-add under a new key) was run by hand on every node of both rolls. roll now does it after the join, keeping the disk's own storageReserved (bug-159 cannot recur), retrying while Longhorn's webhook is still syncing, and halting with the condition message if the disk is not Ready and Schedulable within two minutes. forget_node no longer spends two minutes per node waiting for Longhorn to forget a node it never forgets.
  • bug-170 — the dead node's volumes are released at once. A destroyed node's VolumeAttachments lingered until the attach/detach controller's six-minute unmount wait expired, so every single-writer tenant (PocketBase, Meilisearch) served 500s for ~3.5 minutes per node. roll deletes them right after the Node object; the rescheduled pod mounts in seconds.
  • bug-171 — the gate's local kubectl always uses the break-glass context. It inherited the operator's current context; with brad (read-only, ADR-071) selected, /healthz/etcd was forbidden on every node, the etcd wait reported "not serving" across a healthy cluster, and the roll was three minutes from halting after one node. Regression-tested.
  • bug-158 — refuse to destroy a volume's last healthy replica. Before destroying a node, roll reads every Longhorn replica and refuses — naming the volumes — if any volume would be left with no never-failed replica elsewhere. Detached volumes are held to the same standard as attached ones; exempting them is how garmin-sync-state eroded to zero replicas across four replacements on v0.2.3.

Operator notes

  • Nothing changes on the hypervisors beyond the binary: install.sh v0.2.5 on each, then substrate deploy-posture --apply to re-stage /etc/substrate from the checkout (first live run of the installer's 0600 enforcement on a kept publish-status.env).
  • The acceptance test is the next bump's roll: no WARNING, no disk dance, no context switch, no 500 on trails.

141 tests. Verified: cosign identity bradpenney/substrate/.github/workflows/release.yaml@refs/tags/v0.2.5.