TL;DR: I’ve been brooding about tests and automation of PRs, and I’m wondering whether we can improve the overall nixpkgs & NixOS development by splitting the nixpkgs repository into two:
-
nixpkgs
: Only standard library, packages and unit tests. (Subfolderspkgs
,lib
.) -
nixos
: Hasnixpkgs
as a dependency. Adds modules (services, config options, …), integration tests, boot loader setups, and so on. (Subfoldernixos
.)
What problem are we solving here?
The main goal here is to make more automation of boring tasks possible.
The largest portion of PRs to nixpkgs are semi-automatically created by bots or automation tools that contributors run locally. They often only bump a minor version of some package. These PRs still need manual attention to merge, though. This is annoying for package maintainers: I don’t want to do nixpkgs-review
on any version bump just to find that the package still works. There should be a simple unit test that does the job I would have done, and if that test succeeds, the update should be merged automatically.
Why is this not done already? My impression is that we simply don’t have such a unit test suite for most packages. We do have nixos/tests/*
, and often for a package foo
we well set foo.passthru.tests = nixosTests.foo;
. But this fires up a whole VM booting and running a complete NixOS, just to test this one package. It probably would be too much CI burden to run such tests for each and every package. Consequently, the nixpkgs-unstable
channel advances much quicker than nixos-unstable
, because doesn’t run all the NixOS tests.
nixos/tests/*
are actually integration tests, not unit tests. With any run of such a test I’m not only testing my particular package, I’m testing a whole setup of a running NixOS machine, modules, possibly even X. Note also that we underrepresent tests in non-NixOS setups that way.
But don’t we already sort of split nixpkgs & nixos?
Sort of. Still, nixpkgs uses tests from nixos. The documentation overlaps in many places (which can also be seen as a good thing).
So what’s the proposal?
- Write simple, low-resource unit tests for packages. Maybe a simple
runCommand "foo" {} "${foo}/bin/foo --version"
is already enough to ensure that the version can be bumped for many executables. For bigger applications, maybe a pool of shared machines (some with X servers) and lightweight systemd containers could be used. - Separate documentation more clearly into nixpkgs parts (e.g. language frameworks, how to contribute a package, …) and NixOS parts (e.g. options, modules, services, booting, system installation).
- Split
nixpkgs
into 2 repositories,nixpkgs
andnixos
. The latter pins a version of the former. -
nixpkgs
can advance whenever only packages and unit tests evaluate and build. Many PRs like minor version bumps should just go through automatically, and simply be merged (or be added to the merge train, if the bors idea takes off) without manual intervention. -
nixos
can advance whenever the integration tests evaluate and build. - The pinned
nixpkgs
version innixos
will advance whenever possible, but this does not block the advancement ofnixpkgs
itself.
Advantages
- The evaluation times are split. The CI doesn’t need to evaluate all of (what is presently) nixpkgs, but only the packages. I’m not sure how big the advantage is, but I’m hoping that it is considerable.
- The complete test pipeline for
nixpkgs
can run much faster: No VMs are started and the tests should be smaller (unit tests instead of integration tests).
Problems
What if nixpkgs
advances in a way that nixos
cannot deal with? E.g. the unit tests didn’t catch some breaking update, but it is noticed in nixos
(e.g. through an integration test). In this case, nixos
has the role of a downstream repo that needs the upstream repo to be fixed. Until this is done, the nixpkgs
pinned version in nixos
cannot advance before that.
How to apply security updates to NixOS? The previous point implies that sometimes, we cannot advance the pinned nixpkgs
version in nixos
even though we should, e.g. because of an urgent security update to a package. That’s a problem of course, though it exists today as well. The solution is probably the same as today, i.e. nixos-small and LTS releases.
What about massive rebuilds? This is still an issue. If a core library updates, a lot of rebuilds are triggered. That doesn’t change much, because the bulk of the load is packages that need to be compiled again. Still, tests complete faster than before, so that process might be a tad simpler.
Are you serious about all this?
I’m not completely sold on this proposal. It’s a massive change where a lot can go wrong, and it will probably not happen. There may be many reasons that I didn’t think of, or that I don’t know about, that this is a Bad Idea. I’m actually hoping to learn why it’s a bad idea/currently not possible/in principle a good idea, but [insert argument here]. Maybe it’s even an interesting viewpoint for much more seasoned and invested NixOS contributors to give their insights on how automatisation should be done. So see all this as a starting point for a discussion.
There are discussions about having a green pipeline all the time, and I welcome them. It’s also clear that this is difficult. Maybe a split would make that simpler, because then there are two independent pipelines that can advance individually. Even if the overall goal to split the repo is too drastic, we might learn something in the discussion that makes this goal more reachable. For example, the basic philosophy could be kept, and only applied to decisions of when to merge automatically.