Merge pull request 'check jsonschema comaptibility for all clan modules' (#1280) from schema into main
All checks were successful
buildbot/nix-build .#checks.aarch64-darwin.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-test-backup Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-installer Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-age Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-bash Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-e2fsprogs Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-fakeroot Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-git Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-nix Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-openssh Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.11-mypy" Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.11-qemu" Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-vm-manager Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-default Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-cli Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-jsonschema-example-valid Build done.
buildbot/nix-build .#checks.x86_64-linux.check-for-breakpoints Build done.
buildbot/nix-build .#checks.x86_64-linux.deltachat Build done.
buildbot/nix-build .#checks.x86_64-linux.container Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-rsync Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sops Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sshpass Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-tor Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-zbar Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-with-core Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-without-core Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-vm-manager-no-breakpoints Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-vm-manager-pytest Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.borgbackup Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-vm-manager Build done.
buildbot/nix-build .#checks.x86_64-linux.package-deploy-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-cli Build done.
buildbot/nix-build .#checks.x86_64-linux.package-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-default Build done.
buildbot/nix-build .#checks.x86_64-linux.package-impure-checks Build done.
buildbot/nix-build .#checks.x86_64-linux.matrix-synapse Build done.
buildbot/nix-build .#checks.x86_64-linux.flash Build done.
buildbot/nix-build .#checks.x86_64-linux.package-merge-after-ci Build done.
buildbot/nix-build .#checks.x86_64-linux.package-moonlight-sunshine-accept Build done.
buildbot/nix-build .#checks.x86_64-linux.package-pending-reviews Build done.
buildbot/nix-build .#checks.x86_64-linux.package-tea-create-pr Build done.
buildbot/nix-build .#checks.x86_64-linux.package-wayland-proxy-virtwl Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zerotier-members Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zerotierone Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-jsonschema-nix-unit-tests Build done.
buildbot/nix-build .#checks.x86_64-linux.renderClanOptions Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-function-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.x86_64-linux.secrets Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.treefmt Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.test-backups Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.package-install-iso Build done.
buildbot/nix-build .#checks.x86_64-linux.syncthing Build done.
buildbot/nix-build .#checks.x86_64-linux.wayland-proxy-virtwl Build done.
buildbot/nix-build .#checks.x86_64-linux.test-installation Build done.
buildbot/nix-eval Build done.
checks / checks (push) Successful in 1m0s
checks / checks-impure (push) Successful in 2m20s

This commit is contained in:
clan-bot 2024-05-01 21:18:33 +00:00
commit f231f1e0c7
13 changed files with 134 additions and 81 deletions

View File

@ -46,7 +46,6 @@
syncthing = import ./syncthing nixosTestArgs;
wayland-proxy-virtwl = import ./wayland-proxy-virtwl nixosTestArgs;
};
schemaTests = pkgs.callPackages ./schemas.nix { inherit self; };
flakeOutputs =
lib.mapAttrs' (
@ -58,7 +57,7 @@
self'.legacyPackages.homeConfigurations or { }
);
in
{ inherit renderClanOptions; } // nixosTests // schemaTests // flakeOutputs;
{ inherit renderClanOptions; } // nixosTests // flakeOutputs;
legacyPackages = {
nixosTests =
let

View File

@ -1,48 +0,0 @@
{
self,
runCommand,
check-jsonschema,
pkgs,
lib,
...
}:
let
clanModules.clanCore = self.nixosModules.clanCore;
baseModule = {
imports = (import (pkgs.path + "/nixos/modules/module-list.nix")) ++ [
{
nixpkgs.hostPlatform = "x86_64-linux";
clanCore.clanName = "dummy";
}
];
};
optionsFromModule =
module:
let
evaled = lib.evalModules {
modules = [
module
baseModule
];
};
in
evaled.options.clan;
clanModuleSchemas = lib.mapAttrs (
_: module: self.lib.jsonschema.parseOptions (optionsFromModule module)
) clanModules;
mkTest =
name: schema:
runCommand "schema-${name}" { } ''
${check-jsonschema}/bin/check-jsonschema \
--check-metaschema ${builtins.toFile "schema-${name}" (builtins.toJSON schema)}
touch $out
'';
in
lib.mapAttrs' (name: schema: {
name = "schema-${name}";
value = mkTest name schema;
}) clanModuleSchemas

View File

