27da5cd9ecbe8fec8678bb139f920ccc856fa8f6
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f3ce42eb80 |
fix(deploy): report what enable actually did, and arm the tier's timers
Two lies in the unit loop, both reported as success: - `systemctl --user enable live-sync.service` fails on every deploy — the file has no [Install] section, because live-sync.timer is what arms it. The result was swallowed by `|| true` and the tool printed ENABLE anyway, so the line an operator reads after a rebuild was false on every box, on the repo's own heartbeat. The [Install] section is readable from the file being deployed, so the tool now checks it and prints INERT with the reason instead of making a call that cannot succeed; a real enable failure prints INERT too. - The loop walked *.service only. live-sync.timer was never enabled by anything, so a rebuilt box got the heartbeat and no schedule for it. Timers are walked now; a timer has no ExecStart, so the "does this unit belong on this box" test runs against the service it activates. The systemctl stub models systemd's refusal (no [Install] section -> non-zero), which is what makes the new tests red against the old loop; both new tests were run red first, and the five existing unit tests still pin #44's semantics. Refs #60 |
||
|
|
e278e4b863 |
Expand systemd specifiers before calling a unit foreign
The first real `deploy.sh` run on blankpad printed:
SKIP live-sync.service (ExecStart '%h/.omp/scripts/live-sync.sh' absent on this host)
while `/home/blank/.omp/scripts/live-sync.sh` sits right there. `%h` is expanded by systemd,
never by the shell, so the literal string was handed to `command -v`, failed, and the unit was
declared to belong to another machine — through the same code path whose whole purpose is to
keep a *foreign* unit inert, and silently. The victim was this repo's own heartbeat, and the
verdict was the same on every box that ever deployed it, because `%h` is exactly where the
checkout lives.
Nothing broke tonight only by luck of install state: `live-sync.service` is `linked`, driven
by its timer, so the heartbeat kept running while the deploy lied about it. A unit whose only
install route was this loop would simply never have been enabled anywhere.
`%h`, `%u` and `%U` are now expanded before resolution; an unrecognised specifier is left
alone so it fails loudly rather than being guessed at. Pinned by a test that writes a
`%h/.local/bin/helper` unit into the scratch home — red before (`SKIP`), green after
(`already linked; not started`), which also keeps the #45 rule intact: resolving a unit is not
licence to start it. Refs #44.
Verification: `bats tests/` 71/71, `kb-lint.sh omp-docs` 0 violations, `kb-coverage.py` 0
issues, `bash -n` clean.
|
||
|
|
ecc089c6ef |
deploy.sh no longer starts units a live session already runs
`sync` on a box with a live session on it was unsafe in two independent ways, found by preflighting the run rather than performing it. Refs #44. **`enable --now` would have armed a screen lock mid-session.** The unit loop started every `systemd-user/` unit whose `ExecStart` resolves. `swayidle-lock.service` on blankpad is `enabled`/`inactive` — nothing started it, no swayidle process exists, `autostart.kdl` does not launch one — so one `deploy.sh` would have begun blanking and locking the monitors while the operator was mid-sentence. `live-sync.service` is `linked`, driven by its timer, and `--now` forces a heartbeat commit at an arbitrary moment. A unit is now started only when systemd reports it as nothing-yet (`""`/`disabled`), which is precisely a fresh box; anything already installed is merely `enable`d. The state has to come from the **printed state**: `is-enabled` exits 1 for `linked` exactly as for `disabled`, so exit status cannot distinguish "installed, timer-driven" from "never installed" — the first version of this fix got that wrong and the test caught it. **`--check` output was being read as more than it can mean.** It prints `RELINK` for every path the `zz` tier carries, even when the live link already points at the override (`rules.kdl`, `keybinds.kdl`, `misc.kdl`, `autostart.kdl`, `.zshrc` all did on blankpad), because the walk visits the base package first and reports the intermediate owner change. The sentence committed in #43 — RELINK noise is "the sound of a stale override waiting" — is too strong and is corrected: the line proves a pending change only when `readlink` shows the live target is not already the `zz-$HOST` file, and `actions=0` is the honest summary. The stale-override hazard #43 removed was and is real; the signal for it is the target, not the line. **The dconf dump carried six of its 24 keys from another box**, none of them preferences: a Firefox file-chooser `last-folder-path` of `/home/dank/Downloads`, a nautilus `window-state` section, and `picture-uri`/`picture-uri-dark` pointing at `file:///home/dank/.config/background`. The last five showed no conflict because blankpad's live tree *already* held those `/home/dank` values — an earlier deploy wrote them here — and a foreign value that agrees with live is invisible to any diff while still being wrong. They are dropped; `picture-options='zoom'` stays, because it is a preference. The live wallpaper URIs are cleared on the box as part of landing this (niri draws the wallpaper, noctalia owns it, nothing reads a dead path). `tests/deploy.bats` grows by four, over a stub `systemctl` — the real one on this box is exactly what must not be invoked from a test. Red before: an already-`enabled` unit and a `linked` unit both get `--now`. Green after, including the two directions that keep the change honest: a `disabled` unit is still `enable --now`'d so a fresh box comes up, and a unit whose `ExecStart` is absent here is never touched at all. Verification: `bats tests/` 70/70, `kb-lint.sh omp-docs` 0, `kb-coverage.py` 0. The dump now reconciles against live state with **0 conflicts and no `/home/` values in 18 keys**, proven by key-by-key comparison rather than `diff` — `dconf load` writes only the keys present, so a diff overstates the damage one way and hides it the other. |
||
|
|
3022277167 |
Stop the deploy tier from reverting live theme state
Three findings from verifying the #41 merge against the live box with `deploy.sh --check`. One commit because they share the deploy tier, its documentation, and the first test file that tier ever had. **1. Generated palette output was tracked, and sync would have restored it over a live theme.** `dotfiles/zz-blankpad/niri/.config/niri/noctalia.kdl` (`b3d3df4`, 2026-10-18) sat byte-identical to the live file — harmless while the palette held, and `--check` was already proposing `ADOPT … noctalia.kdl`. The moment the theme changed, the next sync would have quarantined the live file and reinstated 2026-10-18's colours. `deploy.sh` now refuses the class outright (`SKIP … (generated theme output)`), `.gitignore` carries the matching patterns so it cannot be re-added, and the file is untracked. **2. A `zz` override older than the file it overrides.** `dotfiles/zz-blankpad/niri/…/ layout.kdl` held focus ring `width 2` / `#e01b24` (`7b7dbf5`, 2026-10-17) while base absorbed `b3d3df4` (2026-10-18): `width 4`, `#ff8c00`. Stow order makes `zz-*` win, and a cross-package owner change relinks *silently* — no quarantine, no warning. Live was linked to base, the newer intent, so `--check` printed `RELINK … layout.kdl` every run and one unattended `deploy.sh` would have reverted the amber focus ring. The duplicate is deleted; base owns the file. **3. Two topologies I had asserted and not measured.** The media law and the `.gitignore` comment both said `~/.local/share/noctalia/wallpapers` symlinks into the repo, so deleting the tracked copies would blank the desktop. Measured: it is a real directory of real files that Noctalia owns; the repo held a duplicate, and the #41 merge deleted that duplicate without the desktop flickering. The correct general law replaces the false one — untracking a path deletes the file in every other checkout, `git rm --cached` on the branch notwithstanding — and the restore procedure now points at the app's directory, which `deploy.sh` does not manage. The guard is `tests/deploy.bats`, black-box over exit status, stdout, the symlink shape under `$HOME`, and the quarantine directory. Before the change: test 1 and test 2 fail, test 2 because the live palette really is quarantined and reverted. After: 4/4, including the control that an ordinary identical config is still adopted — an exclusion nobody can turn off is just a broken tool. Verification: `bats tests/` 66/66, `kb-lint.sh omp-docs` 0 violations, `kb-coverage.py` 0 issues, and live `deploy.sh --check` on blankpad reports `SKIP … (generated theme output)` with `actions=0` instead of `ADOPT … noctalia.kdl`. The real `deploy.sh` run that clears the remaining `RELINK` lines is deliberately left until this is in main — running it from a worktree would repoint live symlinks into a checkout the heartbeat reaps. Refs #42 |