testers.shellcheck: refactor, update docs, and simplify tests (#385940)

This commit is contained in:
Connor Baker 2025-03-07 20:53:33 -08:00 committed by GitHub
commit 871cda0b06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 56 additions and 59 deletions

View File

@ -118,7 +118,7 @@ It has two modes:
## `shellcheck` {#tester-shellcheck} ## `shellcheck` {#tester-shellcheck}
Runs files through `shellcheck`, a static analysis tool for shell scripts. Run files through `shellcheck`, a static analysis tool for shell scripts, failing if there are any issues.
:::{.example #ex-shellcheck} :::{.example #ex-shellcheck}
# Run `testers.shellcheck` # Run `testers.shellcheck`
@ -127,7 +127,7 @@ A single script
```nix ```nix
testers.shellcheck { testers.shellcheck {
name = "shellcheck"; name = "script";
src = ./script.sh; src = ./script.sh;
} }
``` ```
@ -139,7 +139,7 @@ let
inherit (lib) fileset; inherit (lib) fileset;
in in
testers.shellcheck { testers.shellcheck {
name = "shellcheck"; name = "nixbsd-activate";
src = fileset.toSource { src = fileset.toSource {
root = ./.; root = ./.;
fileset = fileset.unions [ fileset = fileset.unions [
@ -154,15 +154,20 @@ testers.shellcheck {
### Inputs {#tester-shellcheck-inputs} ### Inputs {#tester-shellcheck-inputs}
[`src` (path or string)]{#tester-shellcheck-param-src} `name` (string, optional)
: The name of the test.
`name` will be required at a future point because it massively improves traceability of test failures, but is kept optional for now to avoid breaking existing usages.
Defaults to `run-shellcheck`.
The name of the derivation produced by the tester is `shellcheck-${name}` when `name` is supplied.
`src` (path-like)
: The path to the shell script(s) to check. : The path to the shell script(s) to check.
This can be a single file or a directory containing shell files. 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. 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} ### Return value {#tester-shellcheck-return}
A derivation that runs `shellcheck` on the given script(s). A derivation that runs `shellcheck` on the given script(s), producing an empty output if no issues are found.
The build will fail if `shellcheck` finds any issues. The build will fail if `shellcheck` finds any issues.
## `shfmt` {#tester-shfmt} ## `shfmt` {#tester-shfmt}

View File

@ -1557,9 +1557,6 @@
"tester-shellcheck-inputs": [ "tester-shellcheck-inputs": [
"index.html#tester-shellcheck-inputs" "index.html#tester-shellcheck-inputs"
], ],
"tester-shellcheck-param-src": [
"index.html#tester-shellcheck-param-src"
],
"tester-shellcheck-return": [ "tester-shellcheck-return": [
"index.html#tester-shellcheck-return" "index.html#tester-shellcheck-return"
], ],

View File

@ -18,6 +18,9 @@
- The hand written `perlPackages.SearchXapian` bindings have been dropped in favor of the (mostly compatible) - The hand written `perlPackages.SearchXapian` bindings have been dropped in favor of the (mostly compatible)
`perlPackages.Xapian`. `perlPackages.Xapian`.
- [testers.shellcheck](https://nixos.org/manual/nixpkgs/unstable/#tester-shellcheck) now warns when `name` is not provided.
The `name` argument will become mandatory in a future release.
- The `nixLog*` family of functions made available through the standard environment have been rewritten to prefix messages with both the debug level and the function name of the caller. - The `nixLog*` family of functions made available through the standard environment have been rewritten to prefix messages with both the debug level and the function name of the caller.
The `nixLog` function, which logs unconditionally, was also re-introduced and modified to prefix messages with the function name of the caller. The `nixLog` function, which logs unconditionally, was also re-introduced and modified to prefix messages with the function name of the caller.
For more information, [see this PR](https://github.com/NixOS/nixpkgs/pull/370742). For more information, [see this PR](https://github.com/NixOS/nixpkgs/pull/370742).

View File

@ -5,6 +5,7 @@ let
inherit (lib) fileset; inherit (lib) fileset;
runShellcheck = testers.shellcheck { runShellcheck = testers.shellcheck {
name = "activation-check";
src = fileset.toSource { src = fileset.toSource {
root = ./.; root = ./.;
fileset = fileset.unions [ fileset = fileset.unions [

View File

@ -31,6 +31,7 @@ let
}; };
runShellcheck = testers.shellcheck { runShellcheck = testers.shellcheck {
name = "activation-lib";
src = runTests.src; src = runTests.src;
}; };

View File

@ -1,39 +1,35 @@
# Dependencies (callPackage) # Dependencies (callPackage)
{ {
lib, lib,
stdenv, stdenvNoCC,
runCommand,
shellcheck, shellcheck,
}: }:
# testers.shellcheck function # testers.shellcheck function
# Docs: doc/build-helpers/testers.chapter.md # Docs: doc/build-helpers/testers.chapter.md
# Tests: ./tests.nix # Tests: ./tests.nix
{ src }: {
let name ? null,
inherit (lib) pathType isPath; src,
in }:
stdenv.mkDerivation { stdenvNoCC.mkDerivation {
name = "run-shellcheck"; __structuredAttrs = true;
src = strictDeps = true;
if name =
isPath src && pathType src == "regular" # note that for strings this would have been IFD, which we prefer to avoid if name == null then
then lib.warn "testers.shellcheck: name will be required in a future release, defaulting to run-shellcheck" "run-shellcheck"
runCommand "testers-shellcheck-src" { } ''
mkdir $out
cp ${src} $out
''
else else
src; "shellcheck-${name}";
inherit src;
dontUnpack = true; # Unpack phase tries to extract an archive, which we don't want to do with source trees
nativeBuildInputs = [ shellcheck ]; nativeBuildInputs = [ shellcheck ];
doCheck = true; doCheck = true;
dontConfigure = true; dontConfigure = true;
dontBuild = true; dontBuild = true;
checkPhase = '' checkPhase = ''
find . -type f -print0 \ find "$src" -type f -print0 | xargs -0 shellcheck
| xargs -0 shellcheck
''; '';
installPhase = '' installPhase = ''
touch $out touch "$out"
''; '';
} }

View File

@ -4,39 +4,33 @@
{ {
lib, lib,
testers, testers,
runCommand,
}: }:
lib.recurseIntoAttrs { lib.recurseIntoAttrs {
example-dir = testers.testBuildFailure' {
example-dir = drv = testers.shellcheck {
runCommand "test-testers-shellcheck-example-dir" name = "example-dir";
{ src = ./src;
failure = testers.testBuildFailure ( };
testers.shellcheck { expectedBuilderExitCode = 123;
src = ./src; expectedBuilderLogEntries = [
}
);
}
'' ''
log="$failure/testBuildFailure.log" echo $@
echo "Checking $log" ^-- SC2068 (error): Double quote array expansions to avoid re-splitting elements.
grep SC2068 "$log"
touch $out
'';
example-file =
runCommand "test-testers-shellcheck-example-file"
{
failure = testers.testBuildFailure (
testers.shellcheck {
src = ./src/example.sh;
}
);
}
'' ''
log="$failure/testBuildFailure.log" ];
echo "Checking $log" };
grep SC2068 "$log"
touch $out example-file = testers.testBuildFailure' {
''; drv = testers.shellcheck {
name = "example-file";
src = ./src/example.sh;
};
expectedBuilderExitCode = 123;
expectedBuilderLogEntries = [
''
echo $@
^-- SC2068 (error): Double quote array expansions to avoid re-splitting elements.
''
];
};
} }