@ -21,7 +21,6 @@
root-password = ./root-password;
thelounge = ./thelounge.nix;
vm-user = ./vm-user.nix;
waypipe = ./waypipe.nix;
xfce = ./xfce.nix;
xfce-vm = ./xfce-vm.nix;
zt-tcp-relay = ./zt-tcp-relay.nix;

View File

@ -34,6 +34,10 @@
'';
type = lib.types.listOf lib.types.str;
default = [ ];
example = [
"folder1"
"folder2"
];
};
};

View File

@ -68,7 +68,6 @@ nav:
- reference/clanModules/syncthing.md
- reference/clanModules/thelounge.md
- reference/clanModules/vm-user.md
- reference/clanModules/waypipe.md
- reference/clanModules/xfce-vm.md
- reference/clanModules/xfce.md
- reference/clanModules/zt-tcp-relay.md

View File

@ -38,20 +38,7 @@ let
) clanModules;
clanModulesReadmes = builtins.mapAttrs (
module_name: _module:
let
readme = "${self}/clanModules/${module_name}/README.md";
readmeContents =
if
builtins.trace "Trying to get Module README.md for ${module_name} from ${readme}"
# TODO: Edge cases
(builtins.pathExists readme)
then
(builtins.readFile readme)
else
null;
in
readmeContents
module_name: _module: self.lib.modules.getDescription module_name
) clanModules;
# clanCore docs

View File

@ -6,6 +6,6 @@
}:
{
jsonschema = import ./jsonschema { inherit lib; };
modules = import ./description.nix { inherit clan-core; };
buildClan = import ./build-clan { inherit clan-core lib nixpkgs; };
}

19
lib/description.nix Normal file
View File

@ -0,0 +1,19 @@
{ clan-core, ... }:
{
getDescription =
modulename:
let
readme = "${clan-core}/clanModules/${modulename}/README.md";
readmeContents =
if
builtins.trace "Trying to get Module README.md for ${modulename} from ${readme}"
# TODO: Edge cases
(builtins.pathExists readme)
then
(builtins.readFile readme)
else
null;
in
readmeContents;
}

View File

