diff --git a/maintainers/scripts/haskell/report-successes.sh b/maintainers/scripts/haskell/report-successes.sh new file mode 100755 index 0000000000000..5fc6ce9c43052 --- /dev/null +++ b/maintainers/scripts/haskell/report-successes.sh @@ -0,0 +1,39 @@ +set -euo pipefail + +function help { +cat < 0 ]]; then + help +fi + +echo "Reading derivations list" +derivations=$( /dev/null || : # ignore error code here so we can report successes + +echo "Checking which derivations actually placed output paths in the store..." +for drv in $derivations; do + outputs=$(nix-store --query $drv) + failures=false; + for out in $outputs; do + if [[ ! -d $out ]]; then + failures=true + fi; + done; + if ! $failures; then + echo $drv + fi; +done diff --git a/maintainers/scripts/haskell/sweep-packages.nix b/maintainers/scripts/haskell/sweep-packages.nix new file mode 100644 index 0000000000000..ade08e88aee05 --- /dev/null +++ b/maintainers/scripts/haskell/sweep-packages.nix @@ -0,0 +1,83 @@ +# Utils for sweeping through packages based on some property discoverable at eval time +# Useful for narrowing down package candidates on which to test some build time property +# +# Example 1: finding packages with patches that no longer apply +# nix-build sweep-packages.nix -A derivationsWith.overrideAttrs.patches --keep-going +# The desired packages are reported in the error message or on a subsequent `--dry-run` +# +# Example 2: finding packages with unnecessarily disabled test suite +# nix-instantiate sweep-packages.nix -A derivationsWithout.overrideAttrs.doCheck | ./report-successes.sh +# Here we use `derivationsWithout` to reset the `doCheck` override and then look at builds that *don't* fail + +{ + nixpkgs ? import ../../.. { }, # nixpkgs to obtain utils from + pkgs ? nixpkgs.haskellPackages, # package set to sweep +}: + +with nixpkgs; + +rec { + inherit pkgs lib; + + id = x: x; + + canEval = v: (builtins.tryEval v.outPath).success; + + isValidPackage = + n: v: + lib.all id [ + (n != "ghc") + (!(v.meta.broken or true)) + ((v.meta.hydraPlatforms or null) != [ ]) + ]; + + original = lens: lib.filterAttrs (n: v: isValidPackage n v && lens.get v) pkgs; + + modified = + modify: lens: + lib.pipe (original lens) [ + (builtins.mapAttrs (_: modify lens)) + (lib.filterAttrs (_: canEval)) + ]; + + lenses = { + overrideAttrs = { + doCheck = rec { + get = v: !(v.doCheck or true); + set = x: v: v.overrideAttrs { doCheck = x; }; + reset = set true; + }; + + patches = rec { + get = v: v.patches != [ ]; + set = x: v: v.overrideAttrs { patches = x; }; + reset = set [ ]; + }; + }; + + overrideCabal = with haskell.lib.compose; { + doHaddock = rec { + get = v: v.isHaskellLibrary && !(lib.hasInfix "Setup haddock" v.haddockPhase); + set = x: overrideCabal { doHaddock = x; }; + reset = set true; + }; + + jailbreak = rec { + get = v: lib.hasInfix "jailbreak-cabal" v.postPatch; + set = x: overrideCabal { jailbreak = x; }; + reset = set false; + }; + + enableParallelBuilding = rec { + get = v: !lib.hasInfix "-j$NIX_BUILD_CORES" v.setupCompilerEnvironmentPhase; + set = x: overrideCabal { enableParallelBuilding = x; }; + reset = set true; + }; + }; + }; + + sweep = f: builtins.mapAttrs (_: builtins.mapAttrs (_: modified f)) lenses; + + derivationsWithout = sweep (l: l.reset); + derivationsWith = sweep (_: id); +}