Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to hs-nix-infra for the Nix setup #1778

Merged
merged 39 commits into from
Dec 4, 2023
Merged

Conversation

enobayram
Copy link
Contributor

@enobayram enobayram commented Nov 9, 2023

This PR does the following:

Unify the GHC derivation used across Kadena projects

Instead of depending on nixpkgs and haskellNix directly, this flake now depends on our new hs-nix-infra flake and uses the nixpkgs and haskellNix revisions provided by it. The hash of the nixpkgs and haskellNix flakes used for defining the haskell.nix project determines the hash of the GHC package that gets used to compile the Haskell modules.

When multiple projects depend on nixpkgs and haskellNix independently, it's very hard (and not really well supported by nix CLI) to make sure that they don't deviate from each others' nixpkgs and haskellNix pins arbitrarily. I.e. updating two projects' flake.lock files at slightly different times is likely to cause one of the pins to be on a different revision, even though the difference doesn't matter functionally.

These unnecessarily different GHC packages put a lot of pressure on our CI infrastructure, taking hours to build functionally equivalent GHC packages and bloating the cache (with binaries from all the architectures we build and cache for). That also bloats the /nix/store of any chainweb user that wants to nix build an uncached chainweb version.

The new workflow for updating Haskell-Nix toolchain

After this PR, the new workflow for managing our Haskell dependencies used by Nix will involve the following steps:

  • If we need to update our hackage pin so that we can build with newly released Haskell packages, we can just nix flake lock --update-input hackage similar to how we've been doing so far, because this PR keeps declaring hackage as an input to the chainweb-node flake. This means the hackage flake pin can deviate between multiple projects, but that's relatively OK, since the hackage pin doesn't influence the GHC package. The only bloat caused by such deviation is the need to download the hackage repository, which is inconvenient, but worthwhile in exchange for the convenience of easily bumping the hackage pin.
  • If we need to use a new GHC version provided by a newer nixpkgs version or if we need to bump our haskellNix pin for any reason, then unlike the status quo, we need to follow a two-step process:
    • If hs-nix-infra has a newer version, bump it in this repo and see if that fixes the build.
    • If that latest hs-nix-infra version isn't good enough, then open a PR to hs-nix-infra to bump nixpkgs and haskellNix. The PR would preferably bump both of them to the latest version.

Hopefully, this new workflow will reduce the number of nixpkgs + haskellNix versions we depend on across our Haskell projects.

Add a recursive alternative to the default package

As part of the CI automation for this repo, we're building and caching the Nix binaries for chainweb, which makes it convenient for any user to nix build chainweb from any commit/branch since all the dependencies will come from our binary cache. However, even without building anything locally, evaluating the default package of this flake takes a significant amount of time and involves downloading ~2 GB of Nix dependencies. This is due to the complexity of what haskellNix does for us at Nix evaluation time.

This PR introduces a recursive package to this flake's output, which uses recursive-nix to push the Nix evaluation of the default package into the build of a derivation. This means, any user that tries to nix build .#recursive will fetch the chainweb binary from our cache without having to perform any complex Nix evaluation locally or downloading the Nix dependencies of any such evaluation as long as the recursive derivation they're building is already in our binary cache. If not, the recursive-nix derivation will be built locally (in which case make sure your local Nix setup has recursive-nix enabled), which is essentially as much work as building default itself. This might still be worthwhile however, since subsequent builds of the same recursive derivation will complete immediately, without having to evaluate the default derivation again.

Expose pact as an attribute of output derivation

The default package and the recursive package now both have a pact attribute containing the version of the pact that gets compiled in as well as its src. This allows downstream consumers of these packages to access the version and the source of the pact package embedded into the chainweb binary they're building.

Allow overriding the pact source

This PR adds a pact input to the flake, which defaults to an empty flake, standing in for a null, meaning that the pact source pinned from the cabal.project should be used. When the pact input is overridden, via --override-input or as part of a downstream flake, chainweb will be built by the provided pact version. This overriding mechanism is also exposed via the functions in the lib output for cases when the choice of pact source is made outside the resolution of flake inputs.

@enobayram enobayram requested a review from DevopsGoth November 9, 2023 19:02
Copy link
Contributor

@DevopsGoth DevopsGoth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat, build times reduced (within and downstream from this repo). Workflow changes are documented.

flake.nix Outdated
haskellNix = {
url = "github:input-output-hk/haskell.nix";
hs-nix-infra = {
url = "github:kadena-io/hs-nix-infra/enis/metadata-experiments";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We intend to follow the main branch at this repo, yes?

Copy link
Contributor Author

@enobayram enobayram Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jwiegley, that's correct, I'm just experimenting with a few approaches for now.

Trying to expose the `src` of the pact input by caching it as a nix
store path proved to be fragile. It's possible to output such paths
from recursive-nix derivations, but those paths will be very tricky to
access by downstream Nix expressions.

This  commit instead uses pure metadata to reconstruct the pact src
definition at the recursive layer.
Copy link
Contributor

@chessai chessai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great, thanks!

@enobayram enobayram added this pull request to the merge queue Nov 17, 2023
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 17, 2023
@enobayram enobayram added this pull request to the merge queue Nov 20, 2023
@enobayram enobayram removed this pull request from the merge queue due to a manual request Nov 20, 2023
@enobayram enobayram added this pull request to the merge queue Dec 4, 2023
@enobayram enobayram removed this pull request from the merge queue due to a manual request Dec 4, 2023
@chessai chessai added this pull request to the merge queue Dec 4, 2023
Merged via the queue into master with commit 28764eb Dec 4, 2023
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants