I’m using flakes for building various software packages authored by different people in various languages in CI. My flake.lock files are checked in and my build’s are reproducible. I’m really happy with what I have so far.
One of the remaining pain points is that a lot of projects depend on the same outside inputs (like nixpkgs), but if those inputs are independently updated using
nix flake update --recreate-lock-file
they end up depending on different versions of the same thing which is inefficient in various ways*.
My idea to solve this would be creating an aggregate flake which does nothing but aggregate some external dependencies centrally (mostly nixpkgs, but potentially also some others) and re-export them in a specific version determined by its own lock file.
Instead of depending on these external dependencies directly my other projects could then depend on the versions provided by the aggregate flake, which gives my more control over the update cycle. I could first update the aggregate and then my other projects individually, to get the same version everywhere.
I wanted to try this but I’m having a hard time figuring out what the aggregator flake would have to look like.
Can anyone give me some input on how that aggregate flake idea could be implemented in a flake?
(* My issue is not only with downloading and storing slightly different versions of the same software. I also wrote a bot that automatically creates/updates pull requests for outdated flake inputs. Right now changes to nixpkgs lead to a lot of noise in those pull requests, which I would like to concentrate in the aggregate flake’s repo by updating it at a lower frequency, like weekly or every two weeks so that in downstream projects those updates only show up with that frequency.)
I think both of those solutions could solve some of my issues, but they are not expressive enough to give me what I actually want in terms of workflow and expressiveness directly inside the flake file.
I want hm to pick my specific version of nixpkgs, and when I update my dependencies I want the latest one that hm picked in my lock file.
This is more powerful because it works for direct dependencies, so it does not involve re-targeting some pre-existing dependency later on.
hm does not make sense as an example for why I would want this, for that I would replace hm with the aggregate I mentioned in my original post. It still shows nicely what I think is not possible with those solutions.
and then refering to it inside the outputs block as hm.inputs.nixpkgs.
The downside of that being that it turns into an transitive dependency even though I would prefer to still have it listed as a direct dependency in the inputs. I just wanted nix to look at another dependency for resolving which specific version to include in the lockfile and have the flake file be as explicit as possible about what I actually depend on and in which version.
It seems like you want a parent flake to use/inherit an input as defined by a child flake? Can you have the child flake expose the input as an output, and then just explicitly reference that output? Something like this: (untested, just an idea)
I do something like that (closed repository, sorry). I have a syntaxdot flake which has a nixpkgs and utils inputs. Then I use these inputs in another flake syntaxdot-models (the rec might be superfluous?):
(I don’t think this was documented anywhere, I just got here by trial and error, reading the error messages, and reading Nix source code. These stringly-typed inputs are not really helpful and quite ugly.)
Thank’s everyone. from me as well. With @danieldk’s suggestion I can express exactly what I wanted in the downstream project (The rec in his reply is indeed superfluous.):
And the upstream aggregate (named flock-of-flakes and only a local path for now) looks like this:
{
description = "A collection of flakes we depend on and want to use the same version of";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
utils.url = "github:numtide/flake-utils";
};
outputs = inputs : {};
}
At least thats the best way that I could figure out to make a collection of flakes. Note that this flake itself can’t be built because it lacks a defaultPackage, but it doesn’t have to be a buildable thing for this use case. You can run nix flake check and nix flake update on it and it produces a working a flake.lock file to check in.
If we look at the output of the nix flake list-inputs command we can see that the .follows are working as expected.