Skip to content

__structuredAttrs=false exports environment variables, but __structuredAttrs=true only declares them #14847

@ju1m

Description

@ju1m

Describe the bug

__structuredAttrs=true changes the behavior of environment variables given to derivation (same with mkDerivation) by not exporting them, causing subtle and possibly unnoticed bugs when enabled.

Steps To Reproduce

Without __structuredAttrs=true, FOO is exported:

$ nix -L build --no-link --print-out-paths --impure --expr '
  let pkgs = import (__getFlake "flake:nixpkgs") {}; in
  builtins.derivation {
    name = "script.sh";
    system = builtins.currentSystem;
    PATH = pkgs.lib.makeBinPath [pkgs.coreutils pkgs.gnugrep];
    FOO = "OK";
    builder=pkgs.lib.getExe pkgs.bash;
    args = ["-xc" "source \${NIX_ATTRS_SH_FILE:-/dev/null};
                   out=\${out:-\${outputs[out]}};
                   env | grep ^FOO= >\$out;
                   exit 0
                  "];
  }
' | xargs cat -n
script.sh> + source /dev/null
script.sh> + out=/nix/store/rfk147y3mxp970kzzaxaw8wpyy2k6bsv-script.sh
script.sh> + env
script.sh> + grep '^FOO='
script.sh> + exit 0
     1  FOO=OK

With __structuredAttrs=true, FOO is no longer exported:

$ nix -L build --no-link --print-out-paths --impure --expr '
  let pkgs = import (__getFlake "flake:nixpkgs") {}; in
  builtins.derivation {
    name="script.sh";
    system=builtins.currentSystem;
    PATH = pkgs.lib.makeBinPath [pkgs.coreutils pkgs.gnugrep];
    FOO="OK";
    builder=pkgs.lib.getExe pkgs.bash;
    args = ["-xc" "source \${NIX_ATTRS_SH_FILE:-/dev/null};
                   out=\${out:-\${outputs[out]}};
                   env | grep ^FOO= >\$out;
                   exit 0
                  "];
    __structuredAttrs=true;
  }
' | xargs cat -n
script.sh> + source /build/.attrs.sh
script.sh> ++ declare FOO=OK
script.sh> ++ declare PATH=/nix/store/rry6qingvsrqmc7ll7jgaqpybcbdgf5v-coreutils-9.7/bin:/nix/store/l2wvwyg680h0v2la18hz3yiznxy2naqw-gnugrep-3.11/bin
script.sh> ++ declare builder=/nix/store/smkzrg2vvp3lng3hq7v9svfni5mnqjh2-bash-interactive-5.2p37/bin/bash
script.sh> ++ declare name=script.sh
script.sh> ++ outputs=(['out']='/nix/store/721kijwr0kwkignw66cz7lr7r9mb2467-script.sh')
script.sh> ++ declare -A outputs
script.sh> ++ declare preferLocalBuild=1
script.sh> ++ declare system=x86_64-linux
script.sh> + out=/nix/store/721kijwr0kwkignw66cz7lr7r9mb2467-script.sh
script.sh> + env
script.sh> + grep '^FOO='
script.sh> + exit 0

Expected behavior

I expect the same behavior wrt. exporting environment variables regardless of whether __structuredAttrs is set or not.
I found nothing in the Nix or Nixpkgs manuals warning otherwise.

So, AFAIU, this should be declare -x there:

jsonSh += fmt("declare %s=%s\n", key, *s);

Metadata

$ nix-info
system: "x86_64-linux", multi-user?: yes, version: nix-env (Nix) 2.28.4, nixpkgs: /nix/store/8han14lkbind4nx63hqq3i2sv6fbqiy5-source

Additional context

I stumbled on that bug after enabling __structuredAttrs in mixRelease which then no longer exported MIX_ENV and other envvars, causing the package to no longer be built for MIX_ENV=prod but MIX_ENV=dev.
And it was not obvious at all why when debugging in the nix develop because checking with echo $MIX_ENV printed prod as I expected, but it was no longer exported, hence mix would default to a dev build.

Checklist


Add 👍 to issues you find important.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions