Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose finalPackages #68

Merged
merged 12 commits into from
Feb 8, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- API changes
- #37: Group `buildTools` (renamed to `tools`), `hlsCheck` and `hlintCheck` under the `devShell` submodule option; and allow disabling them all using `devShell.enable = false;` (useful if you want haskell-flake to produce just the package outputs).
- #64: Remove hlintCheck (use [treefmt-nix](https://github.com/numtide/treefmt-nix#flake-parts) instead)
- #52: Expose the final package set (API provisional)

## 0.1.0

Expand Down
18 changes: 18 additions & 0 deletions docs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env sh

# Renders the docs, prints the location of the docs, opens the docs if possible
#
# Does not run the link checker. That's done in runtest.sh.

nix --option sandbox false \
build --override-input haskell-flake path:${FLAKE} \
-L --show-trace \
github:hercules-ci/flake.parts-website \
"$@"

echo "Docs rendered to $PWD/result/options/haskell-flake.html"

# Works on linux
if type xdg-open &>/dev/null; then
xdg-open result/options/haskell-flake.html
fi
63 changes: 38 additions & 25 deletions flake-module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ in
};
};
};
projectSubmodule = types.submodule (args@{ name, config, lib, ... }: {
projectSubmodule = types.submoduleWith { specialArgs = { inherit pkgs self; }; modules = [ ./haskell-project.nix
{
options = {
haskellPackages = mkOption {
type = types.attrsOf raw;
Expand Down Expand Up @@ -133,37 +134,49 @@ in
This is an internal option, not meant to be set by the user.
'';
};

# Derived options

finalPackages = mkOption {
type = types.attrsOf raw;
readOnly = true;
Copy link
Owner

@srid srid Feb 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like readonly has no effect, because I can still set finalPackages.foo = ./.; (even finalPackages = ./.;) in test/flake.nix?

Or does it just silently ignore user values?

description = ''
The final package set, based `haskellPackages` plus
the additions and overrides specified in the other options.
'';
};
finalOverlay = mkOption {
type = types.raw;
readOnly = true;
internal = true;
};
};
config = import ./haskell-project.nix (args // { inherit self pkgs; });
});
} ]; };
in
{
options.haskellProjects = mkOption {
description = "Haskell projects";
type = types.attrsOf projectSubmodule;
};
});
};

config = {
perSystem = { config, self', lib, inputs', pkgs, ... }:
let
# Like mapAttrs, but merges the values (also attrsets) of the resulting attrset.
flatAttrMap = f: attrs: lib.mkMerge (lib.attrValues (lib.mapAttrs f attrs));
in
{
packages =
flatAttrMap (_: project: project.outputs.packages) config.haskellProjects;
devShells =
flatAttrMap
(_: project:
lib.optionalAttrs project.devShell.enable project.outputs.devShells)
config.haskellProjects;
checks =
flatAttrMap
(_: project:
lib.optionalAttrs project.devShell.enable project.outputs.checks)
config.haskellProjects;
};
config = let
# Like mapAttrs, but merges the values (also attrsets) of the resulting attrset.
mergeMapAttrs = f: attrs: lib.mkMerge (lib.mapAttrsToList f attrs);
in
{
packages =
mergeMapAttrs (_: project: project.outputs.packages) config.haskellProjects;
devShells =
mergeMapAttrs
(_: project:
lib.optionalAttrs project.devShell.enable project.outputs.devShells)
config.haskellProjects;
checks =
mergeMapAttrs
(_: project:
lib.optionalAttrs project.devShell.enable project.outputs.checks)
config.haskellProjects;
};
});
};
}
60 changes: 38 additions & 22 deletions haskell-project.nix
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ let
'';
in
{
outputs =

config =
let
projectKey = name;

Expand Down Expand Up @@ -78,29 +79,44 @@ in
};
in
{
packages =
let
mapKeys = f: attrs: lib.mapAttrs' (n: v: { name = f n; value = v; }) attrs;
# Prefix package names with the project name (unless
# project is named `default`)
dropDefaultPrefix = packageName:
if projectKey == "default"
then packageName
else "${projectKey}-${packageName}";
in
mapKeys dropDefaultPrefix
(lib.mapAttrs
(name: _: finalPackages."${name}")
config.packages);
finalPackages = config.haskellPackages.extend config.finalOverlay;

devShells."${projectKey}" = devShell;
finalOverlay = lib.composeManyExtensions [
# The order here matters.
#
# User's overrides (cfg.overrides) is applied **last** so
# as to give them maximum control over the final package
# set used.
localPackagesOverlay
(pkgs.haskell.lib.packageSourceOverrides config.source-overrides)
config.overrides
];

} // lib.optionalAttrs config.devShell.hlsCheck.enable {
outputs = {
packages =
let
mapKeys = f: attrs: lib.mapAttrs' (n: v: { name = f n; value = v; }) attrs;
# Prefix package names with the project name (unless
# project is named `default`)
dropDefaultPrefix = packageName:
if projectKey == "default"
then packageName
else "${projectKey}-${packageName}";
in
mapKeys dropDefaultPrefix
(lib.mapAttrs
(name: _: finalPackages."${name}")
config.packages);

checks."${projectKey}-hls" =
runCommandInSimulatedShell
devShell
self "${projectKey}-hls-check"
{ } "haskell-language-server";
devShells."${projectKey}" = devShell;

} // lib.optionalAttrs config.devShell.hlsCheck.enable {

checks."${projectKey}-hls" =
runCommandInSimulatedShell
devShell
self "${projectKey}-hls-check"
{ } "haskell-language-server";
};
};
}
25 changes: 21 additions & 4 deletions runtest.sh
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
set -e

if [ "$(uname)" == "Darwin" ]; then
SYSTEM=aarch64-darwin
function logHeader {
echo "\n||| $@"
}
else
SYSTEM=x86_64-linux
function logHeader {
echo -e "\n||| $@"
}
fi

FLAKE=$(pwd)
cd ./test

# First, build the flake.
echo "\n||| Testing nix build"
logHeader "Testing nix build"
nix build --override-input haskell-flake path:${FLAKE}
# Run the devshell test script in a nix develop shell.
echo "\n||| Testing nix devshell"
logHeader "Testing nix devshell"
nix develop --override-input haskell-flake path:${FLAKE} -c ./test.sh
# Test non-devshell features:
# Checks
echo "\n||| Testing nix flake checks"
logHeader "Testing nix flake checks"
nix --option sandbox false \
build --override-input haskell-flake path:${FLAKE} -L .#check

echo "\n||| All tests passed!"
logHeader "Testing docs"
nix build --override-input haskell-flake path:${FLAKE} \
--option log-lines 1000 --show-trace \
github:hercules-ci/flake.parts-website#checks.${SYSTEM}.linkcheck

logHeader "All tests passed!"