Add an example of dogfooding (fix #121)#197
Conversation
| partitionedAttrs.devShells = "dogfood"; | ||
| partitionedAttrs.packages = "dogfood"; |
There was a problem hiding this comment.
Having to list these is not great UX.
I think I'd prefer to add a parameter to mkFlake.
I think we could have a modules specialArg to make that nice:
mkFlake {
inherit inputs;
publicModules.foo = ./foo.nix;
}
({ modules, ... }: {
imports = [
modules.self.foo # based on the publicModules parameter
modules.git-hooks-nix.default # just a mapAttrs of inputs; lazy and cheap
];
})It's a bit more custom, but it avoids the complexity of having partitions, probably improving error messages as well, and slightly less boilerplate.
It does put the module in a different scope, but I think this can be worked around, with techniques similar to withSystem, and it'd look like:
publicModules = local@{ config, withSystem, ... }: { # not defining a module; just a function
/** A module that adds a check using a package built in the local way,
with no interference except `follows` */
foo = userFlake@{ self, ... }: {
perSystem = { system, pkgs, ... }:
withSystem system (localPerSystem@{ ... }: {
checks.foo = pkgs.runCommand "check-foo" {
nativeBuildInputs = [ localPerSystem.config.packages.foo ];
} "foo ${userFlake.self} && touch $out";
});
};
};However, actually needing access to the local flake seems quite rare for flake-parts modules, so we might not even need it for now.
What do you think?
There was a problem hiding this comment.
I think a flake module that defines a flake module is a good abstract, because it distinguishes the module author's inputs from the module user's inputs. I like the idea to make publicModules a partition of preparatory step by default before the "main" partition. This design has precedent in other languages, e.g. sbt.
There was a problem hiding this comment.
The reason why we cannot put bootstrap modules to flakeModules is that flakeModules is a submodule of the mkFlake's top level module, and the mkFlake's top level module cannot depend on its own submodule.
Can we make mkFlake a submodule instead of a function, then we can create a "meta-module" as the new top-level module to set up special args for the mkFlake submodule. Eventually the user could simply use nixpkgs's evalModules to evaluate the meta-module to build the flake:
(lib.evalModules {
modules = [
inputs.flake-parts.modules.metaModule
{
inherit inputs;
publicModules.myPublicModule = {};
mkFlake = {modules, flake-parts-lib, lib, inputs, ...}: {
imports = [ modules.myPublicModule ];
perSystem = { ... };
};
}
];
}).config.mkFlake.flake
This PR is a rework of #156. It avoids infinite loops by using partitions.