kadena-io / pact

The Pact Smart Contract Language
https://docs.kadena.io/build/pact
BSD 3-Clause "New" or "Revised" License
579 stars 100 forks source link

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

Closed enobayram closed 9 months ago

enobayram commented 9 months ago

I'm skipping the PR checklist since this is a Nix-only infrastructure change.

PR checklist: * [ ] Test coverage for the proposed changes * [ ] PR description contains example output from repl interaction or a snippet from unit test output * [ ] Documentation has been updated if new natives or FV properties have been added. To generate new documentation, issue `cabal run tests`. If they pass locally, docs are generated. * [ ] Any changes that could be relevant to users [have been recorded in the changelog](https://github.com/kadena-io/pact/blob/master/CHANGELOG.md) * [ ] In case of changes to the Pact trace output (`pact -t`), make sure [pact-lsp](https://github.com/kadena-io/pact-lsp) is in sync. Additionally, please justify why you should or should not do the following: * [ ] Confirm replay/back compat * [ ] Benchmark regressions * [ ] (For Kadena engineers) Run integration-tests against a Chainweb built with this version of Pact

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 pact user that wants to nix build an uncached pact 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:

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 pact, which makes it convenient for any user to nix build pact 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 pact 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.

enobayram commented 9 months ago

Thank you for the review @emilypi! You have a great point about the documentation. We're planning to write some comprehensive documentation about all of our Nix infra soon and that will include all these workflows. I was planning to add a link to that from the README, so that we don't clutter it too much and more importantly, we can keep it up to date without spamming each one of our Haskell repos with README PRs.