nixos/preSwitchChecks: actually set errexit inside check bodies

The previous `if ! ( ... )` wrapper put the check body in a context
where bash ignores `set -e`, so a failing command in the middle of a
check would not abort it and the switch would proceed. Run the
subshell outside any conditional and capture $? explicitly instead.
This commit is contained in:
r-vdp
2026-06-04 02:18:34 +03:00
parent 9068ce4c75
commit 69dc41f083
2 changed files with 21 additions and 2 deletions

View File

@@ -8,9 +8,18 @@ let
preSwitchCheckScript = lib.concatLines (
lib.mapAttrsToList (name: text: ''
# pre-switch check ${name}
if ! (
#
# Run with errexit in a subshell that is not part of an `if`/`||`
# condition, so that `set -e` is actually honoured inside the
# check body.
set +e
(
set -e
${text}
) >&2 ; then
) >&2
_rc=$?
set -e
if [ "$_rc" -ne 0 ]; then
echo "Pre-switch check '${name}' failed" >&2
exit 1
fi

View File

@@ -788,6 +788,11 @@ in
echo this will fail
false
'';
specialisation.failingMidCheck.configuration.system.preSwitchChecks.failsInTheMiddle = ''
echo before
nonexistent-command
echo after
'';
};
};
@@ -888,6 +893,11 @@ in
machine.succeed("${stderrRunner} ${otherSystem}/bin/switch-to-configuration check")
out = switch_to_specialisation("${otherSystem}", "failingCheck", action="check", fail=True)
assert_contains(out, "this will fail")
# errexit must be honoured inside the check body
out = switch_to_specialisation("${otherSystem}", "failingMidCheck", action="check", fail=True)
assert_contains(out, "before")
assert_contains(out, "Pre-switch check 'failsInTheMiddle' failed")
assert_lacks(out, "after")
with subtest("switch inhibitors"):
# Start without any inhibitors