From d6c8bcf5d3d0c270153d676f8f14884f247ef454 Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 31 Aug 2026 19:44:51 +0200 Subject: [PATCH] module-eval: escape case names in the failure report `echo 'FAILED: ${c.name}'` hand-quoted a string that is prose, so the first case name containing an apostrophe to actually fail terminated the builder script mid-report. The remaining failures never printed, and the error read as a shell syntax error rather than as a broken property. Only failing cases are ever echoed, so every green run agreed the reporter was fine -- the defect was reachable exclusively at the moment the report was the thing being relied on. Measured: with two cases failing, the old form printed one line and an EOF error, the escaped form prints both plus the count. --- nix/module-eval.nix | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 2e9bfbb1..73b49a84 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -233,17 +233,32 @@ let # local mints certificates off-host — so this orders against nothing. # Eval cannot see that failure; only the empty list here stands in for it. name = "an off-host reader requires no unit the store's host would have provided"; - ok = baoRemoteReader.systemd.services.swarm-bao-matrix-token.requires == [ ]; + # Membership first, then the value: indexing a missing unit throws, and a + # table that reports which property broke must not be the thing that dies. + ok = + let + s = baoRemoteReader.systemd.services; + in + s ? swarm-bao-matrix-token && s.swarm-bao-matrix-token.requires == [ ]; } { # Presence control for the case above: the list is conditional, not gone. name = "a co-located reader still orders after the local pki unit"; - ok = baoWithMatrix.systemd.services.swarm-bao-matrix-token.requires == [ "swarm-bao-pki.service" ]; + ok = + let + s = baoWithMatrix.systemd.services; + in + s ? swarm-bao-matrix-token && s.swarm-bao-matrix-token.requires == [ "swarm-bao-pki.service" ]; } ]; bad = builtins.filter (c: !c.ok) cases; - report = lib.concatMapStringsSep "\n" (c: " echo 'FAILED: ${c.name}' >&2") bad; + # Escaped, because a name is prose and prose contains apostrophes. Hand-quoting + # broke the builder mid-report on the first such name that failed — and only + # ever on failure, so every green run agreed the reporter was fine. + report = lib.concatMapStringsSep "\n" ( + c: " echo ${lib.escapeShellArg "FAILED: ${c.name}"} >&2" + ) bad; in # The results are embedded in the builder text on purpose: that is what # makes this derivation's hash depend on them, so a nix-only change that