GithubHelp home page GithubHelp logo

hercules-ci / flake-parts Goto Github PK

View Code? Open in Web Editor NEW
614.0 18.0 34.0 242 KB

❄️ Simplify Nix Flakes with the module system

Home Page: https://flake.parts

License: MIT License

Nix 99.95% Shell 0.05%
flakes nix nixos flake-parts nix-modules

flake-parts's Introduction

Flake Parts

Core of a distributed framework for writing Nix Flakes.

flake-parts provides the options that represent standard flake attributes and establishes a way of working with system. Opinionated features are provided by an ecosystem of modules that you can import.

flake-parts itself has the goal to be a minimal mirror of the Nix flake schema. Used by itself, it is very lightweight.


Documentation: flake.parts


Why Modules?

Flakes are configuration. The module system lets you refactor configuration into modules that can be shared.

It reduces the proliferation of custom Nix glue code, similar to what the module system has done for NixOS configurations.

Unlike NixOS, but following Flakes' spirit, flake-parts is not a monorepo with the implied goal of absorbing all of open source, but rather a single module that other repositories can build upon, while ensuring a baseline level of compatibility: the core attributes that constitute a flake.

Features

  • Split your flake.nix into focused units, each in their own file.

  • Take care of system.

  • Allow users of your library flake to easily integrate your generated flake outputs into their flake.

  • Reuse project logic written by others

Getting Started

If your project does not have a flake yet:

nix flake init -t github:hercules-ci/flake-parts

Migrate

Otherwise, add the input,

    flake-parts.url = "github:hercules-ci/flake-parts";

then slide mkFlake between your outputs function head and body,

  outputs = inputs@{ flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      flake = {
        # Put your original flake attributes here.
      };
      systems = [
        # systems for which you want to build the `perSystem` attributes
        "x86_64-linux"
        # ...
      ];
    };

Now you can add the remaining module attributes like in the the template.

Templates

See the template.

Examples

See the examples/ directory.

Projects using flake-parts

Options Reference

See flake.parts options

flake-parts's People

Contributors

arcuru avatar atry avatar bors[bot] avatar davhau avatar edrex avatar figsoda avatar hercules-ci[bot] avatar iogamaster avatar ldesgoui avatar matthewcroughan avatar mic92 avatar roberth avatar sempruijs avatar shlevy avatar srid avatar woile avatar zimbatm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flake-parts's Issues

Set a description of the template

Hello, I followed the instruction in README to clone the template.

Apparently, flake.nix must be a valid Nix file even in the template, so I think you have to set the description.

merge perSystem system argument with the rest

It's a small ergonomic thing but I think it would be best if perSystem would take one argument instead of two.

Current:

