diff options
author | Alyssa Ross <hi@alyssa.is> | 2024-02-13 12:25:07 +0100 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2024-02-13 12:25:07 +0100 |
commit | a5e1520e4538e29ecfbd4b168306f890566d7bfd (patch) | |
tree | 28099c268b5d4b1e33c2b29f0714c45f0b961382 /nixpkgs/pkgs/build-support/trivial-builders | |
parent | 822f7c15c04567fbdc27020e862ea2b70cfbf8eb (diff) | |
parent | 3560d1c8269d0091b9aae10731b5e85274b7bbc1 (diff) | |
download | nixlib-a5e1520e4538e29ecfbd4b168306f890566d7bfd.tar nixlib-a5e1520e4538e29ecfbd4b168306f890566d7bfd.tar.gz nixlib-a5e1520e4538e29ecfbd4b168306f890566d7bfd.tar.bz2 nixlib-a5e1520e4538e29ecfbd4b168306f890566d7bfd.tar.lz nixlib-a5e1520e4538e29ecfbd4b168306f890566d7bfd.tar.xz nixlib-a5e1520e4538e29ecfbd4b168306f890566d7bfd.tar.zst nixlib-a5e1520e4538e29ecfbd4b168306f890566d7bfd.zip |
Merge branch 'nixos-unstable-small' of https://github.com/NixOS/nixpkgs
Conflicts: nixpkgs/nixos/modules/services/mail/rss2email.nix nixpkgs/pkgs/build-support/go/module.nix
Diffstat (limited to 'nixpkgs/pkgs/build-support/trivial-builders')
-rw-r--r-- | nixpkgs/pkgs/build-support/trivial-builders/default.nix | 127 | ||||
-rw-r--r-- | nixpkgs/pkgs/build-support/trivial-builders/test/writeShellApplication.nix | 152 |
2 files changed, 217 insertions, 62 deletions
diff --git a/nixpkgs/pkgs/build-support/trivial-builders/default.nix b/nixpkgs/pkgs/build-support/trivial-builders/default.nix index 9643c9ba048e..a38231bdcaa3 100644 --- a/nixpkgs/pkgs/build-support/trivial-builders/default.nix +++ b/nixpkgs/pkgs/build-support/trivial-builders/default.nix @@ -152,19 +152,21 @@ rec { , meta ? { } , allowSubstitutes ? false , preferLocalBuild ? true + , derivationArgs ? { } # Extra arguments to pass to `stdenv.mkDerivation` }: let matches = builtins.match "/bin/([^/]+)" destination; in runCommand name - { + ({ inherit text executable checkPhase allowSubstitutes preferLocalBuild; - passAsFile = [ "text" ]; + passAsFile = [ "text" ] + ++ derivationArgs.passAsFile or [ ]; meta = lib.optionalAttrs (executable && matches != null) { mainProgram = lib.head matches; - } // meta; - } + } // meta // derivationArgs.meta or {}; + } // removeAttrs derivationArgs [ "passAsFile" "meta" ]) '' target=$out${lib.escapeShellArg destination} mkdir -p "$(dirname "$target")" @@ -238,53 +240,94 @@ rec { meta.mainProgram = name; }; - /* - Similar to writeShellScriptBin and writeScriptBin. - Writes an executable Shell script to /nix/store/<store path>/bin/<name> and - checks its syntax with shellcheck and the shell's -n option. - Individual checks can be foregone by putting them in the excludeShellChecks - list, e.g. [ "SC2016" ]. - Automatically includes sane set of shellopts (errexit, nounset, pipefail) - and handles creation of PATH based on runtimeInputs - - Note that the checkPhase uses stdenv.shell for the test run of the script, - while the generated shebang uses runtimeShell. If, for whatever reason, - those were to mismatch you might lose fidelity in the default checks. - - Example: - - Writes my-file to /nix/store/<store path>/bin/my-file and makes executable. - - - writeShellApplication { - name = "my-file"; - runtimeInputs = [ curl w3m ]; - text = '' - curl -s 'https://nixos.org' | w3m -dump -T text/html - ''; - } - - */ + # See doc/build-helpers/trivial-build-helpers.chapter.md + # or https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-text-writing writeShellApplication = - { name - , text - , runtimeInputs ? [ ] - , meta ? { } - , checkPhase ? null - , excludeShellChecks ? [ ] + { + /* + The name of the script to write. + + Type: String + */ + name, + /* + The shell script's text, not including a shebang. + + Type: String + */ + text, + /* + Inputs to add to the shell script's `$PATH` at runtime. + + Type: [String|Derivation] + */ + runtimeInputs ? [ ], + /* + Extra environment variables to set at runtime. + + Type: AttrSet + */ + runtimeEnv ? null, + /* + `stdenv.mkDerivation`'s `meta` argument. + + Type: AttrSet + */ + meta ? { }, + /* + The `checkPhase` to run. Defaults to `shellcheck` on supported + platforms and `bash -n`. + + The script path will be given as `$target` in the `checkPhase`. + + Type: String + */ + checkPhase ? null, + /* + Checks to exclude when running `shellcheck`, e.g. `[ "SC2016" ]`. + + See <https://www.shellcheck.net/wiki/> for a list of checks. + + Type: [String] + */ + excludeShellChecks ? [ ], + /* + Bash options to activate with `set -o` at the start of the script. + + Defaults to `[ "errexit" "nounset" "pipefail" ]`. + + Type: [String] + */ + bashOptions ? [ "errexit" "nounset" "pipefail" ], + /* Extra arguments to pass to `stdenv.mkDerivation`. + + :::{.caution} + Certain derivation attributes are used internally, + overriding those could cause problems. + ::: + + Type: AttrSet + */ + derivationArgs ? { }, }: writeTextFile { - inherit name meta; + inherit name meta derivationArgs; executable = true; destination = "/bin/${name}"; allowSubstitutes = true; preferLocalBuild = false; text = '' #!${runtimeShell} - set -o errexit - set -o nounset - set -o pipefail - '' + lib.optionalString (runtimeInputs != [ ]) '' + ${lib.concatMapStringsSep "\n" (option: "set -o ${option}") bashOptions} + '' + lib.optionalString (runtimeEnv != null) + (lib.concatStrings + (lib.mapAttrsToList + (name: value: '' + ${lib.toShellVar name value} + export ${name} + '') + runtimeEnv)) + + lib.optionalString (runtimeInputs != [ ]) '' export PATH="${lib.makeBinPath runtimeInputs}:$PATH" '' + '' diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/writeShellApplication.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/writeShellApplication.nix index 6ce6f0720fcf..c50f5a4d283f 100644 --- a/nixpkgs/pkgs/build-support/trivial-builders/test/writeShellApplication.nix +++ b/nixpkgs/pkgs/build-support/trivial-builders/test/writeShellApplication.nix @@ -1,29 +1,141 @@ -/* - Run with: +# Run with: +# nix-build -A tests.trivial-builders.writeShellApplication +{ writeShellApplication +, writeTextFile +, runCommand +, lib +, linkFarm +, diffutils +, hello +}: +let + checkShellApplication = args@{name, expected, ...}: + let + writeShellApplicationArgs = builtins.removeAttrs args ["expected"]; + script = writeShellApplication writeShellApplicationArgs; + executable = lib.getExe script; + expected' = writeTextFile { + name = "${name}-expected"; + text = expected; + }; + actual = "${name}-actual"; + in + runCommand name { } '' + echo "Running test executable ${name}" + ${executable} > ${actual} + echo "Got output from test executable:" + cat ${actual} + echo "Checking test output against expected output:" + ${diffutils}/bin/diff --color --unified ${expected'} ${actual} + touch $out + ''; +in +linkFarm "writeShellApplication-tests" { + test-meta = + let + script = writeShellApplication { + name = "test-meta"; + text = ""; + meta.description = "A test for the `writeShellApplication` `meta` argument."; + }; + in + assert script.meta.mainProgram == "test-meta"; + assert script.meta.description == "A test for the `writeShellApplication` `meta` argument."; + script; - cd nixpkgs - nix-build -A tests.trivial-builders.writeShellApplication -*/ + test-runtime-inputs = + checkShellApplication { + name = "test-runtime-inputs"; + text = '' + hello + ''; + runtimeInputs = [ hello ]; + expected = "Hello, world!\n"; + }; -{ lib, writeShellApplication, runCommand }: -let - pkg = writeShellApplication { - name = "test-script"; + test-runtime-env = + checkShellApplication { + name = "test-runtime-env"; + runtimeEnv = { + MY_COOL_ENV_VAR = "my-cool-env-value"; + MY_OTHER_COOL_ENV_VAR = "my-other-cool-env-value"; + # Check that we can serialize a bunch of different types: + BOOL = true; + INT = 1; + LIST = [1 2 3]; + MAP = { + a = "a"; + b = "b"; + }; + }; + text = '' + echo "$MY_COOL_ENV_VAR" + echo "$MY_OTHER_COOL_ENV_VAR" + ''; + expected = '' + my-cool-env-value + my-other-cool-env-value + ''; + }; + + test-check-phase = + checkShellApplication { + name = "test-check-phase"; + text = ""; + checkPhase = '' + echo "echo -n hello" > $target + ''; + expected = "hello"; + }; + + test-argument-forwarding = + checkShellApplication { + name = "test-argument-forwarding"; + text = ""; + derivationArgs.MY_BUILD_TIME_VARIABLE = "puppy"; + derivationArgs.postCheck = '' + if [[ "$MY_BUILD_TIME_VARIABLE" != puppy ]]; then + echo "\$MY_BUILD_TIME_VARIABLE is not set to 'puppy'!" + exit 1 + fi + ''; + meta.description = "A test checking that `writeShellApplication` forwards extra arguments to `stdenv.mkDerivation`."; + expected = ""; + }; + + test-exclude-shell-checks = writeShellApplication { + name = "test-exclude-shell-checks"; excludeShellChecks = [ "SC2016" ]; text = '' - echo -e '#!/usr/bin/env bash\n' \ - 'echo "$SHELL"' > /tmp/something.sh # this line would normally - # ...cause shellcheck error + # Triggers SC2016: Expressions don't expand in single quotes, use double + # quotes for that. + echo '$SHELL' ''; }; -in - assert pkg.meta.mainProgram == "test-script"; - runCommand "test-writeShellApplication" { } '' - echo Testing if writeShellApplication builds without shellcheck error... - - target=${lib.getExe pkg} + test-bash-options-pipefail = checkShellApplication { + name = "test-bash-options-pipefail"; + text = '' + touch my-test-file + echo puppy | grep doggy | sed 's/doggy/puppy/g' + # ^^^^^^^^^^ This will fail. + true + ''; + # Don't use `pipefail`: + bashOptions = ["errexit" "nounset"]; + expected = ""; + }; - touch $out - '' + test-bash-options-nounset = checkShellApplication { + name = "test-bash-options-nounset"; + text = '' + echo -n "$someUndefinedVariable" + ''; + # Don't use `nounset`: + bashOptions = []; + # Don't warn about the undefined variable at build time: + excludeShellChecks = [ "SC2154" ]; + expected = ""; + }; +} |