source: trunk/flake.nix

Last change on this file was 9186615, checked in by Jean-Paul Calderone <exarkun@…>, at 2023-07-21T15:29:06Z

expose our cache to anyone who wants it

  • Property mode set to 100644
File size: 9.7 KB
Line 
1{
2  description = "Tahoe-LAFS, free and open decentralized data store";
3
4  nixConfig = {
5    # Supply configuration for the build cache updated by our CI system.  This
6    # should allow most users to avoid having to build a large number of
7    # packages (otherwise necessary due to our Python package overrides).
8    substituters = ["https://tahoe-lafs-opensource.cachix.org"];
9    trusted-public-keys = ["tahoe-lafs-opensource.cachix.org-1:eIKCHOPJYceJ2gb74l6e0mayuSdXqiavxYeAio0LFGo="];
10  };
11
12  inputs = {
13    # A couple possible nixpkgs pins.  Ideally these could be selected easily
14    # from the command line but there seems to be no syntax/support for that.
15    # However, these at least cause certain revisions to be pinned in our lock
16    # file where you *can* dig them out - and the CI configuration does.
17    #
18    # These are really just examples for the time being since neither of these
19    # releases contains a package set that is completely compatible with our
20    # requirements.  We could decide in the future that supporting multiple
21    # releases of NixOS at a time is worthwhile and then pins like these will
22    # help us test each of those releases.
23    "nixpkgs-22_11" = {
24      url = github:NixOS/nixpkgs?ref=nixos-22.11;
25    };
26    "nixpkgs-23_05" = {
27      url = github:NixOS/nixpkgs?ref=nixos-23.05;
28    };
29
30    # We depend on a very new python-cryptography which is not yet available
31    # from any release branch of nixpkgs.  However, it is contained in a PR
32    # currently up for review.  Point our nixpkgs at that for now.
33    "nixpkgs-unstable" = {
34      url = github:NixOS/nixpkgs?ref=pull/244135/head;
35    };
36
37    # Point the default nixpkgs at one of those.  This avoids having getting a
38    # _third_ package set involved and gives a way to provide what should be a
39    # working experience by default (that is, if nixpkgs doesn't get
40    # overridden).
41    nixpkgs.follows = "nixpkgs-unstable";
42
43    # Also get flake-utils for simplified multi-system definitions.
44    flake-utils = {
45      url = github:numtide/flake-utils;
46    };
47
48    # And get a helper that lets us easily continue to provide a default.nix.
49    flake-compat = {
50      url = "github:edolstra/flake-compat";
51      flake = false;
52    };
53  };
54
55  outputs = { self, nixpkgs, flake-utils, ... }:
56    {
57      # Expose an overlay which adds our version of Tahoe-LAFS to the Python
58      # package sets we specify, as well as all of the correct versions of its
59      # dependencies.
60      #
61      # We will also use this to define some other outputs since it gives us
62      # the most succinct way to get a working Tahoe-LAFS package.
63      overlays.default = import ./nix/overlay.nix;
64
65    } // (flake-utils.lib.eachDefaultSystem (system: let
66
67      # The package set for this system architecture.
68      pkgs = import nixpkgs {
69        inherit system;
70        # And include our Tahoe-LAFS package in that package set.
71        overlays = [ self.overlays.default ];
72      };
73
74      # pythonVersions :: [string]
75      #
76      # The version strings for the Python runtimes we'll work with.
77      pythonVersions =
78        let
79          # Match attribute names that look like a Python derivation - CPython
80          # or PyPy.  We take care to avoid things like "python-foo" and
81          # "python3Full-unittest" though.  We only want things like "pypy38"
82          # or "python311".
83          nameMatches = name: null != builtins.match "(python|pypy)3[[:digit:]]{0,2}" name;
84
85          # Sometimes an old version is left in the package set as an error
86          # saying something like "we remove this".  Make sure we whatever we
87          # found by name evaluates without error, too.
88          notError = drv: (builtins.tryEval drv).success;
89        in
90          # Discover all of the Python runtime derivations by inspecting names
91          # and filtering out derivations with errors.
92          builtins.attrNames (
93            pkgs.lib.attrsets.filterAttrs
94              (name: drv: nameMatches name && notError drv)
95              pkgs
96          );
97
98      # defaultPyVersion :: string
99      #
100      # An element of pythonVersions which we'll use for the default package.
101      defaultPyVersion = "python3";
102
103      # pythons :: [derivation]
104      #
105      # Retrieve the actual Python package for each configured version.  We
106      # already applied our overlay to pkgs so our packages will already be
107      # available.
108      pythons = builtins.map (pyVer: pkgs.${pyVer}) pythonVersions;
109
110      # packageName :: string -> string
111      #
112      # Construct the Tahoe-LAFS package name for the given Python runtime.
113      packageName = pyVersion: "${pyVersion}-tahoe-lafs";
114
115      # string -> string
116      #
117      # Construct the unit test application name for the given Python runtime.
118      unitTestName = pyVersion: "${pyVersion}-unittest";
119
120      # (string -> a) -> (string -> b) -> string -> attrset a b
121      #
122      # Make a singleton attribute set from the result of two functions.
123      singletonOf = f: g: x: { ${f x} = g x; };
124
125      # [attrset] -> attrset
126      #
127      # Merge a list of attrset into a single attrset with overlap preferring
128      # rightmost values.
129      mergeAttrs = pkgs.lib.foldr pkgs.lib.mergeAttrs {};
130
131      # makeRuntimeEnv :: string -> derivation
132      #
133      # Create a derivation that includes a Python runtime, Tahoe-LAFS, and
134      # all of its dependencies.
135      makeRuntimeEnv = singletonOf packageName makeRuntimeEnv';
136      makeRuntimeEnv' = pyVersion: (pkgs.${pyVersion}.withPackages (ps: with ps;
137        [ tahoe-lafs ] ++
138        tahoe-lafs.passthru.extras.i2p ++
139        tahoe-lafs.passthru.extras.tor
140      )).overrideAttrs (old: {
141        # By default, withPackages gives us a derivation with a fairly generic
142        # name (like "python-env").  Put our name in there for legibility.
143        # See the similar override in makeTestEnv.
144        name = packageName pyVersion;
145      });
146
147      # makeTestEnv :: string -> derivation
148      #
149      # Create a derivation that includes a Python runtime and all of the
150      # Tahoe-LAFS dependencies, but not Tahoe-LAFS itself, which we'll get
151      # from the working directory.
152      makeTestEnv = pyVersion: (pkgs.${pyVersion}.withPackages (ps: with ps;
153        [ tahoe-lafs ] ++
154        tahoe-lafs.passthru.extras.i2p ++
155        tahoe-lafs.passthru.extras.tor ++
156        tahoe-lafs.passthru.extras.unittest
157      )).overrideAttrs (old: {
158        # See the similar override in makeRuntimeEnv'.
159        name = packageName pyVersion;
160      });
161    in {
162      # Include a package set with out overlay on it in our own output.  This
163      # is mainly a development/debugging convenience as it will expose all of
164      # our Python package overrides beneath it.  The magic name
165      # "legacyPackages" is copied from nixpkgs and has special support in the
166      # nix command line tool.
167      legacyPackages = pkgs;
168
169      # The flake's package outputs.  We'll define one version of the package
170      # for each version of Python we could find.  We'll also point the
171      # flake's "default" package at the derivation corresponding to the
172      # default Python version we defined above.  The package consists of a
173      # Python environment with Tahoe-LAFS available to it.
174      packages =
175        mergeAttrs (
176          [ { default = self.packages.${system}.${packageName defaultPyVersion}; } ]
177          ++ (builtins.map makeRuntimeEnv pythonVersions)
178          ++ (builtins.map (singletonOf unitTestName makeTestEnv) pythonVersions)
179        );
180
181      # The flake's app outputs.  We'll define a version of an app for running
182      # the test suite for each version of Python we could find.  We'll also
183      # define a version of an app for running the "tahoe" command-line
184      # entrypoint for each version of Python we could find.
185      apps =
186        let
187          # writeScript :: string -> string -> path
188          #
189          # Write a shell program to a file so it can be run later.
190          #
191          # We avoid writeShellApplication here because it has ghc as a
192          # dependency but ghc has Python as a dependency and our Python
193          # package override triggers a rebuild of ghc and many Haskell
194          # packages which takes a looong time.
195          writeScript = name: text: "${pkgs.writeShellScript name text}";
196
197          # makeTahoeApp :: string -> attrset
198          #
199          # A helper function to define the Tahoe-LAFS runtime entrypoint for
200          # a certain Python runtime.
201          makeTahoeApp = pyVersion: {
202            "tahoe-${pyVersion}" = {
203              type = "app";
204              program =
205                writeScript "tahoe"
206                  ''
207                    ${makeRuntimeEnv' pyVersion}/bin/tahoe "$@"
208                  '';
209            };
210          };
211
212          # makeUnitTestsApp :: string -> attrset
213          #
214          # A helper function to define the Tahoe-LAFS unit test entrypoint
215          # for a certain Python runtime.
216          makeUnitTestsApp = pyVersion: {
217            "${unitTestName pyVersion}" = {
218              type = "app";
219              program =
220                let
221                  python = "${makeTestEnv pyVersion}/bin/python";
222                in
223                  writeScript "unit-tests"
224                    ''
225                    ${python} setup.py update_version
226                    export TAHOE_LAFS_HYPOTHESIS_PROFILE=ci
227                    export PYTHONPATH=$PWD/src
228                    ${python} -m twisted.trial "$@"
229                  '';
230            };
231          };
232        in
233          # Merge a default app definition with the rest of the apps.
234          mergeAttrs (
235            [ { default = self.apps.${system}."tahoe-python3"; } ]
236            ++ (builtins.map makeUnitTestsApp pythonVersions)
237            ++ (builtins.map makeTahoeApp pythonVersions)
238          );
239    }));
240}
Note: See TracBrowser for help on using the repository browser.