diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..236b47d7160f841abe9e56c59f8d3604d4bf2f5b --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,77 @@ +# Use a template that makes pipelines run for the default branch, tags, and +# all types of merge request pipelines. +include: + - template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml' + +# The jobs all use the `nix` CLI so make sure we have it. +image: "nixos/nix:2.13.2" + +default: + # Choose a native Nix runner and we can use the local system's Nix store as + # our Nix cache. + tags: + - "nix" + +variables: + # Pick a nixpkgs to get cachix and bash from. Nothing else + # Turn on some `nix` CLI features that aren't on by default. + NIX_CONFIG: "experimental-features = nix-command flakes" + +# Run the standard Haskell linter over the library and test suite sources. +hlint: + script: >- + nix run .#hlint -- src/ test/ + +# Use cabal to build the library and test suite and then run the test suite. +cabal-build-and-test: + cache: + # The cache is additive. We can aways push more objects to it. The cabal + # system uses a hash mechanism so that different builds will never collide + # with each other. We can probably safely add to a single cache + # indefinitely so we don't try to make come up with a fancy cache key. + # Compared to trying to use a hash of our dependencies (or, eg, the .cabal + # file itself) as a cache key, this saves us a lot of rebuilding when we + # have a minor change in dependencies or packaging metadata. The possibly + # shortcoming of this approach is that the cache will grow without bounds + # as our dependencies change. It would be nice if there were a way to + # trim stale dependencies from it periodically. + key: "v0-cabal" + + # Even if a build fails (eg because of a test suite failure or because the + # job timed out because building things took too long), there will be + # useful build artifacts worth caching - perhaps some new dependencies + # will have been built, for example. We may as well cache these. + when: "always" + + # These paths are resolved relative to the project directory. + paths: + # Cabal normally writes this directory to $HOME. However, we override + # this (in the job script) to put the directory into the project + # checkout, since that's the only place we can cache files from. + - ".cabal" + + script: + - | + # Configure cabal to put its caches beneath the project directory. + # This is only done in CI configuration because non-CI users probably + # want their local cabal configuration left alone. + cat >cabal.project.local <<EOF + store-dir: $CI_PROJECT_DIR/.cabal + remote-repo-cache: $CI_PROJECT_DIR/.cabal/packages + EOF + nix run .#cabal-test + +# Use nix to build the library and test suite and run the test suite. +nix-build-and-test: + script: >- + nix build + +# Force a build of the dev shell dependencies so we know they still work. +# Also, this populates the cache with the results which is a big win for every +# developer using our cache. +# +# We only have an x86_64-linux builder so we can't build the aarch64-darwin +# shell. Sorry... +nix-develop: + script: >- + nix build .#devShells.x86_64-linux.default diff --git a/flake.nix b/flake.nix index 67acf8e28e2d2b62686fe56c49ce2f67cf03b235..83f3d7f8f4685caa40ae4277c62bfc0530df7705 100644 --- a/flake.nix +++ b/flake.nix @@ -37,5 +37,24 @@ ]; }; packages = hslib.packages {}; + apps.hlint = hslib.apps.hlint {}; + + # Using the working directory of `nix run`, do a build with cabal and + # then run the test suite. + apps.cabal-test = { + type = "app"; + program = "${ + pkgs.writeShellApplication { + name = "cabal-build-and-test"; + runtimeInputs = with pkgs; [pkg-config haskell.compiler.${ghcVersion} cabal-install]; + + text = '' + cabal update hackage.haskell.org + cabal build tests + cabal run tests + ''; + } + }/bin/cabal-build-and-test"; + }; }); }