Skip to content

Commit 33dc7bc

Browse files
authored
Tidy ci.nix using dimension (#500)
I recently came across this rather nice way of structuring build matrices for ci.nix. I think it makes the haskell.nix ci.nix a lot clearer!
1 parent cb3acc6 commit 33dc7bc

File tree

2 files changed

+146
-56
lines changed

2 files changed

+146
-56
lines changed

ci.nix

+32-56
Original file line numberDiff line numberDiff line change
@@ -3,66 +3,42 @@
33
# - https://github.com/NixOS/nixpkgs/pull/68398
44

55
let
6+
inherit (import ./dimension.nix) dimension;
67
nixpkgsVersions = {
78
# "release-18.09" = builtins.fetchTarball "https://github.com/input-output-hk/nixpkgs/archive/7e4dcacbf066a8e2d12693a9de1fb30c77081c5d.tar.gz";
89
"release-19.03" = builtins.fetchTarball "https://github.com/input-output-hk/nixpkgs/archive/a8f81dc037a5977414a356dd068f2621b3c89b60.tar.gz";
910
# "release-19.09" = builtins.fetchTarball "https://github.com/input-output-hk/nixpkgs/archive/3d623a406cec9052ae0a16a79ce3ce9de11236bb.tar.gz";
1011
};
12+
systems = {
13+
"x86_64-linux" = {};
14+
};
15+
crossSystems = {
16+
"x86_64-pc-mingw32" = {};
17+
};
1118
haskellNixArgs = import ./.;
12-
defaultNixpkgs = import (nixpkgsVersions."release-19.03") {};
13-
recRecurseIntoAttrs = with defaultNixpkgs; pred: x: if pred x then recurseIntoAttrs (lib.mapAttrs (n: v: if n == "buildPackages" then v else recRecurseIntoAttrs pred v) x) else x;
1419
in
15-
recRecurseIntoAttrs (x: with defaultNixpkgs; lib.isAttrs x && !lib.isDerivation x) (
16-
builtins.mapAttrs (nixpkgsName: nixpkgsSrc: with (import nixpkgsSrc {}); {
17-
x86_64-linux = {
18-
hello = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-linux"; }));
19-
(haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2";}).components.exes.hello;
20-
x86_64-pc-mingw32-hello = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-linux"; crossSystem.config = "x86_64-pc-mingw32"; }));
21-
(haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2";}).components.exes.hello;
22-
23-
iserv-proxy = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-linux"; }));
24-
(ghc-extra-packages.ghc865.iserv-proxy.components.exes).iserv-proxy;
25-
26-
x86_64-pc-mingw32-iserv-proxy = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-linux"; crossSystem.config = "x86_64-pc-mingw32"; }));
27-
(buildPackages.ghc-extra-packages.ghc865.iserv-proxy.components.exes).iserv-proxy;
28-
29-
x86_64-pc-mingw32-remote-iserv = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-linux"; crossSystem.config = "x86_64-pc-mingw32"; }));
30-
(ghc-extra-packages.ghc865.remote-iserv.components.exes).remote-iserv;
31-
32-
};
33-
x86_64-darwin = {
34-
hello = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-darwin"; }));
35-
(haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2";}).components.exes.hello;
36-
x86_64-pc-mingw32-hello = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-darwin"; crossSystem.config = "x86_64-pc-mingw32"; }));
37-
(haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2";}).components.exes.hello;
38-
39-
iserv-proxy = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-darwin"; }));
40-
(ghc-extra-packages.ghc865.iserv-proxy.components.exes).iserv-proxy;
41-
42-
x86_64-pc-mingw32-iserv-proxy = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-darwin"; crossSystem.config = "x86_64-pc-mingw32"; }));
43-
(buildPackages.ghc-extra-packages.ghc865.iserv-proxy.components.exes).iserv-proxy;
44-
45-
x86_64-pc-mingw32-remote-iserv = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-darwin"; crossSystem.config = "x86_64-pc-mingw32"; }));
46-
(ghc-extra-packages.ghc865.remote-iserv.components.exes).remote-iserv;
47-
48-
};
49-
haskell-nix.compiler = {
50-
x86_64-linux = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-linux"; }));
51-
haskell-nix.compiler;
52-
x86_64-darwin = with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-darwin";}));
53-
haskell-nix.compiler;
54-
};
55-
tests = {
56-
x86_64-linux = (import ./test { nixpkgs = nixpkgsSrc; nixpkgsArgs = { system = "x86_64-linux"; }; });
57-
# x86_64-darwin = (import ./test { nixpkgs = nixpkgsSrc; nixpkgsArgs = { system = "x86_64-darwin"; }; });
58-
};
59-
60-
# Don't build (all of) stackage on linux for now.
61-
# stackage = {
62-
# x86_64-linux = (with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-linux"; }));
63-
# haskell-nix.snapshots."lts-13.29");
64-
# # x86_64-darwin = (with (import nixpkgsSrc (haskellNixArgs // { system = "x86_64-darwin"; }));
65-
# # haskell-nix.snapshots."lts-13.29");
66-
# };
67-
68-
}) nixpkgsVersions)
20+
dimension "Nixpkgs version" nixpkgsVersions (nixpkgsName: nixpkgsSrc:
21+
dimension "System" systems (system: _:
22+
# Native builds
23+
# TODO: can we merge this into the general case by picking an appropriate "cross system" to mean native?
24+
let pkgs = import nixpkgsSrc (haskellNixArgs // { inherit system; });
25+
in pkgs.recurseIntoAttrs {
26+
hello = (pkgs.haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2";}).components.exes.hello;
27+
iserv-proxy = pkgs.ghc-extra-packages.ghc865.iserv-proxy.components.exes.iserv-proxy;
28+
ghc = pkgs.recurseIntoAttrs pkgs.haskell-nix.compiler;
29+
tests = pkgs.lib.optionalAttrs (system == "x86_64-linux") (import ./test { inherit pkgs; });
30+
}
31+
//
32+
dimension "Cross system" crossSystems (crossSystem: _:
33+
# Cross builds
34+
let pkgs = import nixpkgsSrc (haskellNixArgs // { inherit system; crossSystem.config = crossSystem; });
35+
in pkgs.recurseIntoAttrs {
36+
hello = (pkgs.haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2";}).components.exes.hello;
37+
38+
iserv-proxy = pkgs.ghc-extra-packages.ghc865.iserv-proxy.components.exes.iserv-proxy;
39+
40+
remote-iserv = pkgs.ghc-extra-packages.ghc865.remote-iserv.components.exes.remote-iserv;
41+
}
42+
)
43+
)
44+
)

dimension.nix

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Borrowed from https://github.com/cachix/ghcide-nix/pull/4/files#diff-70bfff902f4dec33e545cac10ee5844d
2+
# Tweaked to use builtins.mapAttrs instead of needing the one from nixpkgs lib
3+
{
4+
/*
5+
dimension: name -> attrs -> function -> attrs
6+
where
7+
function: keyText -> value -> attrsOf package
8+
9+
WARNING: Attribute names must not contain periods (".").
10+
See https://github.com/NixOS/nix/issues/3088
11+
12+
NOTE: The dimension name will be picked up by agent and web ui soon.
13+
14+
Specifies a dimension of the build matrix. For example
15+
16+
dimension "Example" {
17+
withP = { p = true; }
18+
withoutP = { p = false; }
19+
} (key: # either "withP" or "withoutP"
20+
{ p }: # either p = true or p = false
21+
myProject p
22+
)
23+
24+
evaluates roughly to
25+
26+
{
27+
withP = myProject true;
28+
withoutP = myProject false;
29+
}
30+
31+
Use nested calls for multiple dimensions.
32+
33+
Example:
34+
35+
dimension "System" {
36+
"x86_64-linux" = {};
37+
# ...
38+
}: (system: {}:
39+
40+
dimension "Nixpkgs release" (
41+
{
42+
"nixpkgs-19_03".nixpkgs = someSource
43+
} // optionalAttrs (system != "...") {
44+
"nixpkgs-unstable".nixpkgs = someOtherSource
45+
}
46+
) (_key: { nixpkgs }:
47+
48+
myProject system nixpkgs
49+
50+
)
51+
)
52+
53+
evaluates roughly to
54+
55+
{
56+
x86_64-linux.nixpkgs-19_03 = myProject "x86_64-linux" someSource;
57+
x86_64-linux.nixpkgs-unstable = myProject "x86_64-linux" someOtherSource;
58+
...
59+
}
60+
61+
If you need to make references across attributes, you can do so by binding
62+
the result. Wherever you write
63+
64+
dimension "My dimension" {} (key: value: f1 key value)
65+
66+
You can also write
67+
68+
let
69+
myDimension = dimension "My dimension" {} (key: value: f2 key value myDimension)
70+
in
71+
myDimension
72+
73+
This example builds a single test runner to reuse across releases:
74+
75+
let
76+
overlay =
77+
testRunnerPkgs: self: super: {
78+
# ...
79+
};
80+
myProject =
81+
{ nixpkgs,
82+
pkgs ? import nixpkgs { overlays = [ overlay ]; },
83+
testRunnerPkgs ? pkgs
84+
}: pkgs;
85+
in
86+
87+
let
88+
latest = "nixpkgs-19_03";
89+
releases =
90+
dimension "Nixpkgs release"
91+
{
92+
nixpkgs-18_09.nixpkgs = someSource
93+
nixpkgs-19_03.nixpkgs = someOtherSource
94+
}
95+
(_key: { nixpkgs }:
96+
97+
myProject {
98+
inherit nixpkgs;
99+
testRunnerPkgs = releases."${latest}";
100+
}
101+
102+
);
103+
in releases;
104+
105+
*/
106+
dimension = name: attrs: f:
107+
builtins.mapAttrs
108+
(k: v:
109+
let o = f k v;
110+
in o // { recurseForDerivations = o.recurseForDerivations or true; }
111+
)
112+
attrs
113+
// { meta.dimension.name = name; };
114+
}

0 commit comments

Comments
 (0)