diff --git a/nixos/modules/system/activation/pre-switch-check.nix b/nixos/modules/system/activation/pre-switch-check.nix index 2b53e390b19d..e80bec9eee9a 100644 --- a/nixos/modules/system/activation/pre-switch-check.nix +++ b/nixos/modules/system/activation/pre-switch-check.nix @@ -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 diff --git a/nixos/tests/switch-test.nix b/nixos/tests/switch-test.nix index 256c25108593..2dbc9386f8ae 100644 --- a/nixos/tests/switch-test.nix +++ b/nixos/tests/switch-test.nix @@ -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