tahoe-lafs/flake.nix

211 lines
8.0 KiB
Nix
Raw Normal View History

{
description = "Tahoe-LAFS, free and open decentralized data store";
inputs = {
# Two alternate nixpkgs pins. Ideally these could be selected easily from
# the command line but there seems to be no syntax/support for that.
# However, these at least cause certain revisions to be pinned in our lock
# file where you *can* dig them out - and the CI configuration does.
"nixpkgs-22_11" = {
url = github:NixOS/nixpkgs?ref=nixos-22.11;
};
"nixpkgs-23_05" = {
url = github:NixOS/nixpkgs?ref=release-23.05;
};
2023-07-19 21:29:50 +00:00
# We depend on a very new python-cryptography which is not yet available
# from any release branch of nixpkgs. However, it is contained in a PR
# currently up for review. Point our nixpkgs at that for now.
"nixpkgs-unstable" = {
2023-07-19 21:29:50 +00:00
url = github:NixOS/nixpkgs?ref=pull/244135/head;
};
# Point the default nixpkgs at one of those. This avoids having getting a
# _third_ package set involved and gives a way to provide what should be a
# working experience by default (that is, if nixpkgs doesn't get
# overridden).
nixpkgs.follows = "nixpkgs-unstable";
# Also get flake-utils for simplified multi-system definitions.
flake-utils = {
url = github:numtide/flake-utils;
};
# And get a helper that lets us easily continue to provide a default.nix.
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
};
outputs = { self, nixpkgs, flake-utils, ... }:
{
# Expose an overlay which adds our version of Tahoe-LAFS to the Python
# package sets we specify, as well as all of the correct versions of its
# dependencies.
#
# We will also use this to define some other outputs since it gives us
# the most succinct way to get a working Tahoe-LAFS package.
overlays.default = import ./nix/overlay.nix;
} // (flake-utils.lib.eachDefaultSystem (system: let
2023-07-19 18:27:28 +00:00
# The package set for this system architecture.
pkgs = import nixpkgs {
inherit system;
# And include our Tahoe-LAFS package in that package set.
overlays = [ self.overlays.default ];
};
2023-07-19 18:27:28 +00:00
# pythonVersions :: [string]
#
# The version strings for the Python runtimes we'll work with.
pythonVersions =
let
# Match attribute names that look like a Python derivation - CPython
# or PyPy. We take care to avoid things like "python-foo" and
# "python3Full-unittest" though. We only want things like "pypy38"
# or "python311".
2023-07-19 18:27:28 +00:00
nameMatches = name: null != builtins.match "(python|pypy)3[[:digit:]]{0,2}" name;
2023-07-19 18:27:28 +00:00
# Sometimes an old version is left in the package set as an error
# saying something like "we remove this". Make sure we whatever we
# found by name evaluates without error, too.
notError = drv: (builtins.tryEval drv).success;
in
# Discover all of the Python runtime derivations by inspecting names
# and filtering out derivations with errors.
builtins.attrNames (
pkgs.lib.attrsets.filterAttrs
(name: drv: nameMatches name && notError drv)
pkgs
);
# defaultPyVersion :: string
#
# An element of pythonVersions which we'll use for the default package.
2023-07-19 18:27:28 +00:00
defaultPyVersion = "python3";
2023-07-19 18:27:28 +00:00
# pythons :: [derivation]
#
# Retrieve the actual Python package for each configured version. We
# already applied our overlay to pkgs so our packages will already be
# available.
pythons = builtins.map (pyVer: pkgs.${pyVer}) pythonVersions;
2023-07-19 18:27:28 +00:00
# packageName :: string -> string
#
# Construct the Tahoe-LAFS package name for the given Python runtime.
packageName = pyVersion: "${pyVersion}-tahoe-lafs";
# string -> string
#
# Construct the unit test application name for the given Python runtime.
unitTestName = pyVersion: "${pyVersion}-unittest";
2023-07-04 18:39:26 +00:00
# (string -> a) -> (string -> b) -> string -> attrset a b
#
# Make a singleton attribute set from the result of two functions.
singletonOf = f: g: x: { ${f x} = g x; };
2023-07-19 18:27:28 +00:00
# makeRuntimeEnv :: string -> derivation
#
# Create a derivation that includes a Python runtime, Tahoe-LAFS, and
# all of its dependencies.
2023-07-04 18:39:26 +00:00
makeRuntimeEnv = singletonOf packageName makeRuntimeEnv';
makeRuntimeEnv' = pyVersion: (pkgs.${pyVersion}.withPackages (ps: with ps;
[ tahoe-lafs ] ++
tahoe-lafs.passthru.extras.i2p ++
tahoe-lafs.passthru.extras.tor
)).overrideAttrs (old: {
name = packageName pyVersion;
});
2023-07-19 18:27:28 +00:00
# makeTestEnv :: string -> derivation
#
# Create a derivation that includes a Python runtime, Tahoe-LAFS, and
# all of its dependencies.
2023-07-04 18:39:26 +00:00
makeTestEnv = pyVersion: (pkgs.${pyVersion}.withPackages (ps: with ps;
2023-07-04 18:36:46 +00:00
[ tahoe-lafs ] ++
tahoe-lafs.passthru.extras.i2p ++
tahoe-lafs.passthru.extras.tor ++
tahoe-lafs.passthru.extras.unittest
)).overrideAttrs (old: {
name = packageName pyVersion;
});
in {
2023-07-19 18:27:28 +00:00
# A package set with out overlay on it.
legacyPackages = pkgs;
2023-07-19 18:27:28 +00:00
# The flake's package outputs. We'll define one version of the package
# for each version of Python we could find. We'll also point the
# flake's "default" package at the derivation corresponding to the
# default Python version we defined above. The package consists of a
# Python environment with Tahoe-LAFS available to it.
packages = with pkgs.lib;
foldr mergeAttrs {} ([
{ default = self.packages.${system}.${packageName defaultPyVersion}; }
] ++ (builtins.map makeRuntimeEnv pythonVersions)
++ (builtins.map (singletonOf unitTestName makeTestEnv) pythonVersions)
);
2023-07-19 18:27:28 +00:00
# The flake's app outputs. We'll define a version of an app for running
# the test suite for each version of Python we could find. We'll also
# define a version of an app for running the "tahoe" command-line
# entrypoint for each version of Python we could find.
apps =
let
2023-07-19 18:27:28 +00:00
# writeScript :: string -> string -> path
#
# Write a shell program to a file so it can be run later.
#
# We avoid writeShellApplication here because it has ghc as a
# dependency but ghc has Python as a dependency and our Python
2023-07-19 18:27:28 +00:00
# package override triggers a rebuild of ghc and many Haskell
# packages which takes a looong time.
writeScript = name: text:
let script = pkgs.writeShellScript name text;
in "${script}";
2023-07-19 18:27:28 +00:00
# makeTahoeApp :: string -> attrset
#
# A helper function to define the Tahoe-LAFS runtime entrypoint for
# a certain Python runtime.
makeTahoeApp = pyVersion: {
"tahoe-${pyVersion}" = {
type = "app";
program =
writeScript "tahoe"
''
${makeRuntimeEnv' pyVersion}/bin/tahoe "$@"
'';
};
};
2023-07-19 18:27:28 +00:00
# makeUnitTestsApp :: string -> attrset
#
# A helper function to define the Tahoe-LAFS unit test entrypoint
# for a certain Python runtime.
makeUnitTestsApp = pyVersion: {
"${unitTestName pyVersion}" = {
type = "app";
program =
writeScript "unit-tests"
''
export TAHOE_LAFS_HYPOTHESIS_PROFILE=ci
2023-07-04 18:39:26 +00:00
${makeTestEnv pyVersion}/bin/python -m twisted.trial "$@"
'';
};
};
in
with pkgs.lib;
2023-07-19 18:27:28 +00:00
# Merge a default app definition with the rest of the apps.
foldr mergeAttrs
{ default = self.apps.${system}."tahoe-python3"; }
(
(builtins.map makeUnitTestsApp pythonVersions) ++
(builtins.map makeTahoeApp pythonVersions)
);
}));
}