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

showOption giving incorrect location for modules brought in via Flakes #11210

Closed
fzakaria opened this issue Jul 28, 2024 · 4 comments
Closed
Labels

Comments

@fzakaria
Copy link
Contributor

Describe the bug

I'm using lib.showOptionWithDefLocs which {option}.files --
The result of files seems to be incorrect when the option is brought in via a Flake.

Steps To Reproduce

Minimal flake:

{
  inputs = {
    # Nixpkgs
    nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
  };

  outputs = {
    self,
    nixpkgs,
    ...
  } @ inputs: let
    inherit (self) outputs;
    # Supported systems for your flake packages, shell, etc.
    systems = [
      "x86_64-linux
    ];
    forAllSystems = nixpkgs.lib.genAttrs systems;

    machine = name:
      nixpkgs.lib.nixosSystem {
        specialArgs = {inherit inputs outputs;};
        modules = [
          ./machines/${name}/configuration.nix
        ];
      };
  in {
    packages = forAllSystems (system: import ./pkgs nixpkgs.legacyPackages.${system});
    nixosModules = import ./modules/nixos;

    nixosConfigurations = {
      nyx = machine "nyx";
    };
}

Create a NixOS module in ./modules like:

{lib, ...}: {
  config = {
    services.tailscale.enable = false;
  };
}

Import it through the outputs in your configuration.nix

{
  inputs,
  outputs,
  config,
  lib,
  pkgs,
  ...
}: {
  imports = [
    outputs.nixosModules.testModule
  ];
}

When I use the REPL it only shows my configuration.nix

nix-repl> options.services.tailscale.enable.files   
[
  "/nix/store/ic635x2c2rir92ipb5c7fcyl8xlgcikn-source/machines/nyx/configuration.nix"
]

Expected behavior

I expect it to show the file location

nix-repl> options.services.tailscale.enable.files   
[
  "/nix/store/bbz7s2lcz6dbzjmf4j30gyfqq954zg0g-source/modules/nixos/testModule.nix"
]

nix-env --version output: nix-env (Nix) 2.23.2

Additional context

This seems to work correctly for modules that are references by file paths. import ./testModule

It also doesn't work for any module brought in via Flakes; not just the one defined within my current Flake.
For instance, I am using agenix and incorporating like so:

 imports = [
    inputs.agenix.nixosModules.default
  ];

This also gives the wrong value.

nix-repl> options.age.ageBin.files                  
[
  "/nix/store/ic635x2c2rir92ipb5c7fcyl8xlgcikn-source/machines/nyx/configuration.nix"
]

Priorities

Add 👍 to issues you find important.

@fzakaria fzakaria added the bug label Jul 28, 2024
@roberth
Copy link
Member

roberth commented Jul 29, 2024

The example doesn't seem to be quite complete, so I haven't evaluated it, but this might be expected Module System behavior.
Specifically the expression

import ./testModule

effectively throws away the file name because of import.

If you're not passing arguments to a function that returns the module, you can just remove import. Otherwise, you can simultaneously import and apply arguments using

I believe that should cover all use cases, except perhaps deduplication of the imported module, which is tricky, as discussed in that thread.

@fzakaria
Copy link
Contributor Author

Wow -- so this is kind of a bad anti-pattern that you can either reference a path or import it;
both work but have very different traceability.

is there a way to somehow test for a NixOS module use and check if it's brought in via import?
Seems like something a formatter/linter could check.

I opened ryantm/agenix#277 as an example of somewhere that had this bug.

We can close this issue but it might need another to document the "better" approach at a minimum.
(Best solution would be to warn against it?)

Thank you @roberth for the explanation; it was very confusing.

@roberth
Copy link
Member

roberth commented Jul 29, 2024

I think linting this is tricky, because you may have to do some eval to find the modules, but also you have to not actually evaluate the modules themselves and then inspect the thunk to make sure it's not a call to import. It basically means that it has to be the first thing that gets checked, and you have to hope that they don't get evaluated in the process. For example if they're behind a filterAttrs call, that's game over unless the predicate function only checks the name.

Maybe nixd/nixf could do something clever?

Anyway, I agree we can close this as far as Nix is concerned.

@roberth
Copy link
Member

roberth commented Jul 29, 2024

Linting might work quite well in many cases. Thanks for the suggestion.
I've opened nix-community/nixd#556

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

No branches or pull requests

2 participants