summaryrefslogtreecommitdiffstats
path: root/flake.nix
blob: 88ae3d9ffc79fc066d5fdd824b378c427e230968 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{
  description = "A complete and Simple Nixos Mailserver";

  inputs = {
    flake-compat = {
      url = "github:edolstra/flake-compat";
      flake = false;
    };
    utils.url = "github:numtide/flake-utils";
    nixpkgs.url = "flake:nixpkgs/nixos-unstable";
    nixpkgs-23_05.url = "flake:nixpkgs/nixos-23.05";
    nixpkgs-23_11.url = "flake:nixpkgs/nixos-23.11";
    blobs = {
      url = "gitlab:simple-nixos-mailserver/blobs";
      flake = false;
    };
  };

  outputs = { self, utils, blobs, nixpkgs, nixpkgs-23_05, nixpkgs-23_11, ... }: let
    lib = nixpkgs.lib;
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};
    releases = [
      {
        name = "unstable";
        pkgs = nixpkgs.legacyPackages.${system};
      }
      {
        name = "23.05";
        pkgs = nixpkgs-23_05.legacyPackages.${system};
      }
      {
        name = "23.11";
        pkgs = nixpkgs-23_11.legacyPackages.${system};
      }
    ];
    testNames = [
      "internal"
      "external"
      "clamav"
      "multiple"
      "ldap"
    ];
    genTest = testName: release: {
      "name"= "${testName}-${builtins.replaceStrings ["."] ["_"] release.name}";
      "value"= import (./tests/. + "/${testName}.nix") {
        pkgs = release.pkgs;
        inherit blobs;
      };
    };
    # Generate an attribute set such as
    # {
    #   external-unstable = <derivation>;
    #   external-21_05 = <derivation>;
    #   ...
    # }
    allTests = lib.listToAttrs (
      lib.flatten (map (t: map (r: genTest t r) releases) testNames));

    mailserverModule = import ./.;

    # Generate a MarkDown file describing the options of the NixOS mailserver module
    optionsDoc = let
      eval = lib.evalModules {
        modules = [
          mailserverModule
          {
            _module.check = false;
            mailserver = {
              fqdn = "mx.example.com";
              domains = [
                "example.com"
              ];
              dmarcReporting = {
                organizationName = "Example Corp";
                domain = "example.com";
              };
            };
          }
        ];
      };
      options = builtins.toFile "options.json" (builtins.toJSON
        (lib.filter (opt: opt.visible && !opt.internal && lib.head opt.loc == "mailserver")
          (lib.optionAttrSetToDocList eval.options)));
    in pkgs.runCommand "options.md" { buildInputs = [pkgs.python3Minimal]; } ''
      echo "Generating options.md from ${options}"
      python ${./scripts/generate-options.py} ${options} > $out
    '';

    documentation = pkgs.stdenv.mkDerivation {
      name = "documentation";
      src = lib.sourceByRegex ./docs ["logo\\.png" "conf\\.py" "Makefile" ".*\\.rst"];
      buildInputs = [(
        pkgs.python3.withPackages (p: with p; [
          sphinx
          sphinx_rtd_theme
          myst-parser
          linkify-it-py
        ])
      )];
      buildPhase = ''
        cp ${optionsDoc} options.md
        # Workaround for https://github.com/sphinx-doc/sphinx/issues/3451
        unset SOURCE_DATE_EPOCH
        make html
      '';
      installPhase = ''
        cp -Tr _build/html $out
      '';
    };

  in {
    nixosModules = rec {
      mailserver = mailserverModule;
      default = mailserver;
    };
    nixosModule = self.nixosModules.default; # compatibility
    hydraJobs.${system} = allTests // {
      inherit documentation;
    };
    checks.${system} = allTests;
    packages.${system} = {
      inherit optionsDoc documentation;
    };
    devShells.${system}.default = pkgs.mkShell {
      inputsFrom = [ documentation ];
      packages = with pkgs; [
        clamav
      ];
    };
    devShell.${system} = self.devShells.${system}.default; # compatibility
  };
}