mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-13 21:50:33 +03:00
Merge pull request #323613 from CyberShadow/fix-nix-path-without-channels-v2
nix-channel: do not set empty nix-path when disabling channels
This commit is contained in:
commit
4ca52fdf5f
15 changed files with 291 additions and 7 deletions
|
@ -116,6 +116,55 @@ It has two modes:
|
||||||
|
|
||||||
: The `lychee` package to use.
|
: The `lychee` package to use.
|
||||||
|
|
||||||
|
## `shellcheck` {#tester-shellcheck}
|
||||||
|
|
||||||
|
Runs files through `shellcheck`, a static analysis tool for shell scripts.
|
||||||
|
|
||||||
|
:::{.example #ex-shellcheck}
|
||||||
|
# Run `testers.shellcheck`
|
||||||
|
|
||||||
|
A single script
|
||||||
|
|
||||||
|
```nix
|
||||||
|
testers.shellcheck {
|
||||||
|
name = "shellcheck";
|
||||||
|
src = ./script.sh;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Multiple files
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
inherit (lib) fileset;
|
||||||
|
in
|
||||||
|
testers.shellcheck {
|
||||||
|
name = "shellcheck";
|
||||||
|
src = fileset.toSource {
|
||||||
|
root = ./.;
|
||||||
|
fileset = fileset.unions [
|
||||||
|
./lib.sh
|
||||||
|
./nixbsd-activate
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Inputs {#tester-shellcheck-inputs}
|
||||||
|
|
||||||
|
[`src` (path or string)]{#tester-shellcheck-param-src}
|
||||||
|
|
||||||
|
: The path to the shell script(s) to check.
|
||||||
|
This can be a single file or a directory containing shell files.
|
||||||
|
All files in `src` will be checked, so you may want to provide `fileset`-based source instead of a whole directory.
|
||||||
|
|
||||||
|
### Return value {#tester-shellcheck-return}
|
||||||
|
|
||||||
|
A derivation that runs `shellcheck` on the given script(s).
|
||||||
|
The build will fail if `shellcheck` finds any issues.
|
||||||
|
|
||||||
## `testVersion` {#tester-testVersion}
|
## `testVersion` {#tester-testVersion}
|
||||||
|
|
||||||
Checks that the output from running a command contains the specified version string in it as a whole word.
|
Checks that the output from running a command contains the specified version string in it as a whole word.
|
||||||
|
|
|
@ -12,6 +12,7 @@ let
|
||||||
mkDefault
|
mkDefault
|
||||||
mkIf
|
mkIf
|
||||||
mkOption
|
mkOption
|
||||||
|
stringAfter
|
||||||
types
|
types
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -97,5 +98,8 @@ in
|
||||||
systemd.tmpfiles.rules = lib.mkIf cfg.channel.enable [
|
systemd.tmpfiles.rules = lib.mkIf cfg.channel.enable [
|
||||||
''f /root/.nix-channels - - - - ${config.system.defaultChannel} nixos\n''
|
''f /root/.nix-channels - - - - ${config.system.defaultChannel} nixos\n''
|
||||||
];
|
];
|
||||||
|
|
||||||
|
system.activationScripts.no-nix-channel = mkIf (!cfg.channel.enable)
|
||||||
|
(stringAfter [ "etc" "users" ] (builtins.readFile ./nix-channel/activation-check.sh));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
21
nixos/modules/config/nix-channel/activation-check.sh
Normal file
21
nixos/modules/config/nix-channel/activation-check.sh
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
explainChannelWarning=0
|
||||||
|
if [[ -e "/root/.nix-defexpr/channels" ]]; then
|
||||||
|
warn '/root/.nix-defexpr/channels exists, but channels have been disabled.'
|
||||||
|
explainChannelWarning=1
|
||||||
|
fi
|
||||||
|
if [[ -e "/nix/var/nix/profiles/per-user/root/channels" ]]; then
|
||||||
|
warn "/nix/var/nix/profiles/per-user/root/channels exists, but channels have been disabled."
|
||||||
|
explainChannelWarning=1
|
||||||
|
fi
|
||||||
|
while IFS=: read -r _ _ _ _ _ home _ ; do
|
||||||
|
if [[ -n "$home" && -e "$home/.nix-defexpr/channels" ]]; then
|
||||||
|
warn "$home/.nix-defexpr/channels exists, but channels have been disabled." 1>&2
|
||||||
|
explainChannelWarning=1
|
||||||
|
fi
|
||||||
|
done < <(getent passwd)
|
||||||
|
if [[ $explainChannelWarning -eq 1 ]]; then
|
||||||
|
echo "Due to https://github.com/NixOS/nix/issues/9574, Nix may still use these channels when NIX_PATH is unset." 1>&2
|
||||||
|
echo "Delete the above directory or directories to prevent this." 1>&2
|
||||||
|
fi
|
19
nixos/modules/config/nix-channel/test.nix
Normal file
19
nixos/modules/config/nix-channel/test.nix
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Run:
|
||||||
|
# nix-build -A nixosTests.nix-channel
|
||||||
|
{ lib, testers }:
|
||||||
|
let
|
||||||
|
inherit (lib) fileset;
|
||||||
|
|
||||||
|
runShellcheck = testers.shellcheck {
|
||||||
|
src = fileset.toSource {
|
||||||
|
root = ./.;
|
||||||
|
fileset = fileset.unions [
|
||||||
|
./activation-check.sh
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
lib.recurseIntoAttrs {
|
||||||
|
inherit runShellcheck;
|
||||||
|
}
|
|
@ -33,6 +33,8 @@ let
|
||||||
''
|
''
|
||||||
#!${pkgs.runtimeShell}
|
#!${pkgs.runtimeShell}
|
||||||
|
|
||||||
|
source ${./lib/lib.sh}
|
||||||
|
|
||||||
systemConfig='@out@'
|
systemConfig='@out@'
|
||||||
|
|
||||||
export PATH=/empty
|
export PATH=/empty
|
||||||
|
|
5
nixos/modules/system/activation/lib/lib.sh
Normal file
5
nixos/modules/system/activation/lib/lib.sh
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
printf "\033[1;35mwarning:\033[0m %s\n" "$*" >&2
|
||||||
|
}
|
36
nixos/modules/system/activation/lib/test.nix
Normal file
36
nixos/modules/system/activation/lib/test.nix
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# Run:
|
||||||
|
# nix-build -A nixosTests.activation-lib
|
||||||
|
{ lib, stdenv, testers }:
|
||||||
|
let
|
||||||
|
inherit (lib) fileset;
|
||||||
|
|
||||||
|
runTests = stdenv.mkDerivation {
|
||||||
|
name = "tests-activation-lib";
|
||||||
|
src = fileset.toSource {
|
||||||
|
root = ./.;
|
||||||
|
fileset = fileset.unions [
|
||||||
|
./lib.sh
|
||||||
|
./test.sh
|
||||||
|
];
|
||||||
|
};
|
||||||
|
buildPhase = ":";
|
||||||
|
doCheck = true;
|
||||||
|
postUnpack = ''
|
||||||
|
patchShebangs --build .
|
||||||
|
'';
|
||||||
|
checkPhase = ''
|
||||||
|
./test.sh
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
runShellcheck = testers.shellcheck {
|
||||||
|
src = runTests.src;
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
lib.recurseIntoAttrs {
|
||||||
|
inherit runTests runShellcheck;
|
||||||
|
}
|
34
nixos/modules/system/activation/lib/test.sh
Executable file
34
nixos/modules/system/activation/lib/test.sh
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Run:
|
||||||
|
# ./test.sh
|
||||||
|
# or:
|
||||||
|
# nix-build -A nixosTests.activation-lib
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# report failure
|
||||||
|
onerr() {
|
||||||
|
set +e
|
||||||
|
# find failed statement
|
||||||
|
echo "call trace:"
|
||||||
|
local i=0
|
||||||
|
while t="$(caller $i)"; do
|
||||||
|
line="${t%% *}"
|
||||||
|
file="${t##* }"
|
||||||
|
echo " $file:$line" >&2
|
||||||
|
((i++))
|
||||||
|
done
|
||||||
|
# red
|
||||||
|
printf "\033[1;31mtest failed\033[0m\n" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
trap onerr ERR
|
||||||
|
|
||||||
|
source ./lib.sh
|
||||||
|
|
||||||
|
(warn hi, this works >/dev/null) 2>&1 | grep -E $'.*warning:.* hi, this works' >/dev/null
|
||||||
|
|
||||||
|
# green
|
||||||
|
printf "\033[1;32mok\033[0m\n"
|
|
@ -301,6 +301,7 @@ in {
|
||||||
esphome = handleTest ./esphome.nix {};
|
esphome = handleTest ./esphome.nix {};
|
||||||
etc = pkgs.callPackage ../modules/system/etc/test.nix { inherit evalMinimalConfig; };
|
etc = pkgs.callPackage ../modules/system/etc/test.nix { inherit evalMinimalConfig; };
|
||||||
activation = pkgs.callPackage ../modules/system/activation/test.nix { };
|
activation = pkgs.callPackage ../modules/system/activation/test.nix { };
|
||||||
|
activation-lib = pkgs.callPackage ../modules/system/activation/lib/test.nix { };
|
||||||
activation-var = runTest ./activation/var.nix;
|
activation-var = runTest ./activation/var.nix;
|
||||||
activation-nix-channel = runTest ./activation/nix-channel.nix;
|
activation-nix-channel = runTest ./activation/nix-channel.nix;
|
||||||
activation-etc-overlay-mutable = runTest ./activation/etc-overlay-mutable.nix;
|
activation-etc-overlay-mutable = runTest ./activation/etc-overlay-mutable.nix;
|
||||||
|
@ -624,6 +625,7 @@ in {
|
||||||
nbd = handleTest ./nbd.nix {};
|
nbd = handleTest ./nbd.nix {};
|
||||||
ncdns = handleTest ./ncdns.nix {};
|
ncdns = handleTest ./ncdns.nix {};
|
||||||
ndppd = handleTest ./ndppd.nix {};
|
ndppd = handleTest ./ndppd.nix {};
|
||||||
|
nix-channel = pkgs.callPackage ../modules/config/nix-channel/test.nix { };
|
||||||
nebula = handleTest ./nebula.nix {};
|
nebula = handleTest ./nebula.nix {};
|
||||||
netbird = handleTest ./netbird.nix {};
|
netbird = handleTest ./netbird.nix {};
|
||||||
nimdow = handleTest ./nimdow.nix {};
|
nimdow = handleTest ./nimdow.nix {};
|
||||||
|
|
|
@ -463,7 +463,32 @@ let
|
||||||
""")
|
""")
|
||||||
|
|
||||||
with subtest("Switch to flake based config"):
|
with subtest("Switch to flake based config"):
|
||||||
target.succeed("nixos-rebuild switch --flake /root/my-config#xyz")
|
target.succeed("nixos-rebuild switch --flake /root/my-config#xyz 2>&1 | tee activation-log >&2")
|
||||||
|
|
||||||
|
target.succeed("""
|
||||||
|
cat -n activation-log >&2
|
||||||
|
""")
|
||||||
|
|
||||||
|
target.succeed("""
|
||||||
|
grep -F '/root/.nix-defexpr/channels exists, but channels have been disabled.' activation-log
|
||||||
|
""")
|
||||||
|
target.succeed("""
|
||||||
|
grep -F '/nix/var/nix/profiles/per-user/root/channels exists, but channels have been disabled.' activation-log
|
||||||
|
""")
|
||||||
|
target.succeed("""
|
||||||
|
grep -F '/root/.nix-defexpr/channels exists, but channels have been disabled.' activation-log
|
||||||
|
""")
|
||||||
|
target.succeed("""
|
||||||
|
grep -F 'Due to https://github.com/NixOS/nix/issues/9574, Nix may still use these channels when NIX_PATH is unset.' activation-log
|
||||||
|
""")
|
||||||
|
target.succeed("rm activation-log")
|
||||||
|
|
||||||
|
# Perform the suggested cleanups we've just seen in the log
|
||||||
|
# TODO after https://github.com/NixOS/nix/issues/9574: don't remove them yet
|
||||||
|
target.succeed("""
|
||||||
|
rm -rf /root/.nix-defexpr/channels /nix/var/nix/profiles/per-user/root/channels /root/.nix-defexpr/channels
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
target.shutdown()
|
target.shutdown()
|
||||||
|
|
||||||
|
@ -474,10 +499,20 @@ let
|
||||||
|
|
||||||
# Note that the channel profile is still present on disk, but configured
|
# Note that the channel profile is still present on disk, but configured
|
||||||
# not to be used.
|
# not to be used.
|
||||||
with subtest("builtins.nixPath is now empty"):
|
# TODO after issue https://github.com/NixOS/nix/issues/9574: re-enable this assertion
|
||||||
target.succeed("""
|
# I believe what happens is
|
||||||
[[ "[ ]" == "$(nix-instantiate builtins.nixPath --eval --expr)" ]]
|
# - because of the issue, we've removed the `nix-path =` line from nix.conf
|
||||||
""")
|
# - the "backdoor" shell is not a proper session and does not have `NIX_PATH=""` set
|
||||||
|
# - seeing no nix path settings at all, Nix loads its hardcoded default value,
|
||||||
|
# which is unfortunately non-empty
|
||||||
|
# Or maybe it's the new default NIX_PATH?? :(
|
||||||
|
# with subtest("builtins.nixPath is now empty"):
|
||||||
|
# target.succeed("""
|
||||||
|
# (
|
||||||
|
# set -x;
|
||||||
|
# [[ "[ ]" == "$(nix-instantiate builtins.nixPath --eval --expr)" ]];
|
||||||
|
# )
|
||||||
|
# """)
|
||||||
|
|
||||||
with subtest("<nixpkgs> does not resolve"):
|
with subtest("<nixpkgs> does not resolve"):
|
||||||
target.succeed("""
|
target.succeed("""
|
||||||
|
@ -491,12 +526,16 @@ let
|
||||||
target.succeed("""
|
target.succeed("""
|
||||||
(
|
(
|
||||||
exec 1>&2
|
exec 1>&2
|
||||||
rm -v /root/.nix-channels
|
rm -vf /root/.nix-channels
|
||||||
rm -vrf ~/.nix-defexpr
|
rm -vrf ~/.nix-defexpr
|
||||||
rm -vrf /nix/var/nix/profiles/per-user/root/channels*
|
rm -vrf /nix/var/nix/profiles/per-user/root/channels*
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
target.succeed("nixos-rebuild switch --flake /root/my-config#xyz")
|
target.succeed("nixos-rebuild switch --flake /root/my-config#xyz | tee activation-log >&2")
|
||||||
|
target.succeed("cat -n activation-log >&2")
|
||||||
|
target.succeed("! grep -F '/root/.nix-defexpr/channels' activation-log")
|
||||||
|
target.succeed("! grep -F 'but channels have been disabled' activation-log")
|
||||||
|
target.succeed("! grep -F 'https://github.com/NixOS/nix/issues/9574' activation-log")
|
||||||
|
|
||||||
target.shutdown()
|
target.shutdown()
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -140,4 +140,6 @@
|
||||||
hasPkgConfigModules = callPackage ./hasPkgConfigModules/tester.nix { };
|
hasPkgConfigModules = callPackage ./hasPkgConfigModules/tester.nix { };
|
||||||
|
|
||||||
testMetaPkgConfig = callPackage ./testMetaPkgConfig/tester.nix { };
|
testMetaPkgConfig = callPackage ./testMetaPkgConfig/tester.nix { };
|
||||||
|
|
||||||
|
shellcheck = callPackage ./shellcheck/tester.nix { };
|
||||||
}
|
}
|
||||||
|
|
3
pkgs/build-support/testers/shellcheck/example.sh
Normal file
3
pkgs/build-support/testers/shellcheck/example.sh
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
echo $@
|
28
pkgs/build-support/testers/shellcheck/tester.nix
Normal file
28
pkgs/build-support/testers/shellcheck/tester.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Dependencies (callPackage)
|
||||||
|
{ lib, stdenv, shellcheck }:
|
||||||
|
|
||||||
|
# testers.shellcheck function
|
||||||
|
# Docs: doc/build-helpers/testers.chapter.md
|
||||||
|
# Tests: ./tests.nix
|
||||||
|
{ src }:
|
||||||
|
let
|
||||||
|
inherit (lib) fileset pathType isPath;
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "run-shellcheck";
|
||||||
|
src =
|
||||||
|
if isPath src && pathType src == "regular" # note that for strings this would have been IFD, which we prefer to avoid
|
||||||
|
then fileset.toSource { root = dirOf src; fileset = src; }
|
||||||
|
else src;
|
||||||
|
nativeBuildInputs = [ shellcheck ];
|
||||||
|
doCheck = true;
|
||||||
|
dontConfigure = true;
|
||||||
|
dontBuild = true;
|
||||||
|
checkPhase = ''
|
||||||
|
find . -type f -print0 \
|
||||||
|
| xargs -0 shellcheck
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
}
|
38
pkgs/build-support/testers/shellcheck/tests.nix
Normal file
38
pkgs/build-support/testers/shellcheck/tests.nix
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# Run:
|
||||||
|
# nix-build -A tests.testers.shellcheck
|
||||||
|
|
||||||
|
{ lib, testers, runCommand }:
|
||||||
|
let
|
||||||
|
inherit (lib) fileset;
|
||||||
|
in
|
||||||
|
lib.recurseIntoAttrs {
|
||||||
|
|
||||||
|
example-dir = runCommand "test-testers-shellcheck-example-dir" {
|
||||||
|
failure = testers.testBuildFailure
|
||||||
|
(testers.shellcheck {
|
||||||
|
src = fileset.toSource {
|
||||||
|
root = ./.;
|
||||||
|
fileset = fileset.unions [
|
||||||
|
./example.sh
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} ''
|
||||||
|
log="$failure/testBuildFailure.log"
|
||||||
|
echo "Checking $log"
|
||||||
|
grep SC2068 "$log"
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
example-file = runCommand "test-testers-shellcheck-example-file" {
|
||||||
|
failure = testers.testBuildFailure
|
||||||
|
(testers.shellcheck {
|
||||||
|
src = ./example.sh;
|
||||||
|
});
|
||||||
|
} ''
|
||||||
|
log="$failure/testBuildFailure.log"
|
||||||
|
echo "Checking $log"
|
||||||
|
grep SC2068 "$log"
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
}
|
|
@ -16,6 +16,8 @@ lib.recurseIntoAttrs {
|
||||||
|
|
||||||
hasPkgConfigModules = pkgs.callPackage ../hasPkgConfigModules/tests.nix { };
|
hasPkgConfigModules = pkgs.callPackage ../hasPkgConfigModules/tests.nix { };
|
||||||
|
|
||||||
|
shellcheck = pkgs.callPackage ../shellcheck/tests.nix { };
|
||||||
|
|
||||||
runNixOSTest-example = pkgs-with-overlay.testers.runNixOSTest ({ lib, ... }: {
|
runNixOSTest-example = pkgs-with-overlay.testers.runNixOSTest ({ lib, ... }: {
|
||||||
name = "runNixOSTest-test";
|
name = "runNixOSTest-test";
|
||||||
nodes.machine = { pkgs, ... }: {
|
nodes.machine = { pkgs, ... }: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue