I want to provide a thoroughly documented trail up the Nix flakes learning curve.
One of the big problems I have with learning Nix in general is that—in the context of its huge complexity—typos, outdated information, assumptions made or shortcuts taken by the author, often lead to waste of vast amounts of precious time on the part of the reader.
I want to start with just about the most trivial flake that does something, and take small steps which introduce some aspect or feature, and build up to something of arbitrary complexity.
Crucially, each of these steps should consist of self-contained, complete, working code, documented with examples of usage which are automatically tested for correctness.
This presents me with some difficulties:
IIANM, a flake is a version-controlled filesystem-tree with a
flake.nixat its root. Two different steps in my progression of examples must therefore be distinct version-controlled filesystem-trees with a
flake.nixat their roots. The obvious way of storing these seems to be as different commits in a Git repo. Thus my final product will be the whole history (cleaned up, with one didactic step per commit) of a Git repo. But how on earth do you version-control this product? IOW, how do you version control the evolution of the entire history stored within a Git repo (that is, a sequence (nay, graph) of trees), as opposed version controlling the evolution of a single filesystem tree?
Furthermore, introducing changes to this is a major PITA, as any change in one of the earlier steps tends to require a lot of rebasing to clean up the whole set. I can imagine that this might become intractable as the number of steps grows.
I’ve tried to use shellspec to write the tests. I’m not at all familiar with it, so maybe I simply haven’t spotted some obvious feature that it provides for dealing with this: Consider something like
nix develop; I would like to write some tests which verify features of the environment inside the shell created by
nix develop, but
shellspecjust hangs there until the shell exits.
The source of the BDD-style
shellspectests is fairly legible, but it would be better if these could be gathered together in a single, pretty,
mdbookbook (or similar). But given that the separate steps (and their corresponding documenting tests) are scattered across different commits in the repo, this is going to be somewhat fiddly.
My attempt at getting (the first two aspects of) this going can be found here. So far it only contains the outline of three steps:
- A single-system, single-package flake.
- Generalize it to multiple systems.
- Introduce a
To run the tests of any single step manually:
nix run github:jacg/flakes-learning-curve/shellspec
shellspec is not available in
nixpkgs, so I’ve put it in a flake in a orphan branch of the same repo. I’ll try to submit
nixpkgs Any Moment Now.)
There is a prototype GitHub action which runs the whole lot. Very pedestrian at the moment: it manually checks out each of the branches corresponding to the steps in the sequence, in turn, and re-runs the tests.
Can you suggest a better way of organizing and presenting theses steps, while maintaining the requirement of automatically verifying the correctness of the samples?
This structure seems very difficult to work with, so I don’t want to invest too much time and effort into it, if a more manageable approach can be found.