perSystem = system: { config, self', inputs', pkgs, ... }: {

Proposed change:

perSystem = { system, config, self', inputs', pkgs, ... }: {

What do you think?

flake-modules-core breaks nixos configurations

{
  description = "A flake with nixos systems";

  inputs = {
    flake-modules-core.url = "github:hercules-ci/flake-modules-core";
    flake-modules-core.inputs.nixpkgs.follows = "nixpkgs";
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };

  outputs = { self, flake-modules-core, nixpkgs, ... }:
    (flake-modules-core.lib.evalFlakeModule
      { inherit self; }
      ({ self, ... }: {
        systems = [ "x86_64-linux" "aarch64-darwin" ];
        flake = {
          nixosConfigurations.some-system = nixpkgs.lib.nixosSystem {
             system = "x86_64-linux";
             modules = [];
          };
          # The usual flake attributes can be defined here, including system-
          # agnostic ones like nixosModule and system-enumerating ones, although
          # those are more easily expressed in perSystem.

        };
      })
    ).config.flake;
}
$ nix build .#nixosConfigurations.some-system.config.system.toplevel
trace: Obsolete option `jobs' is used. It was renamed to `systemd.services'.
error: The option `passthru' is used but not defined.
(use '--show-trace' to show detailed location information)

Use mdbook for site

Should be feasible as the options generation is already using pandoc instead of docbook's own tooling. Wouldn't mind doing more ugly stuff either, if necessary.

Attempt to import home-manager module produces recursion.

Trying to import home-manager module for installation of nix-doom-emacs (imports = [ nix-doom-emacs.hmModule ];).

error: infinite recursion encountered

       at /nix/store/714kd9iay1f89hspfp62f6xhch67n733-source/lib/modules.nix:483:28:

          482|         builtins.addErrorContext (context name)
          483|           (args.${name} or config._module.args.${name})
             |                            ^
          484|       ) (lib.functionArgs f);
(use '--show-trace' to show detailed location information)

Old lib being evaluated

Hello 👋 first thanks for this awesome lib.

For some reason, for this reduced example, some old lib is being evaluated:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    flake-parts = {
      url = "github:hercules-ci/flake-parts";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = {
    self,
    nixpkgs,
    flake-parts,
  }:
    flake-parts.lib.mkFlake {inherit self;} {
      systems = ["x86_64-linux"];
      perSystem = {pkgs, ...}: {
        legacyPackages = pkgs;
      };
    };
}
$ nix eval github:viperML/flake-parts-bug#legacyPackages.x86_64-linux.lib.version
trace: lib.crossLists is deprecated, use lib.cartesianProductOfSets instead
trace: warning: literalExample is deprecated, use literalExpression instead, or use literalDocBook for a non-Nix description.
trace: warning: lib.mkFixStrictness has no effect and will be removed. It returns its argument unmodified, so you can just remove any calls.
trace: `lib.nixpkgsVersion` is deprecated, use `lib.version` instead!
trace: warning: lib.readPathsFromFile is deprecated, use a list instead
trace: Warning: `showVal` is deprecated and will be removed in the next release, please use `traceSeqN`
trace: lib.zip is deprecated, use lib.zipAttrsWith instead
"22.11pre-git"

$ nix eval github:nixos/nixpkgs/nixpkgs-unstable#legacyPackages.x86_64-linux.lib.version
"22.11pre-git"

I also found this behaviour when evaluating lib.nixosSystem

Feature/documentation request: local documentation generation

I've seen the wizardry you've used and now extracted into the flake.parts-website repository for generating single-page documentation from the in-code description/examples and would love to be able to adapt that technique to my own public flake modules. I plan to review that code soon, as well as whatever is used for home-manager's equivalent.

Incidentally this capability would also help me reason my way through my confusion around top-level vs perSystem options I posted here.

Flake check warnings

I don't specify any darwinModules or overlays, but still get these errors:

warning: unknown flake output 'darwinModules'
warning: flake output attribute 'overlay' is deprecated; use 'overlays.default' instead

What's funny is that the devShell output is not recognized, so some of flake-parts has already been ported to the .default of Nix 2.8

self' is not per system?

When I try to remove the rec, I get infinite recursion. Is self' not supposed to be a reference of the config per system?

diff --git a/flake.nix b/flake.nix
index 6bb90e1..1375701 100644
--- a/flake.nix
+++ b/flake.nix
@@ -14,13 +14,13 @@
   outputs = { self, flake-parts, ... }:
     flake-parts.lib.mkFlake { inherit self; } {
       systems = [ "x86_64-linux" ];
-      perSystem = { system, ... }: rec {
+      perSystem = { self', system, ... }: {
         legacyPackages = import ./. { inherit system; };
 
         # For garnix
-        checks = legacyPackages._flatten { };
+        checks = self'.legacyPackages._flatten { };
 
-        devShells.default = legacyPackages.devshell;
+        devShells.default = self'.legacyPackages.devshell;
       };
     };
 }

No great way to close over flake inputs

It would be great to be able to close over the inputs of the current flake in our exported flake modules, either by discovering and documenting a pattern or by adding some kind of scaffolding in flake-parts. This would allow us to e.g. leverage library functions from our inputs within modules or create opinionated layers over-top of other flakes.

At present, the best way to do this seems to be to force anyone who pulls in our module to take a direct dependency on our dependencies with something like inputs.blah or (throw "The flake does not have a 'blah' input. Please add it."). This is pretty fiddly / non-scalable as the ecosystem grows.

How do I apply another flake's overlays to pkgs?

I'm trying out flake-parts for our company's devShell, and it does look a lot tidier than the previous flake-utils based mess we had! But there's one thing I'm not sure about: We're using fenix to provide a pinned cargo/rustc in our devShell, which strongly recommends using its overlay to install the fenix attribute on pkgs. So: Is there a way to apply other overlays to the "final" perSystem pkgs?

I found the so-called easyOverlay attributes, but it looks like that puts the packages only onto the default overlay exported from the flake, not on the internal pkgs available to the flake itself. Am I missing something? Is this something that could be supported in a convenient way by flake-parts?

Auto-wiring

Modules can provide various levels of integration, where an integration is any definition that isn't of a function that it declares.
Sometimes, integrations are not desirable. Making integrations lib.mkDefault may help, but this may not always be sufficient. If it turns out that some flakes need to disable too many integrations explicitly, perhaps it makes sense to introduce a single global option that disables all integrations. All (reusable) modules should then adhere to that option.

The story of a flake would then be

  1. initialize a flake with flake-parts
  2. add some modules with integrations
  3. use the integrations
  4. add a module with undesirable integration
  5. configure that module to disable that integration (?)
  6. encounter another undesirable integration
  7. set autoWire = false
  8. write the missing integrations that they did need

Perhaps modules could list their integrations in another option, to help with (8), but all in all it's not a great experience. I would consider this idea to be a last resort; I hope we'll find better solutions.

Cannot access non-system output of flakeModule in submodule

To reproduce the issue:

$ git clone https://github.com/DavHau/drv-parts --branch problem
$ cd drv-parts
$ nix flake show ./examples/htop --override-input drv-parts ./.

error:

error: attribute 'modules' missing

       at /nix/store/ni13vsgnf6hv42gpnlsv42yvv73w43m0-source/examples/htop/htop.nix:6:47:

            5|   # select mkDerivation as a backend for this package
            6|   imports = builtins.trace inputs'.drv-parts [inputs'.drv-parts.modules.mkDerivation];
             |                                               ^
            7|

The problem is, that I want to access an output of my flakeModule drv-parts, but the inputs' variable only contains system prefixed outputs, like devShells and packages. Other outputs like nixosModules for example are missing.

Am I using this wrong? If not, could we also add non-system specific outputs to inputs'?

Can flake-parts solve cross-system evaluation with IFD?

Consider a Haskell project built with haskell.nix. We want flake outputs and hydra builds for Linux and Darwin. Flake outputs are fine, just use perSystem or the equivalent functionality in flake-utils. But Hydra presents a problem.

Hydra jobs are evaluated once for all systems, on a Linux machine. So if we have the hydraJobs just build all of the packages, we'll run into a problem with the IFD of haskell.nix: It will require a Darwin builder at evaluation time, which may not be available then and certainly will be slow. haskell.nix does allow you to specify an evalSystem for your project evaluation, but if we set the evalSystem unconditionally to Linux then local darwin users will not be able to evaluate the flake outputs.

My current approach to solving this is to define a function taking system and evalSystem, with the latter defaulting to the former, then call the function just setting system for each system's packages but call it setting each system but the Linux evalSystem when building hydraJobs.

Could flake-parts give us some general way to do this? Maybe some kind of general way to re-call self with an extra module, or alternatively have perSystem be callable twice somehow?

Unable to add package with unfree license to `packages` output

I have a custom package defined in my configuration repo for an ancient Epson printer driver with a partially-unfree license:

https://github.com/montchr/dotfield/blob/flake-parts-v3/packages/drivers/epson_201212w/default.nix

I'm adding this package to my packages output via perSystem.packages.epson_201212w.

Upon running nix flake check, however, evaluation fails because this package uses an unfree license.

Is there any way to provide this package as a flake output without causing checks to fail?

I could see the sense in flakes disallowing this entirely for the sake of respecting purity (i.e. ignoring my system configuration's nixpkgs.config.allowUnfree setting) and enforcing the safe default of disallowing redistribution of unfree packages. Like, if providing this package in flake outputs means that any user of my flake will automatically become a copyright infringer 🙃 I just want my printer to work on NixOS.

On the other hand, this package is essentially the same as a similar driver in Nixpkgs, though I don't think that the existing driver would support my printer. So, given that Nixpkgs does provide packages for unfree software, maybe it's not inherently wrong for my flake to do so also...?

lib.nixosSystem missing

lib.nixosSystem is missing from the lib avaialble in flake-parts modules. I'm aware that one can work around it by referencing inputs.nixpkgs.lib.nixosSystem but this isn't user friendly and requires deeper knowledge about internals.

I guess we could either change the lib used in flake-parts to globally to inputs.nixpkgs.lib, or fix the origin of the problem which is nixpkgs having two different libs.

Working with multiple nixpkgs and nixosConfigurations

What's the most idiomatic way to work with multiple nixpkgs in flake-parts?

When defining nixosConfigurations I often have to work with multiple nixpkgs. For example host a would use nixos-unstable while host b would use nixos-22.11. This is simple enough with inputs.<nixpkgs>.lib.nixosSystem, however it becomes annoying when trying to reference flake packages and nixosModules from inside nixos configurations. This is because these outputs use the flake's nixpkgs input, not the nixos system one.

Example package:

# flake-parts package definition
{
  perSystem = { pkgs, ... }: {
    packages.my-package = pkgs.hello;
  };
}

# nixos configuration
{ flakeSpecialArg, ... }:

{
  # we use my-package in the nixos configuration
  # the package is based on flake's nixpkgs, not the nixos system nixpkgs
  environment.systemPackages = [ flakeSpecialArg.packages.my-package ];
}

Example module:

# flake-parts module definition
{ moduleWithSystem, ... }:

{
  flake.nixosModules.my-module = moduleWithSystem ({ self' }: { ... }: {
    environment.systemPackages = [ self'.packages.my-package ];
  });
}

# nixos configuration
{ flakeSpecialArg, ... }:

{
  # we import my-module in the nixos configuration
  # my-module's packages are based on flake's nixpkgs, not the nixos system nixpkgs
  imports = [ flakeSpecialArg.nixosModule.my-module ];
}

All of this is of course expected, that's how flake outputs work. But how should I go about defining packages and modules so they can be parameterized by nixpkgs?

Some ideas and things I've tried:

  • Define nixos configurations in subflakes with overridden follows.nixpkgs. Conceptually the simplest, but annoying to work with as you have to update inputs for every single change you make.
  • A custom implementation of subflakes by recreating the flakes structure (a inputs -> outputs function with a new self instance where I can customize the inputs.nixpkgs). Works surprisingly well, but easy to get into infinite recursion errors.
  • It might be possible with hercules-ci-agent's variants module? In nixos configurations I could maybe get this to work with nixosSystem.specialArgs.packages = config.variants.nixos-unstable.packages. But I'm not sure how I could make this work with nixosModules moduleWithSystem without abusing specialArgs there as well. Ideally nixosModules shouldn't depend on specialArgs.
  • Give up and define versioned packages and nixosModules (e.g. packages.my-package-22-11, nixosModules.my-modules-22-11)

Option to generate flake attributes with cross-compilation enabled nixpkgs

Hello,

I've started playing with cross-compilation today, I tried to write an option similar to perSystem whose value would be called with each possible pair of localSystem and crossSystem, the goal would be to be able to write something like this:

{
  perCrossSystem = { pkgs, system, crossSystem, ... }: {
    packages."x/${crossSystem}/hello" = pkgs.hello;
  };
}

And get something like this:

{
  perSystem = { system, ... }: {
    packages."x/aarch64-linux/hello" = (import nixpkgs { inherit system; crossSystem = "aarch64-linux"; }).hello;
    packages."x/riscv64-linux/hello" = (import nixpkgs { inherit system; crossSystem = "riscv64-linux"; }).hello;
    packages."x/x86_64-linux/hello" = (import nixpkgs { inherit system; crossSystem = "x86_64-linux"; }).hello;
  };
}

I have some basic knowledge of developing NixOS modules but I had a very hard time understanding how perSystem works, could you throw me a few pointers?
What I've tried so far was just defining an option of type raw and using it in something like config.perSystem = { system, ... }: lib.mkMerge (map (crossSystem: config.perCrossSystem { pkgs = import nixpkgs { inherit system crossSystem; }; }) config.systems);, but that recurses infinitely.

Side note, functionTo in lib.nix doesn't seem to be used anymore.

Thanks for this library, it's a pleasure to work with.

Idiomatic way to provide a "library" of Nix functions

We are using the module system options to expose functions for other modules to use.

For example,

{ self, ... }:
{
  options = {
    mkCheck = lib.mkOption {
      type = lib.types.functionTo lib.types.unspecified;
      default = { package, ... }: 
        abort "TODO: return a derivation that runs the tests for $package";
    };
  };
}

Then we use the mkCheck "library" function from other flake-module.nix modules (there are >10 of them, hence the library function) as:

{ self, ... }: {
  perSystem = { config, ... }: {
    checks.foo = config.mkCheck { ... };
  };
}

Is this the recommended way to use the module system to achieve this?

Tests for flake modules

Has there been any work/discussion regarding tests for flake modules? It would be nice to have a community defined flow for how to create tests for flake modules. Similar like we have tests for nixos modules and home-manager modules.

I think a testing framework or similar for flake-parts could potentially increase the best practices.

Things that could be nice to test:

  • Validate that the generated flake is correct/evaluates.
  • Test generated flake attributes to see if your output is what you expected.
  • Inspect/evaluate attributes to see that what they produced were the correct thing.

What do you think?

How to use rosetta on M1?

What's the most idiomatic way to configure flake-parts so that the pkgs of perSystem (and other relevant places) uses x86_64-darwin if on aarch64-darwin?

Currently I pass --option system x86_64-darwin to nix commands; but can this obviated when using flake-parts?

Converting vanilla flake to `flake-parts` by just moving to `flake` option fails with "systems used but not defined"

I wanted to convert my main flake to flake parts to get a feeling for it, as from all the different abstractions I have seen so far, it seems to be the most sensible approach.

Though the approach as drafted in the wiki by just wrapping the old vanilla stuff in flake-parts.lib.mkFlake {inherit self;} {flake = { … }; }; fails with an error when trying to build anything:

$ nix develop
warning: Git tree '/home/nmelzer/Projects/nixos-config' is dirty
error: The option `systems' is used but not defined.
(use '--show-trace' to show detailed location information)
$

Making the second argument {systems = []; flake = {…}; } instead solves the problem.

Is this a problem in the documentation or the implementation?

`perSystem` seemingly breaks with IFD

I essentially have perSystem.packages = import drv.
This doesn't work, and something tries to evaluate what packages is for all systems, even though it can only be evaluated for the current system.

Get rid of all the default empty outputs

By default mkFlake creates tons of outputs that most of the times won't actually be used by the flake. Let's say you make a flake that has a package output and a devshell, you don't need it to also have formatter, legacyPackages, nixosConfigurations, darwinModules, nixosModules and more. This makes the output of nix flake show really hard to work with and even confusing as it shows many outputs that don't have any actual output.

[kranzes@pongo ~/devel/website]$ (master) nix flake show
warning: Git tree '/home/kranzes/devel/website' is dirty
git+file:///home/kranzes/devel/website
├───apps
│   └───x86_64-linux
├───checks
│   └───x86_64-linux
├───darwinModules: unknown
├───devShells
│   └───x86_64-linux
├───formatter
├───legacyPackages
│   └───x86_64-linux omitted (use '--legacy' to show)
├───nixosConfigurations
├───nixosModules
├───overlays
└───packages
    └───x86_64-linux

Feature/documentation request: testing story

Preface: I am a fairly casual nixpkgs contributor thus far and have not submitted any NixOS modules or tests upstream, and in general I am woefully unfamiliar with my opportunities and available techniques to test Nix code in any context. I know there's some prior art for me to review in the form of the NixOS testing support, and that's about all I know today.

As mentioned elsewhere, I'm working on my first non-trivial flake intended for public consumption, and it's defined in terms of a flake-parts module. I'd like to keep a few common permutations around in-repo and evaluate them with/against my current flakeModule content to prove that they still work as intended and check some simple results. Is this something that I can do today? Would such an approach be best based around lib.evalFlakeModule?

Early motivating examples of "unit tests" I'd like to incorporate are:

  • If I set a particular option defined by my flakeModule, does a particular leaf node of config hold an expected value?
  • If I set a particular option defined by my flakeModule, does the consuming flake now have an output at a particular path?

Later on it would be cool to also check things like:

  • Is such-and-such binary in PATH in the generated devShell?
  • Does a particular shell command produce expected output when run in the context of the devShell?

As with #77, if some early guidance is available I'd be happy to try to implement this myself. I am not always able to deeply comprehend some of the more sophisticated code in the Nix ecosystem without assistance - my functional-programming background begins and ends with Elixir.

Dev-only dependencies

Avoid loading dev-only modules by deferring those; when checks etc are accessed.

  • devImports : deferredModule
  • override flake.checks and flake.devShells in the main eval; choice of attrs should be generalized
  • what about apps?
  • do this at the perSystem level too?

This will work best with

The option `self` does not exist - when attempting to add a new top-level flake output and leveraging it

Hi!

I'm trying to make a top-level flake output variable allowedUnfreePackages, which I intend to reference through the self parameter made/created for me by flake-parts.

I already leverage the self parameter in my module system (see previous commits of below branch), so that works fine.
I do not understand the error message though, as self obviously exists. Why does it think it's an option?

(I have tried with assigning a inputs.nixpkgs.lib.option to the top-level flake output variable instead, but I got nowhere with that avenue of attack).

My attempt can be found in the HEAD commit of this branch: https://git.sr.ht/~x10an14/nix-configs/log/global-unfree-predicate

Allow for more more than just packages in `perSystem.packages`

https://github.com/hercules-ci/flake-parts/blob/main/modules/packages.nix#L31 there the type of perSystem.packages is restricted to lazyAttrsOf package, which mostly is fine, but just in nixpkgs we have examples which won't fit there, namely generators or writeText. In my flake I define custom helpers of both the attrsetOf (attrsOf package) and attrsetOf function nature. I propose a new type:

let
  self = 
    oneOf
      [ (lazyAttrsOf self)
        package
        (functionTo self)
      ];
in
  lazyAttrsOf self // { description = "Attrs of functions or packges, with arbitrary depth."; }

Easier ad hoc perSystem definition

Currently if I want to add a perSystem flake attribute, I have to do a bunch of option defintions and config setting. Would be good if I could just do perSystem = { system, ... }: { foo = ... } and get flake.foo.x86_64-linux.

Exposing a flakeModule that depends on other flake modules without defining in the same file

What is the best practice to expose a flakeModule that depends on other flake modules?

I have something like this:
flake.nix:

...
  outputs = inputs:
    inputs.flake-parts.lib.mkFlake {inherit inputs;} {
      systems = ["x86_64-linux" "x86_64-darwin" "aarch64-darwin"];
      imports = [./modules.nix];
    };
...

modules.nix:

{inputs, ...}:

{
  imports = [inputs.flake-parts.flakeModules.flakeModules];
  flake.flakeModules.default = import ./my-module.nix;
}

my-module.nix:

{inputs, ...}: {
  imports = [input.flake-dep1.flakeModule input.flake-dep2.flakeModule];
}

I currently have 4 solutions, none of them feel optimal.

  1. Define the module in the same file, so I can access the outer scope.
  2. Pass a top-level argument to the module (then the module can't be imported directly via imports, but one needs to do (import ./modules.nix { inherit inputs; }) for example)
  3. Have a wrapper for the module file inside the modules.nix, { imports = [...inputs, ./my-module.nix]; }
  4. Split out the module as a module within the current flake that then defines the module.

I guess there are no _module.args.inputs or something that could be utilized?

What is the best practices for this kind of thing?

arbitrary keys with perSystem?

I'm converting a project using flake-utils, which has outputs.${system}.lib (lib needs system for.. reasons). flake-utils.lib.eachDefaultSystem is open to whatever keys you return, but flake-parts.lib.mkFlake's perSystem attr doesn't accept attrs that don't correspond to a module's option definition. Talking through this myself, I wonder if I'm supposed to create a module that defines a lib option?

Add `mkSimpleFlake`?

In https://github.com/srid/haskell-template I'm using flake-parts in place of flake-utils. The minimal code I came up with in order to replace the latter's eachDefaultSystem is as follows:

  outputs = { self, nixpkgs, flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit self; } {
      systems = nixpkgs.lib.systems.flakeExposed;
      perSystem = { self', inputs', pkgs, system, ... }:
        ..

https://github.com/srid/haskell-template/blob/3fc6858830ecee3d2fe1dfe9a8bfa2047cf561ac/flake.nix#L14-L19

Since I imagine most non-monorepos using flake-parts to repeat the above verbatim, would it be worthwhile to expose a function that obviates both systems and perSystem? i.e.

  outputs = { self, flake-parts, ... }:
    flake-parts.lib.mkSimpleFlake { inherit self; } ({ self', inputs', pkgs, system, ... }: 
      ...
    );

ie., mkSimpleFlake is like mkFlake but uses all systems built by Hydra, as well as assumes the user specifies a single-module flake.

Receiving self in perSystem to define cross compiled targets?

Hello,

Fairly new Nix user here, and I am trying to setup some repository with flake-parts and some cross-compiled targets. That is I am trying to write a flake module like:

{
  perSystem = {pkgs, self, self', ...}:
    let
      somePackage = mkSomePackage {
        inherit pkgs;
        someDependency = self'.packages.some_dependency;
      };
      mkDockerImage = { pkgs, name, somePackage, fromImage }: 
        pkgs.dockerTools.buildLayeredImage {
          inherit name;
          tag = "latest";
          contents = [ pkgs.tini somePackage ];
          fromImage = fromImage;
        };
    in {
      packages.some_package = somePackage;
      packages.some_package_docker = mkDockerImage {
        inherit pkgs;
        inherit somePackage;
        name = "some-name";
        fromImage = self'.packages.docker_alpine;
      };
      packages.some_package_docker_rpi = mkDockerImage {
        name = "armv6l/some-name";
        pkgs = pkgs.pkgsCross.raspberryPi;
        fromImage = self.packages."armv6l-linux".docker_alpine;
        somePackage = mkSomePackage {
          pkgs = pkgs.pkgsCross.raspberryPi;
          someDependency = self.packages."armv6l-linux".some_dependency;
        };
      };
    };
}

However this doesn't work because self is not passed to flake modules, would doing so make sense?

The story for cross-compilation in flakes isn't very clear right now, and I am happy duplicating some targets under ${system} for convenience in the rare cases where I need to cross build something because I miss the build infrastructure for the host system.

Provide explanation for usage of `pkgs.nixos` instead of `lib.nixosSystem`

I hadn't encountered pkgs.nixos before seeing it in one of the examples here. I'm more accustomed to seeing lib.nixosSystem everywhere else.

What's the reasoning for choosing pkgs.nixos over lib.nixosSystem in the context of this project? Is there any reason to avoid the latter when creating a system config based on this library?

I suspect I am not alone in this confusion. Could you add an explanation/expansion to the example please?

FWIW I had a lot of difficulty tracking down its source. search.nixos.org doesn't seem to find it, and pkgs.nixos is pretty hard to search for in general without many false positives. I finally managed to track it down in all-packages.nix, where it's defined. This is a pretty arcane source, especially since the file is 1.1MB -- too big for GitHub to display, and AFAIK not possible to link to directly...

https://raw.githubusercontent.com/NixOS/nixpkgs/nixos-22.05/pkgs/top-level/all-packages.nix

Add packages' `passthru.tests` to `checks`

Unless I'm missing something, it appears that packages' passthru.tests don't work with flakes, neither by putting them in perSystem.checks, nor in perSystem.packages.

In any case, it would be a great feature if flake-parts could accumulate all passthru.tests attributes for all perSystem.packages and automatically add them to perSystem.checks!

Enable discussions on repo?

It seems like a GH Discussions instance on flake-parts could be a good place to share ideas and collaboratively solve design problems. Can haz discussions tab? @roberth

Specifically, I came today with thoughts about how it might be possible to utilize large parts of the NixOS module library in a cross-platform way, by providing "polyfills" (injected alternative implementations) for some key modules and utility functions (such as the systemd module for managing service instances).

Option diffing

Add a function that reports which option values change how when adding a definition. This may have to assume that self is defined by mkFlake only.

Cross compilation

Something like #82 but a bit more involved.

Interface ideas

perSystem = { getHostSystem, getBuildSystem, ... }: to set either system.
top@{ getCrossSystem, ... }:, getCrossSystem { /* both host and build */ /* -platform or -system? :/ */ }

Do we set the perSystem to host? I think so, because the goal is to declare outputs, not program a build process. Otherwise we get something like crossSystem which doesn't have a simple, useful definition for reading.

getHostSystem memoization may be tricky. (Use tries??)

Require al host systems to be declared? Required for a name suffixing feature.

Feature request: NixOS-style assertions support

I'd like to offer consumers of my flake modules feedback if they set options to semantically incorrect values, or use mutually-exclusive options simultaneously.

If some guidance is available I'd be happy to try to implement this myself.

The type of `flake.apps.<name>.<name>.program` makes it impossible to refer to a single-file derivation output

This type will match strings that are store paths as types.package, it therefore tries to run getExe on it, which fails.

It feels like it should be possible to fix this but keep the wanted behavior by replacing lib.types.package with a type that only checks isDerivation and not isStorePath.

https://github.com/NixOS/nixpkgs/blob/f1dd761ae8e02f8182832a73bee1c9d508c308bd/lib/types.nix#L380
https://github.com/NixOS/nixpkgs/blob/f1dd761ae8e02f8182832a73bee1c9d508c308bd/lib/attrsets.nix#L427
https://github.com/NixOS/nixpkgs/blob/f1dd761ae8e02f8182832a73bee1c9d508c308bd/lib/strings.nix#L740-L746

Don't override `outputs.herculesCI.onPush` if already provided

{
  outputs = inputs@{ self, flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; }
      {
        imports = [
          inputs.hercules-ci-effects.flakeModule
        ];

        herculesCI =
          { ref
          , branch
          , tag
          , rev
          , shortRev
          , primaryRepo
          , herculesCI
          # flake-parts provides more inputs:
          , ...
          }: {
            onPush = { };
          };
      };
}

Expected: empty herculesCI.onPush
Observed: herculesCI.onPush contains default with contents of checks, &c

P.S. sorry if the wrong repo

EDIT:

onPush = lib.mkForce { } seems to help; I'm not sure if this is desirable 🤔

No access to flake inputs within a perSystem module

Similar to #81.

Trying to add inputs to the perSystem args, triggers this error:

error: `inputs` (without `'`) is not a `perSystem` module argument, but a
       module argument of the top level config.

       The following is an example usage of `inputs`. Note that its binding
       is in the `top` parameter list, which is declared by the top level module
       rather than the `perSystem` module.

         top@{ config, lib, inputs, ... }: {
           perSystem = { config, inputs', ... }: {
             # in scope here:
             #  - inputs
             #  - inputs'
             #  - config (of perSystem)
             #  - top.config (note the `top@` pattern)
           };
         }

The statements about the scope only hold true as long as all code is defined inside a single flake.nix file.
The lexical scope breaks as soon as the code is split into modules.

For example given the following flake.nix:

{
  inputs = {
    flake-parts.url = "github:hercules-ci/flake-parts";
    poetry2nix.url = "poetry2nix";
  };

  outputs = inputs@{ flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      systems = [
        "x86_64-linux"
      ];
      perSystem = { config, pkgs, ... }: {
        imports = [./my-package.nix];
      };
    };
}

and my-package.nix:

# flake-parts module for the tesh package
{config, pkgs, inputs, self, ...}: let
  poetry2nix = import inputs.poetry2nix {inherit pkgs;};
in {
  packages.tesh = poetry2nix.mkPythonPplication {
    projectDir = self;
  };
}

This breaks because inputs is not allowed as a function argument. This means it is not possible to access some inputs lib or similar things inside a perSystem module.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.