default.nix

  1{
  2  pins ? import ../.npins,
  3  pkgs ? import (import ../.npins).nixpkgs { },
  4  lib ? pkgs.lib,
  5  excludes ? [ ],
  6  src ? (
  7    pkgs.nix-gitignore.gitignoreRecursiveSource [
  8      ../.gitignore
  9      ../webui/.gitignore
 10      ../webui/src/.gitignore
 11    ] ../.
 12  ),
 13}:
 14let
 15  checksDir = ./checks;
 16
 17  fmt =
 18    let
 19      treefmtEval = (import pins.treefmt).evalModule pkgs {
 20        projectRootFile = ".git-blame-ignore-revs";
 21
 22        # be a little more verbsoe to see progress
 23        settings.verbose = 1;
 24
 25        # be a little more quiet if unmatched files are encountered (by default
 26        # this is set to info, which always emits every single unmatched file)
 27        settings.on-unmatched = "debug";
 28
 29        # files and directories that should be excluded
 30        settings.global.excludes =
 31          lib.lists.unique [
 32            "*.graphql"
 33            "*.png"
 34            "*.svg"
 35            "*.txt"
 36            ".npins/*"
 37            "Makefile"
 38            "misc/completion/*/*"
 39            "webui/node_modules/*"
 40            "webui/build"
 41
 42            # generated files
 43            "CHANGELOG.md"
 44            "doc/man/*.1" # via //doc:generate.go
 45            "doc/md/*" # via //doc:generate.go
 46          ]
 47          ++ excludes;
 48
 49        # FORMATTERS
 50        #######################################################################
 51
 52        programs.gofmt.enable = true;
 53        programs.shfmt.enable = true;
 54        programs.zizmor.enable = true;
 55        programs.nixf-diagnose.enable = true;
 56        programs.statix.enable = true;
 57
 58        programs.mdformat = {
 59          enable = true;
 60
 61          plugins =
 62            ps: with ps; [
 63              # add support for github flavored markdown
 64              mdformat-gfm
 65              mdformat-gfm-alerts
 66
 67              # add the following comment before running the formatter to
 68              # generate a table of contents in markdown files:
 69              #     <!-- mdformat-toc start -->
 70              mdformat-toc
 71            ];
 72
 73          settings = {
 74            end-of-line = "lf";
 75            number = true;
 76            wrap = 80;
 77          };
 78        };
 79
 80        programs.nixfmt = {
 81          enable = true;
 82          strict = true;
 83        };
 84
 85        # programs.biome = {
 86        #   enable = true;
 87        #   settings.formatter = {
 88        #     useEditorconfig = true;
 89        #   };
 90        #   settings.javascript.formatter = {
 91        #     quoteStyle = "single";
 92        #     semicolons = "always";
 93        #   };
 94        #   settings.json.formatter.enabled = false;
 95        # };
 96        # settings.formatter.biome.excludes = [ "*.min.js" ];
 97
 98        programs.keep-sorted.enable = true;
 99
100        programs.yamlfmt = {
101          enable = true;
102
103          settings.formatter = {
104            eof_newline = true;
105            include_document_start = true;
106            retain_line_breaks_single = true;
107            trim_trailing_whitespace = true;
108          };
109        };
110
111        settings.formatter.markdown-code-runner = {
112          command = lib.getExe pkgs.markdown-code-runner;
113          options =
114            let
115              config = pkgs.writers.writeTOML "markdown-code-runner-config" {
116                presets.nixfmt = {
117                  language = "nix";
118                  command = [ (lib.getExe pkgs.nixfmt) ];
119                };
120
121                presets.go = {
122                  language = "go";
123                  command = [
124                    "${pkgs.go}/bin/gofmt"
125                    "{file}"
126                  ];
127                  input_mode = "file";
128                };
129
130                presets.bash = {
131                  language = "bash";
132                  command = [
133                    (lib.getExe pkgs.shfmt)
134                    "--binary-next-line"
135                    "--case-indent"
136                    "--simplify"
137                    "--space-redirects"
138                    "-"
139                  ];
140                };
141              };
142            in
143            [ "--config=${config}" ];
144          includes = [ "*.md" ];
145          excludes = [ "doc/md/*" ];
146        };
147      };
148
149      fs = lib.fileset;
150      checkFiles = fs.toSource {
151        root = ../.;
152        fileset = fs.difference ../. (fs.maybeMissing ../.git);
153      };
154    in
155    {
156      shell = treefmtEval.config.build.devShell;
157      check = treefmtEval.config.build.check checkFiles;
158    };
159in
160{
161  # the treefmt shell is exported because the treefmt package is added to the
162  # development shell via //:shell.nix
163  inherit (fmt) shell;
164
165  # checks is an attrset built from aggregating all of the non-golang tests
166  # (defined in //ci/checks). these are tests for things like formatting and
167  # spelling.
168  checks = {
169    fmt = fmt.check;
170  }
171  // lib.listToAttrs (
172    map
173      (file: {
174        name = lib.removeSuffix ".nix" file;
175        value = import (checksDir + "/${file}") { inherit pkgs src; };
176      })
177      (
178        builtins.attrNames (
179          lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name) (
180            builtins.readDir checksDir
181          )
182        )
183      )
184  );
185}