Skip to content

Commit

Permalink
fixup! [OPS-1458] Add haskell.nix wrapper for CI
Browse files Browse the repository at this point in the history
  • Loading branch information
Sereja313 committed Aug 9, 2023
1 parent 8c06b9e commit bc7c852
Showing 1 changed file with 48 additions and 36 deletions.
84 changes: 48 additions & 36 deletions lib/haskell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,55 @@ let
makeCI = haskellPkgs: {
# haskell project root
src,
# haskell package names
packageNames,
# cabal file with ghc versions specified in test-with
cabalFile,
# list of ghc versions to build packages, if not specified the ghc versions
# will be taken from tested-with stanzas from .cabal files
ghcVersions ? [],
# whether to build the project with stack, disable if you are not using stack
buildWithStack ? true,
buildWithStack ? true,
# stack files to use in addition to stack.yaml
stackFiles ? [],
# stack resolvers for building the project, they will be replaced in stack.yaml
resolvers ? [],
# extra haskell.nix arguments
extraArgs ? {}
}: let
pkgs = nixpkgs.legacyPackages.${haskellPkgs.system};
}:
# if buildWithStack is false, there is no point in specifying resolvers or stackFiles
assert !buildWithStack -> resolvers == [] && stackFiles == [];
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
replaceDots = builtins.replaceStrings ["."] ["-"];

# invoke haskell.nix for every ghc specified in tested-with stanza of cabalFile
ghc-versions = getTestedWithVersions cabalFile;
pkgs-per-ghc = lib.genAttrs ghc-versions
(ghc: haskellPkgs.haskell-nix.cabalProject ({
inherit src;
compiler-nix-name = ghc;
} // extraArgs));
cabalFiles = lib.filter (x: x != "") (lib.splitString "\n"
(builtins.readFile (pkgs.runCommand "cabalFiles" {} ''
${pkgs.findutils}/bin/find ${src} -type f -name "*.cabal" > $out
'')));

# extract ghc tested-with versions from each .cabal file, keep a list of packages built with each ghc
ghc-versions-tested-with = let
# ghc versions for each package
ghcsPerCabal = map (f: {
package = lib.removeSuffix ".cabal" (builtins.baseNameOf f);
ghcs = getTestedWithVersions f;}) cabalFiles;
# ghc versions from all .cabal files
allGhcs = lib.unique (lib.concatMap (lib.getAttr "ghcs") ghcsPerCabal);
in lib.genAttrs allGhcs
(ghc: map (lib.getAttr "package") (lib.filter (attrs: builtins.elem ghc attrs.ghcs) ghcsPerCabal));
ghc-versions = if ghcVersions != [] then ghcVersions else lib.attrNames ghc-versions-tested-with;
# invoke haskell.nix for every ghc specified in tested-with stanzas of .cabal files
pkgs-per-ghc = let
pkgs' = lib.genAttrs ghc-versions
(ghc: haskellPkgs.haskell-nix.cabalProject ({
inherit src;
compiler-nix-name = ghc;
} // extraArgs));
# we need to filter out packages and checks that are not specified to build with this compiler
filterFlake' = ghc: flake': flake' // {
packages = filterPackages ghc flake'.packages;
checks = filterPackages ghc flake'.checks;
};
filterPackages = ghc: packages: lib.filterAttrs
(n: _: builtins.elem (lib.head (lib.splitString ":" n)) ghc-versions-tested-with.${ghc}) packages;
in if ghcVersions != [] then pkgs'
else lib.flip lib.mapAttrs pkgs' (n: v: v // { flake' = filterFlake' n v.flake';});

# invoke haskell.nix for stack.yaml and every file from stackFiles
stackYamls = lib.optionals buildWithStack ([ "stack.yaml" ] ++ stackFiles);
Expand All @@ -43,36 +69,22 @@ let
(resolver: haskellPkgs.haskell-nix.stackProject {
src = pkgs.runCommand "change resolver" { } ''
mkdir -p $out
cp -r ${src}/* .
${pkgs.gnused}/bin/sed -i 's/resolver:.*/resolver: ${resolver}/' stack.yaml
cp -r ./* $out
cp -rT ${src} $out
${pkgs.gnused}/bin/sed -i 's/resolver:.*/resolver: ${resolver}/' $out/stack.yaml
'';
} // extraArgs));

all-pkgs = pkgs-per-ghc // pkgs-per-stack-yaml // pkgs-per-resolver;

# returns the list of all components for a package
get-package-components = pkg:
# library
lib.optional (pkg ? library) pkg.library
# haddock
++ lib.optional (pkg ? library) pkg.library.haddock
# exes, tests and benchmarks
++ lib.attrValues pkg.exes
++ lib.attrValues pkg.tests
++ lib.attrValues pkg.benchmarks;

# all components for each specified ghc version or stack yaml
build-all = lib.mapAttrs' (prefix: pkg:
let components = lib.concatMap (name: get-package-components pkg.${name}.components) packageNames;
in lib.nameValuePair "${prefix}:build-all"
(pkgs.linkFarmFromDrvs "build-all" components)) all-pkgs;
lib.nameValuePair "${prefix}:build-all"
(pkgs.linkFarmFromDrvs "build-all" (lib.attrValues pkg.flake'.packages))) all-pkgs;

# all tests for each specified ghc version or stack yaml
test-all = lib.mapAttrs' (prefix: pkg:
let tests = lib.filter lib.isDerivation (lib.concatMap (name: lib.attrValues pkg.${name}.checks) packageNames);
in lib.nameValuePair "${prefix}:test-all"
(pkgs.linkFarmFromDrvs "test-all" tests)) all-pkgs;
lib.nameValuePair "${prefix}:test-all"
(pkgs.linkFarmFromDrvs "test-all" (lib.attrValues pkg.flake'.checks))) all-pkgs;

# build matrix used in github actions
build-matrix = { include = map (prefix: { inherit prefix; }) (ghc-versions ++ (map replaceDots (stackYamls ++ stackResolvers))); };
Expand All @@ -94,7 +106,7 @@ let
pkgs.haskell-nix.stackProject {
# <...>
modules = [
(optionsLocalPackages = {
(optionsLocalPackages {
ghcOptions = [ "-Werror" ];
})
];
Expand Down

0 comments on commit bc7c852

Please sign in to comment.