Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib.trivial: rename NIX_ABORT_ON_WARN to NIXPKGS_ABORT_ON_WARN #306026

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

stuebinm
Copy link
Contributor

Description of changes

Renames the NIX_ABORT_ON_WARN environment variable to NIXPKGS_ABORT_ON_WARNto make it consistent with other environment variables read by nixpkgs to configure its behaviour (e.g. NIXPKGS_ALLOW_INSECURE etc.). The previous naming appeared to suggest that the variable is read by Nix itself, which it is not. This is especially a source of confusion when used together with Nix's pure evaluation mode, in which case setting the variable has no effect.

The old NIX_ABORT_ON_WARN is still honoured, but produces a deprecation warning. This warning's check is added as a wrapper to the entire lib.trivial attrset, as it should be checked (and, if necessary, printed) regardless of whether or not a use of lib.warn is encountered, but whenever the lib.warn function is available (i.e. whenever lib itself is evaluated), so that users of NIX_ABORT_ON_WARN will see it even if their code does not currently produce any warnings. Likewise, this means that the warning does not actually abort evaluation, as otherwise downstream users of NIX_ABORT_ON_WARN would be immediately presented with an unrecoverable error.

This deprecation warning and honouring of the older behaviour can then be removed in a future release.

Downsides

For reasons which remain mysterious to me, the deprecation warning is printed eight times if nixpkgs is imported as a flake:

$ NIX_ABORT_ON_WARN=1 nix build .#hello --impure
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.

but only once if imported in the traditional way:

$ NIX_ABORT_ON_WARN=1 nix build -f . hello
trace: warning: NIX_ABORT_ON_WARN has been renamed to NIXPKGS_ABORT_ON_WARN. NIX_ABORT_ON_WARN is still honored, but deprecated and will be removed from nixpkgs after the 24.11 release.

This is only a minor annoyance, but does perhaps (?) point to an unrelated issue with how the nixpkgs flake handles importing lib.

Alternatives

There are a few possible placements for the deprecation warning & its check in the code:

  • inside lib.warn itself: seems the most logical place to put it, but it would then only be shown if a warning is actually produced. As (presumably) most users of NIX_ABORT_ON_WARN will strive to keep their code free of warnings, this could lead to them never seeing the deprecation message.
  • outside of lib/, e.g. in pkgs/top-level/impure.nix: i am very hesitant to touch that file, since even slight mistakes would possibly have large consequences. However, it is the only place i could find where, if placed there, the warning is only ever printed once even when using nixpkgs as a flake.

Question

Should this change be mentioned in the release notes? I was unable to find any clear guidelines on what (if any) changes to lib should get an entry there.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 24.05 Release Notes (or backporting 23.05 and 23.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

Copy link
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just minor thoughts, but overall this is looking good to me! This is a really tricky change, but your explanation makes a lot of sense!

The multiple messages for Flakes can be fixed by putting the builtins.trace before even the { lib }: part of the file (builtins.trace "..." ({ lib }: ...)). But this does feel a bit too ugly..

So indeed I think it would be better to figure out why the Flake handling appears to import lib that many times. But this can be done in a separate PR :)

Ping @roberth as the one who introduced this environment variable

lib/trivial.nix Outdated
# uses of this variable would immediately result in an unrecoverable
# error where there should be a deprecation warning.
printDeprecationWarning =
if builtins.getEnv "NIX_ABORT_ON_WARN" != "" then
Copy link
Member

@infinisil infinisil Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if builtins.getEnv "NIX_ABORT_ON_WARN" != "" then
if lib.isInOldestRelease 2405 && builtins.getEnv "NIX_ABORT_ON_WARN" != "" then

This needs some code rearranging or inlining to get working without infinite recursion, but this makes sure that there's a transition period where stable third party projects can switch to NIXPKGS_ABORT_ON_WARN without warnings for end-users.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have done so, though aesthetically I don't particularly like the result. If you can think of any nicer way to do this, please let me know / feel free to edit this branch.

if lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"]
then msg: builtins.trace "warning: ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
if lib.elem (builtins.getEnv "NIXPKGS_ABORT_ON_WARN") [ "1" "true" "yes" ]
|| lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [ "1" "true" "yes" ]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have a comment here to mention that this one is deprecated, referring to printDeprecationWarning

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added one

