deploy.sh declared this repo's own heartbeat unit foreign, on every box #46

Merged
dank merged 1 commits from fix/44-unit-specifier-resolution into main 2026-10-20 17:22:52 -07:00
3 changed files with 45 additions and 0 deletions
+21
View File
@@ -158,6 +158,27 @@ fresh box — where everything reports `disabled` — still gets its units up. B
are pinned in `tests/deploy.bats` over a stub `systemctl`, because the real one on this box
is exactly what must not be invoked from a test. Refs #44.
## Law: expand systemd specifiers before calling a unit foreign
`ExecStart=%h/.omp/scripts/live-sync.sh` is valid systemd and meaningless to a shell. The
resolution check handed that literal string to `command -v`, which fails everywhere, so the
deployment concluded the unit belonged to another machine and skipped it — silently, through
the same code path that is supposed to keep a *foreign* unit inert. The unit it kept skipping
was this repo's own heartbeat, and `%h` is precisely where this checkout lives, so the false
verdict was the same on every box that deployed it. Measured on blankpad: the first real
`deploy.sh` run 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.
Expand the specifiers a user unit can carry — `%h`, `%u`, `%U` — before resolving, and let an
unknown specifier fail rather than guess at it. The probe needs no privileges and writes
nothing:
```bash
bin=$(sed -n 's/^ExecStart=\([^ ]*\).*/\1/p' \
~/.omp/dotfiles/systemd-user/.config/systemd/user/live-sync.service | head -1)
command -v "${bin//%h/$HOME}" # resolves → the unit is this box's; the SKIP was the lie
```
## Law: the dconf dump holds preferences, not per-box state
`dconf load /` writes every key in `dotfiles/dconf/dump.txt`, so the dump carries whatever
+8
View File
@@ -123,6 +123,14 @@ if [ "$MODE" != "check" ] && [ -d "$PKGS_DIR/systemd-user/.config/systemd/user"
for unit in "$PKGS_DIR"/systemd-user/.config/systemd/user/*.service; do
[ -e "$unit" ] || continue
bin="$(sed -n 's/^ExecStart=\([^ ]*\).*/\1/p' "$unit" | head -1)"
# systemd expands specifiers inside ExecStart; this shell does not. Matching the literal
# `%h/…` makes a unit of THIS box look foreign and skips it in silence — which is exactly
# how live-sync.service, the repo's own heartbeat, has been reported "absent on this
# host" on every machine that deployed it. Expand what a user unit can carry; leave any
# other specifier unmatched rather than guess at it. Refs #44.
bin="${bin//%h/$HOME}"
bin="${bin//%u/$(id -un)}"
bin="${bin//%U/$(id -u)}"
if [ -n "$bin" ] && command -v "$bin" >/dev/null 2>&1; then
name="$(basename "$unit")"
# Read the state, not the exit status: `is-enabled` exits 1 for a `linked` unit exactly
+16
View File
@@ -136,3 +136,19 @@ systemd_unit() {
[[ "$output" == *"SKIP"*otherbox.service* ]]
! grep -q enable "$STUB_LOG"
}
@test "a unit whose ExecStart uses a systemd specifier still resolves here" {
# `%h` is expanded by systemd, not by the shell, so matching the literal string makes a
# unit belonging to THIS box look foreign and skip it in silence. The victim is this repo's
# own heartbeat: `ExecStart=%h/.omp/scripts/live-sync.sh`, skipped on every box. Refs #44.
mkdir -p "$HOME/.local/bin"
printf '#!/bin/sh\ntrue\n' > "$HOME/.local/bin/helper"
chmod +x "$HOME/.local/bin/helper"
systemd_unit heartbeat.service '%h/.local/bin/helper'
printf 'linked\n' > "$UNIT_STATE"
run "$REPO/scripts/deploy.sh"
[ "$status" -eq 0 ]
[[ "$output" == *"heartbeat.service (already linked"* ]]
grep -q 'systemctl --user enable heartbeat.service' "$STUB_LOG"
! grep -q -- '--now' "$STUB_LOG"
}