deploy.sh declared this repo's own heartbeat unit foreign, on every box #46
No files matched your search
@@ -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
|
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.
|
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
|
## 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
|
`dconf load /` writes every key in `dotfiles/dconf/dump.txt`, so the dump carries whatever
|
||||||
|
|||||||
@@ -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
|
for unit in "$PKGS_DIR"/systemd-user/.config/systemd/user/*.service; do
|
||||||
[ -e "$unit" ] || continue
|
[ -e "$unit" ] || continue
|
||||||
bin="$(sed -n 's/^ExecStart=\([^ ]*\).*/\1/p' "$unit" | head -1)"
|
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
|
if [ -n "$bin" ] && command -v "$bin" >/dev/null 2>&1; then
|
||||||
name="$(basename "$unit")"
|
name="$(basename "$unit")"
|
||||||
# Read the state, not the exit status: `is-enabled` exits 1 for a `linked` unit exactly
|
# Read the state, not the exit status: `is-enabled` exits 1 for a `linked` unit exactly
|
||||||
|
|||||||
@@ -136,3 +136,19 @@ systemd_unit() {
|
|||||||
[[ "$output" == *"SKIP"*otherbox.service* ]]
|
[[ "$output" == *"SKIP"*otherbox.service* ]]
|
||||||
! grep -q enable "$STUB_LOG"
|
! 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"
|
||||||
|
}
|
||||||
Reference in new issue
Block a user