nixos/make-options-doc: treat missing descriptions as errors by default

this partially solves the problem of "missing description" warnings of the
options doc build being lost by nix build, at the cost of failing builds that
previously ran. an option to disable this behaviour is provided.
This commit is contained in:
pennae 2021-12-18 19:37:41 +01:00
parent 1301bdb185
commit 50954ad1c5
4 changed files with 43 additions and 8 deletions

View file

@ -1,4 +1,13 @@
{ pkgs, options, config, version, revision, extraSources ? [], baseOptionsJSON ? null, prefix ? ../../.. }: { pkgs
, options
, config
, version
, revision
, extraSources ? []
, baseOptionsJSON ? null
, warningsAreErrors ? true
, prefix ? ../../..
}:
with pkgs; with pkgs;
@ -15,7 +24,7 @@ let
stripAnyPrefixes = lib.flip (lib.foldr lib.removePrefix) prefixesToStrip; stripAnyPrefixes = lib.flip (lib.foldr lib.removePrefix) prefixesToStrip;
optionsDoc = buildPackages.nixosOptionsDoc { optionsDoc = buildPackages.nixosOptionsDoc {
inherit options revision baseOptionsJSON; inherit options revision baseOptionsJSON warningsAreErrors;
transformOptions = opt: opt // { transformOptions = opt: opt // {
# Clean up declaration sites to not refer to the NixOS source tree. # Clean up declaration sites to not refer to the NixOS source tree.
declarations = map stripAnyPrefixes opt.declarations; declarations = map stripAnyPrefixes opt.declarations;

View file

@ -25,6 +25,9 @@
# used to split the options doc build into a static part (nixos/modules) and a dynamic part # used to split the options doc build into a static part (nixos/modules) and a dynamic part
# (non-nixos modules imported via configuration.nix, other module sources). # (non-nixos modules imported via configuration.nix, other module sources).
, baseOptionsJSON ? null , baseOptionsJSON ? null
# instead of printing warnings for eg options with missing descriptions (which may be lost
# by nix build unless -L is given), emit errors instead and fail the build
, warningsAreErrors ? true
}: }:
let let
@ -121,6 +124,7 @@ in rec {
then "cp $options $dst/options.json" then "cp $options $dst/options.json"
else '' else ''
${pkgs.python3Minimal}/bin/python ${./mergeJSON.py} \ ${pkgs.python3Minimal}/bin/python ${./mergeJSON.py} \
${lib.optionalString warningsAreErrors "--warnings-are-errors"} \
${baseOptionsJSON} $options \ ${baseOptionsJSON} $options \
> $dst/options.json > $dst/options.json
'' ''

View file

@ -41,8 +41,10 @@ def unpivot(options: Dict[Key, Option]) -> Dict[str, JSON]:
result[opt.name] = opt.value result[opt.name] = opt.value
return result return result
options = pivot(json.load(open(sys.argv[1], 'r'))) warningsAreErrors = sys.argv[1] == "--warnings-are-errors"
overrides = pivot(json.load(open(sys.argv[2], 'r'))) optOffset = 1 if warningsAreErrors else 0
options = pivot(json.load(open(sys.argv[1 + optOffset], 'r')))
overrides = pivot(json.load(open(sys.argv[2 + optOffset], 'r')))
# fix up declaration paths in lazy options, since we don't eval them from a full nixpkgs dir # fix up declaration paths in lazy options, since we don't eval them from a full nixpkgs dir
for (k, v) in options.items(): for (k, v) in options.items():
@ -65,10 +67,20 @@ for (k, v) in overrides.items():
cur[ok] = ov cur[ok] = ov
# check that every option has a description # check that every option has a description
# TODO: nixos-rebuild with flakes may hide the warning, maybe turn on -L by default for those? hasWarnings = False
for (k, v) in options.items(): for (k, v) in options.items():
if v.value.get('description', None) is None: if v.value.get('description', None) is None:
print(f"\x1b[1;31mwarning: option {v.name} has no description\x1b[0m", file=sys.stderr) severity = "error" if warningsAreErrors else "warning"
hasWarnings = True
print(f"\x1b[1;31m{severity}: option {v.name} has no description\x1b[0m", file=sys.stderr)
v.value['description'] = "This option has no description." v.value['description'] = "This option has no description."
if hasWarnings and warningsAreErrors:
print(
"\x1b[1;31m" +
"Treating warnings as errors. Set documentation.nixos.options.warningsAreErrors " +
"to false to ignore these warnings." +
"\x1b[0m",
file=sys.stderr)
sys.exit(1)
json.dump(unpivot(options), fp=sys.stdout) json.dump(unpivot(options), fp=sys.stdout)

View file

@ -15,7 +15,7 @@ let
f = import m; f = import m;
instance = f (mapAttrs (n: _: abort "evaluating ${n} for `meta` failed") (functionArgs f)); instance = f (mapAttrs (n: _: abort "evaluating ${n} for `meta` failed") (functionArgs f));
in in
cfg.nixos.splitOptionDocBuild cfg.nixos.options.splitBuild
&& builtins.isPath m && builtins.isPath m
&& isFunction f && isFunction f
&& instance ? options && instance ? options
@ -101,6 +101,7 @@ let
exit 1 exit 1
} >&2 } >&2
''; '';
inherit (cfg.nixos.options) warningsAreErrors;
}; };
@ -256,7 +257,7 @@ in
''; '';
}; };
nixos.splitOptionDocBuild = mkOption { nixos.options.splitBuild = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = '' description = ''
@ -266,6 +267,15 @@ in
''; '';
}; };
nixos.options.warningsAreErrors = mkOption {
type = types.bool;
default = true;
description = ''
Treat warning emitted during the option documentation build (eg for missing option
descriptions) as errors.
'';
};
nixos.includeAllModules = mkOption { nixos.includeAllModules = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;