Loading doc/build-helpers/dev-shell-tools.chapter.md +46 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,49 @@ devShellTools.valueToString (builtins.toFile "foo" "bar") devShellTools.valueToString false => "" ``` ::: ## `devShellTools.unstructuredDerivationInputEnv` {#sec-devShellTools-unstructuredDerivationInputEnv} Convert a set of derivation attributes (as would be passed to [`derivation`]) to a set of environment variables that can be used in a shell script. This function does not support `__structuredAttrs`, but does support `passAsFile`. :::{.example} ## `unstructuredDerivationInputEnv` usage example ```nix devShellTools.unstructuredDerivationInputEnv { drvAttrs = { name = "foo"; buildInputs = [ hello figlet ]; builder = bash; args = [ "-c" "${./builder.sh}" ]; }; } => { name = "foo"; buildInputs = "/nix/store/...-hello /nix/store/...-figlet"; builder = "/nix/store/...-bash"; } ``` Note that `args` is not included, because Nix does not added it to the builder process environment. ::: ## `devShellTools.derivationOutputEnv` {#sec-devShellTools-derivationOutputEnv} Takes the relevant parts of a derivation and returns a set of environment variables, that would be present in the derivation. :::{.example} ## `derivationOutputEnv` usage example ```nix let pkg = hello; in devShellTools.derivationOutputEnv { outputList = pkg.outputs; outputMap = pkg; } ``` ::: nixos/tests/all-tests.nix +1 −0 Original line number Diff line number Diff line Loading @@ -264,6 +264,7 @@ in { docker-rootless = handleTestOn ["aarch64-linux" "x86_64-linux"] ./docker-rootless.nix {}; docker-registry = handleTest ./docker-registry.nix {}; docker-tools = handleTestOn ["x86_64-linux"] ./docker-tools.nix {}; docker-tools-nix-shell = runTest ./docker-tools-nix-shell.nix; docker-tools-cross = handleTestOn ["x86_64-linux" "aarch64-linux"] ./docker-tools-cross.nix {}; docker-tools-overlay = handleTestOn ["x86_64-linux"] ./docker-tools-overlay.nix {}; documize = handleTest ./documize.nix {}; Loading nixos/tests/docker-tools-nix-shell.nix 0 → 100644 +95 −0 Original line number Diff line number Diff line # nix-build -A nixosTests.docker-tools-nix-shell { config, lib, ... }: let inherit (config.node.pkgs.dockerTools) examples; in { name = "docker-tools-nix-shell"; meta = with lib.maintainers; { maintainers = [ infinisil roberth ]; }; nodes = { docker = { ... }: { virtualisation = { diskSize = 3072; docker.enable = true; }; }; }; testScript = '' docker.wait_for_unit("sockets.target") with subtest("buildImageWithNixDB: Has a nix database"): docker.succeed( "docker load --input='${examples.nix}'", "docker run --rm ${examples.nix.imageName} nix-store -q --references /bin/bash" ) with subtest("buildNixShellImage: Can build a basic derivation"): docker.succeed( "${examples.nix-shell-basic} | docker load", "docker run --rm nix-shell-basic bash -c 'buildDerivation && $out/bin/hello' | grep '^Hello, world!$'" ) with subtest("buildNixShellImage: Runs the shell hook"): docker.succeed( "${examples.nix-shell-hook} | docker load", "docker run --rm -it nix-shell-hook | grep 'This is the shell hook!'" ) with subtest("buildNixShellImage: Sources stdenv, making build inputs available"): docker.succeed( "${examples.nix-shell-inputs} | docker load", "docker run --rm -it nix-shell-inputs | grep 'Hello, world!'" ) with subtest("buildNixShellImage: passAsFile works"): docker.succeed( "${examples.nix-shell-pass-as-file} | docker load", "docker run --rm -it nix-shell-pass-as-file | grep 'this is a string'" ) with subtest("buildNixShellImage: run argument works"): docker.succeed( "${examples.nix-shell-run} | docker load", "docker run --rm -it nix-shell-run | grep 'This shell is not interactive'" ) with subtest("buildNixShellImage: command argument works"): docker.succeed( "${examples.nix-shell-command} | docker load", "docker run --rm -it nix-shell-command | grep 'This shell is interactive'" ) with subtest("buildNixShellImage: home directory is writable by default"): docker.succeed( "${examples.nix-shell-writable-home} | docker load", "docker run --rm -it nix-shell-writable-home" ) with subtest("buildNixShellImage: home directory can be made non-existent"): docker.succeed( "${examples.nix-shell-nonexistent-home} | docker load", "docker run --rm -it nix-shell-nonexistent-home" ) with subtest("buildNixShellImage: can build derivations"): docker.succeed( "${examples.nix-shell-build-derivation} | docker load", "docker run --rm -it nix-shell-build-derivation" ) with subtest("streamLayeredImage: with nix db"): docker.succeed( "${examples.nix-layered} | docker load", "docker run --rm ${examples.nix-layered.imageName} nix-store -q --references /bin/bash" ) ''; } nixos/tests/docker-tools.nix +1 −67 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ let }; nonRootTestImage = pkgs.dockerTools.streamLayeredImage rec { pkgs.dockerTools.streamLayeredImage { name = "non-root-test"; tag = "latest"; uid = 1000; Loading Loading @@ -567,66 +567,6 @@ in { docker.succeed("docker run --rm image-with-certs:latest test -r /etc/pki/tls/certs/ca-bundle.crt") docker.succeed("docker image rm image-with-certs:latest") with subtest("buildImageWithNixDB: Has a nix database"): docker.succeed( "docker load --input='${examples.nix}'", "docker run --rm ${examples.nix.imageName} nix-store -q --references /bin/bash" ) with subtest("buildNixShellImage: Can build a basic derivation"): docker.succeed( "${examples.nix-shell-basic} | docker load", "docker run --rm nix-shell-basic bash -c 'buildDerivation && $out/bin/hello' | grep '^Hello, world!$'" ) with subtest("buildNixShellImage: Runs the shell hook"): docker.succeed( "${examples.nix-shell-hook} | docker load", "docker run --rm -it nix-shell-hook | grep 'This is the shell hook!'" ) with subtest("buildNixShellImage: Sources stdenv, making build inputs available"): docker.succeed( "${examples.nix-shell-inputs} | docker load", "docker run --rm -it nix-shell-inputs | grep 'Hello, world!'" ) with subtest("buildNixShellImage: passAsFile works"): docker.succeed( "${examples.nix-shell-pass-as-file} | docker load", "docker run --rm -it nix-shell-pass-as-file | grep 'this is a string'" ) with subtest("buildNixShellImage: run argument works"): docker.succeed( "${examples.nix-shell-run} | docker load", "docker run --rm -it nix-shell-run | grep 'This shell is not interactive'" ) with subtest("buildNixShellImage: command argument works"): docker.succeed( "${examples.nix-shell-command} | docker load", "docker run --rm -it nix-shell-command | grep 'This shell is interactive'" ) with subtest("buildNixShellImage: home directory is writable by default"): docker.succeed( "${examples.nix-shell-writable-home} | docker load", "docker run --rm -it nix-shell-writable-home" ) with subtest("buildNixShellImage: home directory can be made non-existent"): docker.succeed( "${examples.nix-shell-nonexistent-home} | docker load", "docker run --rm -it nix-shell-nonexistent-home" ) with subtest("buildNixShellImage: can build derivations"): docker.succeed( "${examples.nix-shell-build-derivation} | docker load", "docker run --rm -it nix-shell-build-derivation" ) with subtest("streamLayeredImage: chown is persistent in fakeRootCommands"): docker.succeed( "${chownTestImage} | docker load", Loading @@ -638,11 +578,5 @@ in { "${nonRootTestImage} | docker load", "docker run --rm ${chownTestImage.imageName} | diff /dev/stdin <(echo 12345:12345)" ) with subtest("streamLayeredImage: with nix db"): docker.succeed( "${examples.nix-layered} | docker load", "docker run --rm ${examples.nix-layered.imageName} nix-store -q --references /bin/bash" ) ''; }) pkgs/build-support/dev-shell-tools/default.nix +50 −1 Original line number Diff line number Diff line { lib }: { lib, writeTextFile, }: let inherit (builtins) typeOf; in rec { # Docs: doc/build-helpers/dev-shell-tools.chapter.md # Tests: ./tests/default.nix # This function closely mirrors what this Nix code does: # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/primops.cc#L1102 # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/eval.cc#L1981-L2036 Loading @@ -13,4 +18,48 @@ rec { if typeOf value == "path" then "${value}" else if typeOf value == "list" then toString (map valueToString value) else toString value; # Docs: doc/build-helpers/dev-shell-tools.chapter.md # Tests: ./tests/default.nix # https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L992-L1004 unstructuredDerivationInputEnv = { drvAttrs }: # FIXME: this should be `normalAttrs // passAsFileAttrs` lib.mapAttrs' (name: value: let str = valueToString value; in if lib.elem name (drvAttrs.passAsFile or []) then let nameHash = if builtins?convertHash then builtins.convertHash { hash = "sha256:" + builtins.hashString "sha256" name; toHashFormat = "nix32"; } else builtins.hashString "sha256" name; basename = ".attr-${nameHash}"; in lib.nameValuePair "${name}Path" "${ writeTextFile { name = "shell-passAsFile-${name}"; text = str; destination = "/${basename}"; } }/${basename}" else lib.nameValuePair name str ) (removeAttrs drvAttrs [ # TODO: there may be more of these "args" ]); # Docs: doc/build-helpers/dev-shell-tools.chapter.md # Tests: ./tests/default.nix derivationOutputEnv = { outputList, outputMap }: # A mapping from output name to the nix store path where they should end up # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/primops.cc#L1253 lib.genAttrs outputList (output: builtins.unsafeDiscardStringContext outputMap.${output}.outPath); } Loading
doc/build-helpers/dev-shell-tools.chapter.md +46 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,49 @@ devShellTools.valueToString (builtins.toFile "foo" "bar") devShellTools.valueToString false => "" ``` ::: ## `devShellTools.unstructuredDerivationInputEnv` {#sec-devShellTools-unstructuredDerivationInputEnv} Convert a set of derivation attributes (as would be passed to [`derivation`]) to a set of environment variables that can be used in a shell script. This function does not support `__structuredAttrs`, but does support `passAsFile`. :::{.example} ## `unstructuredDerivationInputEnv` usage example ```nix devShellTools.unstructuredDerivationInputEnv { drvAttrs = { name = "foo"; buildInputs = [ hello figlet ]; builder = bash; args = [ "-c" "${./builder.sh}" ]; }; } => { name = "foo"; buildInputs = "/nix/store/...-hello /nix/store/...-figlet"; builder = "/nix/store/...-bash"; } ``` Note that `args` is not included, because Nix does not added it to the builder process environment. ::: ## `devShellTools.derivationOutputEnv` {#sec-devShellTools-derivationOutputEnv} Takes the relevant parts of a derivation and returns a set of environment variables, that would be present in the derivation. :::{.example} ## `derivationOutputEnv` usage example ```nix let pkg = hello; in devShellTools.derivationOutputEnv { outputList = pkg.outputs; outputMap = pkg; } ``` :::
nixos/tests/all-tests.nix +1 −0 Original line number Diff line number Diff line Loading @@ -264,6 +264,7 @@ in { docker-rootless = handleTestOn ["aarch64-linux" "x86_64-linux"] ./docker-rootless.nix {}; docker-registry = handleTest ./docker-registry.nix {}; docker-tools = handleTestOn ["x86_64-linux"] ./docker-tools.nix {}; docker-tools-nix-shell = runTest ./docker-tools-nix-shell.nix; docker-tools-cross = handleTestOn ["x86_64-linux" "aarch64-linux"] ./docker-tools-cross.nix {}; docker-tools-overlay = handleTestOn ["x86_64-linux"] ./docker-tools-overlay.nix {}; documize = handleTest ./documize.nix {}; Loading
nixos/tests/docker-tools-nix-shell.nix 0 → 100644 +95 −0 Original line number Diff line number Diff line # nix-build -A nixosTests.docker-tools-nix-shell { config, lib, ... }: let inherit (config.node.pkgs.dockerTools) examples; in { name = "docker-tools-nix-shell"; meta = with lib.maintainers; { maintainers = [ infinisil roberth ]; }; nodes = { docker = { ... }: { virtualisation = { diskSize = 3072; docker.enable = true; }; }; }; testScript = '' docker.wait_for_unit("sockets.target") with subtest("buildImageWithNixDB: Has a nix database"): docker.succeed( "docker load --input='${examples.nix}'", "docker run --rm ${examples.nix.imageName} nix-store -q --references /bin/bash" ) with subtest("buildNixShellImage: Can build a basic derivation"): docker.succeed( "${examples.nix-shell-basic} | docker load", "docker run --rm nix-shell-basic bash -c 'buildDerivation && $out/bin/hello' | grep '^Hello, world!$'" ) with subtest("buildNixShellImage: Runs the shell hook"): docker.succeed( "${examples.nix-shell-hook} | docker load", "docker run --rm -it nix-shell-hook | grep 'This is the shell hook!'" ) with subtest("buildNixShellImage: Sources stdenv, making build inputs available"): docker.succeed( "${examples.nix-shell-inputs} | docker load", "docker run --rm -it nix-shell-inputs | grep 'Hello, world!'" ) with subtest("buildNixShellImage: passAsFile works"): docker.succeed( "${examples.nix-shell-pass-as-file} | docker load", "docker run --rm -it nix-shell-pass-as-file | grep 'this is a string'" ) with subtest("buildNixShellImage: run argument works"): docker.succeed( "${examples.nix-shell-run} | docker load", "docker run --rm -it nix-shell-run | grep 'This shell is not interactive'" ) with subtest("buildNixShellImage: command argument works"): docker.succeed( "${examples.nix-shell-command} | docker load", "docker run --rm -it nix-shell-command | grep 'This shell is interactive'" ) with subtest("buildNixShellImage: home directory is writable by default"): docker.succeed( "${examples.nix-shell-writable-home} | docker load", "docker run --rm -it nix-shell-writable-home" ) with subtest("buildNixShellImage: home directory can be made non-existent"): docker.succeed( "${examples.nix-shell-nonexistent-home} | docker load", "docker run --rm -it nix-shell-nonexistent-home" ) with subtest("buildNixShellImage: can build derivations"): docker.succeed( "${examples.nix-shell-build-derivation} | docker load", "docker run --rm -it nix-shell-build-derivation" ) with subtest("streamLayeredImage: with nix db"): docker.succeed( "${examples.nix-layered} | docker load", "docker run --rm ${examples.nix-layered.imageName} nix-store -q --references /bin/bash" ) ''; }
nixos/tests/docker-tools.nix +1 −67 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ let }; nonRootTestImage = pkgs.dockerTools.streamLayeredImage rec { pkgs.dockerTools.streamLayeredImage { name = "non-root-test"; tag = "latest"; uid = 1000; Loading Loading @@ -567,66 +567,6 @@ in { docker.succeed("docker run --rm image-with-certs:latest test -r /etc/pki/tls/certs/ca-bundle.crt") docker.succeed("docker image rm image-with-certs:latest") with subtest("buildImageWithNixDB: Has a nix database"): docker.succeed( "docker load --input='${examples.nix}'", "docker run --rm ${examples.nix.imageName} nix-store -q --references /bin/bash" ) with subtest("buildNixShellImage: Can build a basic derivation"): docker.succeed( "${examples.nix-shell-basic} | docker load", "docker run --rm nix-shell-basic bash -c 'buildDerivation && $out/bin/hello' | grep '^Hello, world!$'" ) with subtest("buildNixShellImage: Runs the shell hook"): docker.succeed( "${examples.nix-shell-hook} | docker load", "docker run --rm -it nix-shell-hook | grep 'This is the shell hook!'" ) with subtest("buildNixShellImage: Sources stdenv, making build inputs available"): docker.succeed( "${examples.nix-shell-inputs} | docker load", "docker run --rm -it nix-shell-inputs | grep 'Hello, world!'" ) with subtest("buildNixShellImage: passAsFile works"): docker.succeed( "${examples.nix-shell-pass-as-file} | docker load", "docker run --rm -it nix-shell-pass-as-file | grep 'this is a string'" ) with subtest("buildNixShellImage: run argument works"): docker.succeed( "${examples.nix-shell-run} | docker load", "docker run --rm -it nix-shell-run | grep 'This shell is not interactive'" ) with subtest("buildNixShellImage: command argument works"): docker.succeed( "${examples.nix-shell-command} | docker load", "docker run --rm -it nix-shell-command | grep 'This shell is interactive'" ) with subtest("buildNixShellImage: home directory is writable by default"): docker.succeed( "${examples.nix-shell-writable-home} | docker load", "docker run --rm -it nix-shell-writable-home" ) with subtest("buildNixShellImage: home directory can be made non-existent"): docker.succeed( "${examples.nix-shell-nonexistent-home} | docker load", "docker run --rm -it nix-shell-nonexistent-home" ) with subtest("buildNixShellImage: can build derivations"): docker.succeed( "${examples.nix-shell-build-derivation} | docker load", "docker run --rm -it nix-shell-build-derivation" ) with subtest("streamLayeredImage: chown is persistent in fakeRootCommands"): docker.succeed( "${chownTestImage} | docker load", Loading @@ -638,11 +578,5 @@ in { "${nonRootTestImage} | docker load", "docker run --rm ${chownTestImage.imageName} | diff /dev/stdin <(echo 12345:12345)" ) with subtest("streamLayeredImage: with nix db"): docker.succeed( "${examples.nix-layered} | docker load", "docker run --rm ${examples.nix-layered.imageName} nix-store -q --references /bin/bash" ) ''; })
pkgs/build-support/dev-shell-tools/default.nix +50 −1 Original line number Diff line number Diff line { lib }: { lib, writeTextFile, }: let inherit (builtins) typeOf; in rec { # Docs: doc/build-helpers/dev-shell-tools.chapter.md # Tests: ./tests/default.nix # This function closely mirrors what this Nix code does: # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/primops.cc#L1102 # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/eval.cc#L1981-L2036 Loading @@ -13,4 +18,48 @@ rec { if typeOf value == "path" then "${value}" else if typeOf value == "list" then toString (map valueToString value) else toString value; # Docs: doc/build-helpers/dev-shell-tools.chapter.md # Tests: ./tests/default.nix # https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L992-L1004 unstructuredDerivationInputEnv = { drvAttrs }: # FIXME: this should be `normalAttrs // passAsFileAttrs` lib.mapAttrs' (name: value: let str = valueToString value; in if lib.elem name (drvAttrs.passAsFile or []) then let nameHash = if builtins?convertHash then builtins.convertHash { hash = "sha256:" + builtins.hashString "sha256" name; toHashFormat = "nix32"; } else builtins.hashString "sha256" name; basename = ".attr-${nameHash}"; in lib.nameValuePair "${name}Path" "${ writeTextFile { name = "shell-passAsFile-${name}"; text = str; destination = "/${basename}"; } }/${basename}" else lib.nameValuePair name str ) (removeAttrs drvAttrs [ # TODO: there may be more of these "args" ]); # Docs: doc/build-helpers/dev-shell-tools.chapter.md # Tests: ./tests/default.nix derivationOutputEnv = { outputList, outputMap }: # A mapping from output name to the nix store path where they should end up # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/primops.cc#L1253 lib.genAttrs outputList (output: builtins.unsafeDiscardStringContext outputMap.${output}.outPath); }