@ -17,7 +17,10 @@ let
location: ${lib.concatStringsSep "." option.loc}
'';
isExcludedOption = option: (lib.elem (option.type.name or null) excludedTypes);
# Exclude the option if it's type is in the excludedTypes list
# or if the option has a defaultText attribute
isExcludedOption =
option: ((lib.elem (option.type.name or null) excludedTypes) || (option ? defaultText));
filterExcluded = lib.filter (opt: !isExcludedOption opt);
@ -67,6 +70,10 @@ rec {
option:
let
default = lib.optionalAttrs (option ? default) { inherit (option) default; };
example = lib.optionalAttrs (option ? example) {
examples =
if (builtins.typeOf option.example) == "list" then option.example else [ option.example ];
};
description = lib.optionalAttrs (option ? description) {
description = option.description.text or option.description;
};
@ -93,7 +100,7 @@ rec {
];
optionsList = filterExcluded optionsList';
in
default // description // { anyOf = map parseOption optionsList; }
default // example // description // { anyOf = map parseOption optionsList; }
# handle nested options (not a submodule)
else if !option ? _type then
@ -116,6 +123,7 @@ rec {
};
in
default
// example
// description
// {
anyOf = [
@ -128,63 +136,77 @@ rec {
option.type.name == "bool"
# return jsonschema property definition for bool
then
default // description // { type = "boolean"; }
default // example // description // { type = "boolean"; }
# parse float
else if
option.type.name == "float"
# return jsonschema property definition for float
then
default // description // { type = "number"; }
default // example // description // { type = "number"; }
# parse int
else if
(option.type.name == "int" || option.type.name == "positiveInt")
# return jsonschema property definition for int
then
default // description // { type = "integer"; }
default // example // description // { type = "integer"; }
# TODO: Add support for intMatching in jsonschema
# parse port type aka. "unsignedInt16"
else if option.type.name == "unsignedInt16" then
default // example // description // { type = "integer"; }
# parse string
else if
option.type.name == "str"
# return jsonschema property definition for string
then
default // description // { type = "string"; }
default // example // description // { type = "string"; }
# TODO: Add support for stringMatching in jsonschema
# parse stringMatching
else if lib.strings.hasPrefix "strMatching" option.type.name then
default // example // description // { type = "string"; }
# TODO: Add support for separatedString in jsonschema
else if lib.strings.hasPrefix "separatedString" option.type.name then
default // example // description // { type = "string"; }
# parse string
else if
option.type.name == "path"
# return jsonschema property definition for path
then
default // description // { type = "string"; }
default // example // description // { type = "string"; }
# parse anything
else if
option.type.name == "anything"
# return jsonschema property definition for anything
then
default // description // { type = allBasicTypes; }
default // example // description // { type = allBasicTypes; }
# parse unspecified
else if
option.type.name == "unspecified"
# return jsonschema property definition for unspecified
then
default // description // { type = allBasicTypes; }
default // example // description // { type = allBasicTypes; }
# parse raw
else if
option.type.name == "raw"
# return jsonschema property definition for raw
then
default // description // { type = allBasicTypes; }
default // example // description // { type = allBasicTypes; }
# parse enum
else if
option.type.name == "enum"
# return jsonschema property definition for enum
then
default // description // { enum = option.type.functor.payload; }
default // example // description // { enum = option.type.functor.payload; }
# parse listOf submodule
else if
@ -192,6 +214,7 @@ rec {
# return jsonschema property definition for listOf submodule
then
default
// example
// description
// {
type = "array";
@ -211,6 +234,7 @@ rec {
};
in
default
// example
// description
// {
type = "array";
@ -222,7 +246,7 @@ rec {
(option.type.name == "listOf") && (option.type.functor.wrapped.name == "unspecified")
# return jsonschema property definition for list
then
default // description // { type = "array"; }
default // example // description // { type = "array"; }
# parse attrsOf submodule
else if
@ -230,6 +254,7 @@ rec {
# return jsonschema property definition for attrsOf submodule
then
default
// example
// description
// {
type = "object";
@ -242,6 +267,7 @@ rec {
# return jsonschema property definition for attrs
then
default
// example
// description
// {
type = "object";
@ -262,6 +288,7 @@ rec {
};
in
default
// example
// description
// {
type = "object";

View File

@ -22,8 +22,8 @@
'';
};
clanDir = lib.mkOption {
type = lib.types.either lib.types.path lib.types.str;
default = ".";
type = lib.types.path;
default = ./.;
description = ''
the location of the flake repo, used to calculate the location of facts and secrets
'';

View File

@ -4,6 +4,7 @@
./clan-cli/flake-module.nix
./clan-vm-manager/flake-module.nix
./installer/flake-module.nix
./schemas/flake-module.nix
];
perSystem =

View File

@ -0,0 +1,66 @@
{ self, ... }:
{
perSystem =
{ pkgs, lib, ... }:
let
clanModules = self.clanModules;
# Uncomment if you only want one module to be available
# clanModules = {
# syncthing = self.clanModules.syncthing;
# };
baseModule = {
imports = (import (pkgs.path + "/nixos/modules/module-list.nix")) ++ [
{
nixpkgs.hostPlatform = "x86_64-linux";
clanCore.clanName = "dummy";
}
];
};
optionsFromModule =
modulename: module:
let
evaled = lib.evalModules {
modules = [
module
baseModule
self.nixosModules.clanCore
];
};
in
if (evaled.options.clan ? "${modulename}") then evaled.options.clan.${modulename} else { };
clanModuleSchemas = lib.mapAttrs (
modulename: module: self.lib.jsonschema.parseOptions (optionsFromModule modulename module)
) clanModules;
clanModuleFunctionSchemas = lib.mapAttrsFlatten (modulename: module: {
name = modulename;
description = self.lib.modules.getDescription modulename;
parameters = self.lib.jsonschema.parseOptions (optionsFromModule modulename module);
}) clanModules;
in
rec {
checks = {
module-schema = pkgs.runCommand "schema-checks" { } ''
${pkgs.check-jsonschema}/bin/check-jsonschema \
--check-metaschema ${packages.module-schema}
touch $out
'';
};
packages = {
module-schema = pkgs.runCommand "jsonschema" { } ''
MSCHEMA=${builtins.toFile "module-schemas.json" (builtins.toJSON clanModuleSchemas)}
cp "$MSCHEMA" $out
'';
function-schema = pkgs.runCommand "function-schema" { } ''
FSCHEMA=${builtins.toFile "function-schemas.json" (builtins.toJSON clanModuleFunctionSchemas)}
cp "$FSCHEMA" $out
'';
};
};
}