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
This commit is contained in:
1 parent
812be6a0a6
commit
f3ce42eb80
3 files changed
+109
-17
No files matched your search
+32
-12
@@ -120,9 +120,20 @@ done
|
||||
|
||||
if [ "$MODE" != "check" ] && [ -d "$PKGS_DIR/systemd-user/.config/systemd/user" ]; then
|
||||
systemctl --user daemon-reload || true
|
||||
for unit in "$PKGS_DIR"/systemd-user/.config/systemd/user/*.service; do
|
||||
UNITS_DIR="$PKGS_DIR/systemd-user/.config/systemd/user"
|
||||
# Services AND timers. A timer is the schedule that makes a oneshot service run at all, and it
|
||||
# carries no ExecStart of its own — the binary that decides whether the unit belongs on this
|
||||
# box lives in the service it activates. Walking *.service only deployed live-sync.service on
|
||||
# every rebuild and never armed live-sync.timer: the heartbeat was present and never ticked.
|
||||
for unit in "$UNITS_DIR"/*.service "$UNITS_DIR"/*.timer; do
|
||||
[ -e "$unit" ] || continue
|
||||
bin="$(sed -n 's/^ExecStart=\([^ ]*\).*/\1/p' "$unit" | head -1)"
|
||||
name="$(basename "$unit")"
|
||||
probe="$unit"
|
||||
if [ "${name##*.}" = timer ]; then
|
||||
act="$(sed -n 's/^Unit=\(.*\)$/\1/p' "$unit" | head -1)"
|
||||
probe="$UNITS_DIR/${act:-"${name%.timer}.service"}"
|
||||
fi
|
||||
bin="$(sed -n 's/^ExecStart=\([^ ]*\).*/\1/p' "$probe" 2>/dev/null | 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
|
||||
@@ -132,22 +143,31 @@ if [ "$MODE" != "check" ] && [ -d "$PKGS_DIR/systemd-user/.config/systemd/user"
|
||||
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
|
||||
# as for a `disabled` one. Starting something already installed is how a deploy locks a
|
||||
# live session — swayidle-lock sits enabled/inactive on blankpad and `--now` arms it
|
||||
# mid-conversation. Only a unit nothing has installed yet gets started. Refs #44.
|
||||
state="$(systemctl --user is-enabled "$name" 2>/dev/null || true)"
|
||||
case "$state" in
|
||||
"" | disabled)
|
||||
systemctl --user enable --now "$name" || true
|
||||
echo "ENABLE $name (ExecStart resolves here; nothing running it yet)" ;;
|
||||
*)
|
||||
systemctl --user enable "$name" || true
|
||||
echo "ENABLE $name (already $state; not started — a live session decides what runs)" ;;
|
||||
esac
|
||||
if ! grep -q '^\[Install\]' "$unit"; then
|
||||
# systemd refuses to enable these: no [Install] section means nothing can want the unit
|
||||
# at login, and live-sync.service has none on purpose — its timer pulls it in. The old
|
||||
# branch swallowed that failure and printed ENABLE anyway, so the one line a rebuild is
|
||||
# checked by was false on every box. The section is readable right here, so do not make
|
||||
# the call at all. Refs #60.
|
||||
echo "INERT $name (state=${state:-none}; no [Install] section — another unit arms it, enable cannot)"
|
||||
elif [ -z "$state" ] || [ "$state" = disabled ]; then
|
||||
if systemctl --user enable --now "$name"; then
|
||||
echo "ENABLE $name (ExecStart resolves here; nothing running it yet)"
|
||||
else
|
||||
echo "INERT $name (enable --now failed — systemd's message above says why)"
|
||||
fi
|
||||
elif systemctl --user enable "$name"; then
|
||||
echo "ENABLE $name (already $state; not started — a live session decides what runs)"
|
||||
else
|
||||
echo "INERT $name (already $state; enable failed — systemd's message above says why)"
|
||||
fi
|
||||
else
|
||||
echo "SKIP $(basename "$unit") (ExecStart '$bin' absent on this host)"
|
||||
echo "SKIP $name (ExecStart '$bin' absent on this host)"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
Reference in new issue
Block a user