@roberth
Copy link
Member

roberth commented Apr 22, 2024

While your reasoning makes sense, my original goal was to build this functionality into Nix.
I haven't followed through on that, because at the time, there wasn't a Nix team yet, and it proved really hard to get anything merged.
So my preferred way forward is to still build this into Nix.

  1. Add builtins.warn, which logs at the correct Nix log level instead of just ANSI codes at "info" level.
  2. Add a Nix config option abort-on-warn that defaults to the NIX_ABORT_ON_WARN value.
  3. Change lib.warn to builtins.warn or ..., where the current implementation will serve as a good polyfill.

This PR would not prevent that from happening, but it would be messier, as users first have to learn to use NIXPKGS_ABORT_ON_WARN, and then switch back to NIX_ABORT_ON_WARN or --abort-on-warn. If we leave Nixpkgs as is, there's no need to learn anything.

Also there's an argument to be made that lib is fairly universal, and users might not perceive themselves as interacting with Nixpkgs when they need this behavior. For instance, they might be trying to solve a problem in a module system application like home-manager, which is not Nixpkgs.

this makes it consistent with other environment variables read by
nixpkgs to configure its behaviour. The previous naming appeared to
suggest that the variable is read by Nix itself, which it is not. This
is especially a source of confusion when used together with Nix's pure
evaluation mode, in which case setting the variable has no effect.

The old NIX_ABORT_ON_WARN is still honoured, but produces a deprecation
warning. This warning's check is added as a wrapper to the entire
lib.trivial attrset, as it should be checked (and, if necessary,
printed) regardless of whether or not a use of lib.warn is encountered,
but whenever the lib.warn function is available (i.e. whenever lib
itself is evaluated), so that users of NIX_ABORT_ON_WARN will see it
even if their code does not currently produce any warnings. Likewise,
this means that the warning does not actually abort evaluation, as
otherwise downstream users of NIX_ABORT_ON_WARN would be immediately
presented with an unrecoverable error.
As by NixOS#306026 (comment)

This has to temporarily move oldestSupportedRelease up outside the main
attribute set so that it can be used before lib.trivial itself is defined.
@stuebinm
Copy link
Contributor Author

@roberth

So my preferred way forward is to still build this into Nix

This would, of course, be the cleaner way to do it, and I'd much prefer it over the current situation. However, the current state has now existed for ~two and a half years, and unless I've overlooked something (admittedly possible, github search being what it is) there have been no plans to actually change it on the nix side after it was not done during or after adding builtins.traceVerbose.

but it would be messier, as users first have to learn to use NIXPKGS_ABORT_ON_WARN, and then switch back to NIX_ABORT_ON_WARN or --abort-on-warn. If we leave Nixpkgs as is, there's no need to learn anything.

yes there is: the need to learn that this variable behaves differently then expected, and that it does not work in pure evaluation mode (which recently cost me some time during and after #303841 while looking at how the module options documentation is built, and how to check that it does, indeed, still work — and I expect others will have run into similarly confusing corners when dealing with it).

So while I can see the motivation for waiting further, to reduce possible future confusion later on (in case this gets merged & then nix does add a similar feature), I'm a little skeptical of doing so if this means keeping a current source of confusion around for (potentially) an undefined future period of time.

@lorenzleutgeb
Copy link
Member

When I found out about this environment variable recently (ngi-nix/ngipkgs#155 and consequently https://discourse.nixos.org/t/disallow-warnings-on-nix-flake-check/38964) I had this change in mind, too, but did not follow through. I support @stuebinm's reasoning. No matter what happens upstream in Nix, this environment variable should have the prefix NIXPKGS_ not NIX_ (as explained). If at some point a new built-in or similar appears, then there'll just have to be another change. I am one of the few (?) "users" of this environment variable and don't mind re-learning.

@roberth
Copy link
Member

roberth commented Apr 22, 2024

I've just opened NixOS/nix#10592. Sorry for dropping the ball earlier.
I think the team can merge this after the release, if not sooner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants