hnix-store/docs/02-Hacking.org
2023-12-02 11:30:44 +01:00

4.4 KiB

Hacking

Basic workflow

Entering the development shell using nix-shell will pull in all the dependencies required by all sub-packages.

Both default.nix and shell.nix simply import <nixpkgs> from your NIX_PATH. If this is by chance broken, try using nixpkgs-unstable which is targeted by our CI, as it is also the basis for haskell-updates nixpkgs branch where new Hackage packages land.

Not pinning the to specific version of nixpkgs is intentional so CI can roll with the unstable branch and detect breakage early.

Using another version of GHC

To use a different version of GHC to the one used by your pkgs.haskellPackages, pass, for example --argstr compiler ghc963 to either nix-shell or nix-build

matrix.nix

nix-build matrix-nix can be used to check that all our packages built against all supported GHC versions. It pulls the versions from .github/workflows/ci.dhall so there is a single source of truth and the compilers don't need to be listed separately again.

Adding new packages

When adding a new sub-package, following files need to be updated:

  • default.nix
  • shell.nix
  • cabal.project
  • cabal.project.local.ci (only if needed)
  • hie.yaml

CI

The GitHub Actions CI uses github-actions-dhall and .github/workflows/ci.dhall to generate the .github/workflows/ci.yaml workflow file which does a full matrix build of supported compilers both using cabal and nix.

Cachix cache

The CI uses cachix to not rebuild everything from scratch everytime it runs, it also feeds the cache available at https://app.cachix.org/cache/hnix-store which you can configure on your system.

Updating

To update the CI, edit .github/workflows/ci.dhall and run .github/workflows/ci.sh to regenerate the yaml file. Don't forget to commit both files.

cabal.project.local.ci

The cabal.project.local.ci file is used by the CI workflow to alter ghc-options, enabling e.g. -Werror and -Wunused-packages. You can copy this to cabal.project.local to have the same build configuration:

cp cabal.project.local.ci cabal.project.local

Changelogs

Since the packages are used by others as dependencies in production environments, make sure to add changelog entries for public interface breaking changes. These don't need to cover all changes if you are sure that the change only affects packages inside hnix-store.

Readmes

Some README.md files are symlinked to README.lhs files and also serve as a buildable executables. This makes sure they are always up to date and buildable. They are guarded by cabal flags and only available in development environment which enables all of them via cabal.project, which also causes them to be built by CI but not to propagate downstream (and polute $PATH of downstream users).

ghcid

ghcid can be used as a lightweight IDE to assist with edit-compile-run-test cycle. You can obtain it quickly using nix-shell -p haskellPackages.ghcid

Running

For a single library

ghcid -c 'cabal repl hnix-store-core'

For a testsuite or executable

ghcid -c 'cabal repl test-suite:props'
# or
ghcid -c 'cabal repl exe:db-readme'

Often the specifier like exe or test-suite can be omitted when the name is unique.

Running a testsuite after a build

If working with the testsuite directly, you can invoke

ghcid -c 'cabal repl test-suite:remote' --test 'hspec spec'

If you are editing a library or you need to run multiple testsuites, you can for example use

ghcid -c 'cabal repl hnix-store-remote' --test ':! cabal test test-suite:remote && cabal test test-suite:remote-io'

With restarting

ghcid can also restart itself so ghci picks up new or moved files, following incantation can be invoked when working with hnix-store-remote to combine all of the features

ghcid -c 'cabal repl hnix-store-remote' \
  --restart 'hnix-store-remote/hnix-store-remote.cabal' \
  --test ':! cabal test test-suite:remote && cabal test test-suite:remote-io'