Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds a new `incremental` utility for Haskell CI that supports incremental builds based on the approach outlined in this blog post: https://harry.garrood.me/blog/easy-incremental-haskell-ci-builds-with-ghc-9.4/ The basic idea is that instead of Nix doing a full build for a package, we split every build into two builds: - A full build at an older point in time e.g. a daily or weekly time boundary - An incremental build relative to the last full build This incremental build reuses the build products left over from the most recent full build. In order to do this, though, we need a way to "snap" a package's `git` source input to an earlier point in time (e.g. a daily boundary or weekly boundary). This would allow multiple incremental builds to share the same full rebuild if they snap to the same time boundary. The approach I went with to make that possible was to extend Nix's `builtins.fetchGit` to support a new `date` argument and you can find the corresponding PR for that here: NixOS/nix#7362 That is why the `incremental` utility added here requires a sufficiently new version of Nix (one that would incorporate that change, presuming it is merged). This also requires GHC 9.4 or newer in order to pick up a fix to GHC's change detection logic, as described in more detail in the above blog post. However, if you satisfy those requirements then this works exactly the way you'd expect: all of the incremental builds only have to build the diff since the last time boundary. Moreover, if CI caches the full build then developers can also run `nix build` locally and only have to build the diff, too. --- Lower required version … so that it works against the upstream PR I'll change the required version to an official release if the PR is merged. --- s/pkgs/pkg/g … as caught by @cdepillabout Co-authored-by: Dennis Gosnell <[email protected]> --- Skip the use of `tar` We can store the `dist` directory decompressed, which speeds up the dist export/import This potentially requires more disk space *but* by storing the files unpacked it may actually improve disk utilization in some cases if `auto-optimise-store` is enabled by permitting deduplication of `dist` files. --- Add an `installDist` phase … which is disabled by default The motivation for this is to bring the behavior of `enableSeparateDistOutput` more in line with the other options where it doesn't change *whether* or not something is exported, but rather *where* it is exported. Now `installDist` controls whether or not the `dist` directory is exported. Based on this discussion: https://github.com/NixOS/nixpkgs/pull/203499/files#r1034150076 --- Document `interval` argument … as suggested by @cdepillabout --- s/for use for/for use with/ … based on feedback from @MaxGabriel --- Move `installDistPhase` to `postPhases` There are two reasons for doing this: - We can get rid of the hack to remove the dist output from the outputs - We can ensure that any changes that happen in the install phase are correctly reflected in the `dist` export --- Disable dylib workaround for incremental build --- Improve correctness of `incremental` function Typically we don't want to just roll back the source code that is the input for the Haskell package because the dependencies for the package may have changed In other words, if you roll back the source code for the top-level package without also rolling back the Nix-supplied dependencies for that build then you run the risk of an unexpected build failure (due to an older version of the Haskell package being built against a newer version of the Nix-supplied dependencies). What you actually want to do is to roll back the entire repository (i.e. the Haskell source code and the supporting Nix code) to ensure that the Haskell source code and Nix code stay in sync. This more generalized rollback complicates the UX for the `incremental` function. I did my best to try to streamline the UX so that the user just needs to specify how to locate the matching (older) package after a rollback. --- Make date relative to revision (if possible) This way if you attempt to incrementally build an older revision then the full rebuild will be relative to the older revision instead of being relative to the present. --- Add `extraFetchGitArgs` option This in particular comes in handy if you want to specify `ref = "main";` to ensure that the older build comes from the `main` branch of your repository.
- Loading branch information