mirror of
https://github.com/moons-14/dotfiles.git
synced 2026-10-06 06:08:11 +09:00
nix registory
This commit is contained in:
@@ -24,4 +24,8 @@
|
||||
|
||||
!/hosts/
|
||||
|
||||
!/libs/
|
||||
|
||||
!/modules/
|
||||
|
||||
!/tests/
|
||||
|
||||
Generated
+22
@@ -570,6 +570,27 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1783744694,
|
||||
"narHash": "sha256-2cp6N3rrwnGYLTx9l6N+NI+kwrCWxvJUbj5WJhvB29A=",
|
||||
"owner": "nix-darwin",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "c3e90c89649b07d1a96e4b9dd6cd0d6e44b91a74",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-darwin",
|
||||
"ref": "nix-darwin-26.05",
|
||||
"repo": "nix-darwin",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-index-database": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -962,6 +983,7 @@
|
||||
"lanzaboote": "lanzaboote",
|
||||
"llm-agents": "llm-agents",
|
||||
"niri-flake": "niri-flake",
|
||||
"nix-darwin": "nix-darwin",
|
||||
"nix-index-database": "nix-index-database",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixos-wsl": "nixos-wsl",
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
nix-darwin = {
|
||||
url = "github:nix-darwin/nix-darwin/nix-darwin-26.05";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# Hardware / Platform
|
||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||
nixos-wsl.url = "github:nix-community/NixOS-WSL";
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
imports = [
|
||||
./formatter.nix
|
||||
./git-hooks.nix
|
||||
./registry.nix
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
dotfilesLib = import ../libs {
|
||||
inherit inputs lib;
|
||||
root = ../.;
|
||||
};
|
||||
hostSpecsPath = ../hosts/default.nix;
|
||||
hostSpecs =
|
||||
if builtins.pathExists hostSpecsPath then
|
||||
let
|
||||
value = import hostSpecsPath;
|
||||
in
|
||||
if builtins.isFunction value then
|
||||
value (
|
||||
builtins.intersectAttrs (builtins.functionArgs value) {
|
||||
inherit inputs lib;
|
||||
}
|
||||
)
|
||||
else
|
||||
value
|
||||
else
|
||||
{ };
|
||||
configurations = dotfilesLib.hosts.mkConfigurations hostSpecs;
|
||||
in
|
||||
{
|
||||
flake = {
|
||||
inherit (configurations) darwinConfigurations nixosConfigurations;
|
||||
lib = dotfilesLib;
|
||||
};
|
||||
|
||||
perSystem =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
checks.registry = import ../tests/registry.nix {
|
||||
inherit inputs lib pkgs;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
inputs,
|
||||
lib ? inputs.nixpkgs.lib,
|
||||
root,
|
||||
}:
|
||||
let
|
||||
registry = import ./registry.nix {
|
||||
inherit inputs lib;
|
||||
modulesRoot = root + "/modules";
|
||||
};
|
||||
hosts = import ./hosts.nix {
|
||||
inherit inputs lib registry;
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit hosts registry;
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
registry,
|
||||
}:
|
||||
let
|
||||
ensure =
|
||||
condition: message: value:
|
||||
if condition then value else throw "host registry: ${message}";
|
||||
|
||||
isLinux = system: lib.hasSuffix "-linux" system;
|
||||
isDarwin = system: lib.hasSuffix "-darwin" system;
|
||||
|
||||
hostFile =
|
||||
spec: name:
|
||||
let
|
||||
path = spec.path + "/${name}";
|
||||
in
|
||||
if builtins.pathExists path then path else null;
|
||||
|
||||
selectedUnits =
|
||||
spec:
|
||||
[ "users.${spec.user}" ]
|
||||
++ map (name: "profiles.${name}") (spec.profiles or [ ])
|
||||
++ map (name: "applications.${name}") (spec.applications or [ ])
|
||||
++ (spec.units or [ ]);
|
||||
|
||||
validateSpec =
|
||||
name: spec:
|
||||
ensure (builtins.isAttrs spec) "${name}: host specification must be an attribute set" (
|
||||
ensure (spec ? system && builtins.isString spec.system) "${name}: system is required" (
|
||||
ensure (isLinux spec.system || isDarwin spec.system)
|
||||
"${name}: unsupported system '${spec.system}'; expected a Linux NixOS or Darwin system"
|
||||
(
|
||||
ensure (spec ? user && builtins.isString spec.user && spec.user != "") "${name}: user is required" (
|
||||
ensure (spec ? path && builtins.pathExists spec.path)
|
||||
"${name}: path must name an existing host directory"
|
||||
(
|
||||
ensure
|
||||
(lib.all
|
||||
(field: builtins.isList (spec.${field} or [ ]) && lib.all builtins.isString (spec.${field} or [ ]))
|
||||
[
|
||||
"profiles"
|
||||
"applications"
|
||||
"units"
|
||||
]
|
||||
)
|
||||
"${name}: profiles, applications, and units must be lists of strings"
|
||||
(ensure (builtins.isBool (spec.homeManager or true)) "${name}: homeManager must be a boolean" spec)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
mkSpecialArgs = name: spec: {
|
||||
inherit inputs registry;
|
||||
inherit (spec) system;
|
||||
hostName = name;
|
||||
primaryUser = spec.user;
|
||||
};
|
||||
|
||||
mkHomeManagerModule =
|
||||
name: spec: selected:
|
||||
let
|
||||
homePath = hostFile spec "home.nix";
|
||||
homeModules = [
|
||||
(registry.mkModule { class = "home"; })
|
||||
(registry.mkSelectionModule selected)
|
||||
]
|
||||
++ lib.optional (homePath != null) homePath;
|
||||
in
|
||||
{
|
||||
imports = [ inputs.home-manager.nixosModules.home-manager ];
|
||||
|
||||
home-manager = {
|
||||
useGlobalPkgs = true;
|
||||
useUserPackages = true;
|
||||
extraSpecialArgs = mkSpecialArgs name spec;
|
||||
users.${spec.user}.imports = homeModules;
|
||||
};
|
||||
};
|
||||
|
||||
mkDarwinHomeManagerModule =
|
||||
name: spec: selected:
|
||||
let
|
||||
homePath = hostFile spec "home.nix";
|
||||
homeModules = [
|
||||
(registry.mkModule { class = "home"; })
|
||||
(registry.mkSelectionModule selected)
|
||||
]
|
||||
++ lib.optional (homePath != null) homePath;
|
||||
in
|
||||
{
|
||||
imports = [ inputs.home-manager.darwinModules.home-manager ];
|
||||
|
||||
home-manager = {
|
||||
useGlobalPkgs = true;
|
||||
useUserPackages = true;
|
||||
extraSpecialArgs = mkSpecialArgs name spec;
|
||||
users.${spec.user}.imports = homeModules;
|
||||
};
|
||||
};
|
||||
|
||||
mkNixos =
|
||||
name: rawSpec:
|
||||
let
|
||||
spec = validateSpec name rawSpec;
|
||||
selected = registry.validateUnitIds (selectedUnits spec);
|
||||
nixosPath = hostFile spec "nixos.nix";
|
||||
modules = [
|
||||
(registry.mkModule { class = "nixos"; })
|
||||
(registry.mkSelectionModule selected)
|
||||
{ networking.hostName = lib.mkDefault name; }
|
||||
]
|
||||
++ lib.optional (spec.homeManager or true) (mkHomeManagerModule name spec selected)
|
||||
++ lib.optional (nixosPath != null) nixosPath;
|
||||
in
|
||||
inputs.nixpkgs.lib.nixosSystem {
|
||||
inherit (spec) system;
|
||||
specialArgs = mkSpecialArgs name spec;
|
||||
inherit modules;
|
||||
};
|
||||
|
||||
mkDarwin =
|
||||
name: rawSpec:
|
||||
let
|
||||
spec = validateSpec name rawSpec;
|
||||
selected = registry.validateUnitIds (selectedUnits spec);
|
||||
darwinPath = hostFile spec "darwin.nix";
|
||||
modules = [
|
||||
(registry.mkModule { class = "darwin"; })
|
||||
(registry.mkSelectionModule selected)
|
||||
{ networking.hostName = lib.mkDefault name; }
|
||||
]
|
||||
++ lib.optional (spec.homeManager or true) (mkDarwinHomeManagerModule name spec selected)
|
||||
++ lib.optional (darwinPath != null) darwinPath;
|
||||
in
|
||||
ensure (inputs ? nix-darwin) "${name}: the nix-darwin input is required" (
|
||||
inputs.nix-darwin.lib.darwinSystem {
|
||||
inherit (spec) system;
|
||||
specialArgs = mkSpecialArgs name spec;
|
||||
inherit modules;
|
||||
}
|
||||
);
|
||||
|
||||
mkConfigurations =
|
||||
hostSpecs:
|
||||
let
|
||||
validated = lib.mapAttrs validateSpec hostSpecs;
|
||||
in
|
||||
{
|
||||
nixosConfigurations = lib.mapAttrs mkNixos (
|
||||
lib.filterAttrs (_: spec: isLinux spec.system) validated
|
||||
);
|
||||
darwinConfigurations = lib.mapAttrs mkDarwin (
|
||||
lib.filterAttrs (_: spec: isDarwin spec.system) validated
|
||||
);
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit
|
||||
mkConfigurations
|
||||
mkDarwin
|
||||
mkNixos
|
||||
selectedUnits
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
modulesRoot,
|
||||
}:
|
||||
let
|
||||
reservedFiles = {
|
||||
common = "common.nix";
|
||||
nixos = "nixos.nix";
|
||||
darwin = "darwin.nix";
|
||||
home = "home.nix";
|
||||
meta = "meta.nix";
|
||||
};
|
||||
|
||||
isFile = kind: kind == "regular" || kind == "symlink";
|
||||
|
||||
ensure =
|
||||
condition: message: value:
|
||||
if condition then value else throw "unit registry: ${message}";
|
||||
|
||||
callWithAvailableArgs =
|
||||
value: availableArgs:
|
||||
if builtins.isFunction value then
|
||||
value (builtins.intersectAttrs (builtins.functionArgs value) availableArgs)
|
||||
else
|
||||
value;
|
||||
|
||||
pathFor =
|
||||
relativePath:
|
||||
if relativePath == [ ] then
|
||||
modulesRoot
|
||||
else
|
||||
modulesRoot + "/${lib.concatStringsSep "/" relativePath}";
|
||||
|
||||
entryIsFile = entries: name: builtins.hasAttr name entries && isFile entries.${name};
|
||||
|
||||
normalizeMeta =
|
||||
unit:
|
||||
let
|
||||
metaPath = unit.fragments.meta;
|
||||
importedValue =
|
||||
if metaPath == null then
|
||||
{ }
|
||||
else
|
||||
callWithAvailableArgs (import metaPath) {
|
||||
inherit inputs lib unit;
|
||||
};
|
||||
imported =
|
||||
ensure (builtins.isAttrs importedValue) "${unit.id}: meta.nix must return an attribute set"
|
||||
importedValue;
|
||||
allowedKeys = [
|
||||
"description"
|
||||
"includes"
|
||||
"imports"
|
||||
];
|
||||
unknownKeys = lib.filter (name: !(builtins.elem name allowedKeys)) (builtins.attrNames imported);
|
||||
description = imported.description or null;
|
||||
includes = imported.includes or [ ];
|
||||
imports = imported.imports or { };
|
||||
allowedImportKeys = [
|
||||
"nixos"
|
||||
"darwin"
|
||||
"home"
|
||||
];
|
||||
unknownImportKeys =
|
||||
if builtins.isAttrs imports then
|
||||
lib.filter (name: !(builtins.elem name allowedImportKeys)) (builtins.attrNames imports)
|
||||
else
|
||||
[ ];
|
||||
normalized = {
|
||||
inherit description includes;
|
||||
imports = {
|
||||
nixos = imports.nixos or [ ];
|
||||
darwin = imports.darwin or [ ];
|
||||
home = imports.home or [ ];
|
||||
};
|
||||
};
|
||||
in
|
||||
ensure (unknownKeys == [ ])
|
||||
"${unit.id}: meta.nix has unsupported keys: ${lib.concatStringsSep ", " unknownKeys}"
|
||||
(
|
||||
ensure (description == null || builtins.isString description)
|
||||
"${unit.id}: meta.description must be a string"
|
||||
(
|
||||
ensure (builtins.isList includes && lib.all builtins.isString includes)
|
||||
"${unit.id}: meta.includes must be a list of fully qualified unit IDs"
|
||||
(
|
||||
ensure (lib.unique includes == includes) "${unit.id}: meta.includes contains duplicate unit IDs" (
|
||||
ensure (builtins.isAttrs imports) "${unit.id}: meta.imports must be an attribute set" (
|
||||
ensure (unknownImportKeys == [ ])
|
||||
"${unit.id}: meta.imports has unsupported classes: ${lib.concatStringsSep ", " unknownImportKeys}"
|
||||
(
|
||||
ensure (lib.all builtins.isList [
|
||||
normalized.imports.nixos
|
||||
normalized.imports.darwin
|
||||
normalized.imports.home
|
||||
]) "${unit.id}: every meta.imports.<class> value must be a list" normalized
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
makeUnit =
|
||||
relativePath: entries:
|
||||
let
|
||||
directory = pathFor relativePath;
|
||||
id = lib.concatStringsSep "." relativePath;
|
||||
fragments = lib.mapAttrs (
|
||||
_class: fileName: if entryIsFile entries fileName then directory + "/${fileName}" else null
|
||||
) reservedFiles;
|
||||
baseUnit = {
|
||||
inherit
|
||||
id
|
||||
directory
|
||||
fragments
|
||||
relativePath
|
||||
;
|
||||
optionPath = [ "my" ] ++ relativePath ++ [ "enable" ];
|
||||
kind = builtins.head relativePath;
|
||||
name = lib.last relativePath;
|
||||
}
|
||||
//
|
||||
lib.optionalAttrs (builtins.length relativePath > 2 && builtins.head relativePath == "profiles")
|
||||
{
|
||||
group = builtins.elemAt relativePath 1;
|
||||
};
|
||||
in
|
||||
ensure (relativePath != [ ]) "the modules root cannot itself be a unit" (
|
||||
ensure (lib.all (component: component != "" && !(lib.hasInfix "." component)) relativePath)
|
||||
"${id}: path components must be non-empty and must not contain dots"
|
||||
(baseUnit // { meta = normalizeMeta baseUnit; })
|
||||
);
|
||||
|
||||
walk =
|
||||
relativePath:
|
||||
let
|
||||
directory = pathFor relativePath;
|
||||
entries = builtins.readDir directory;
|
||||
hasReservedFile = lib.any (fileName: entryIsFile entries fileName) (
|
||||
builtins.attrValues reservedFiles
|
||||
);
|
||||
childDirectories = lib.filter (name: entries.${name} == "directory") (builtins.attrNames entries);
|
||||
current = lib.optional hasReservedFile (makeUnit relativePath entries);
|
||||
children = lib.concatMap (name: walk (relativePath ++ [ name ])) childDirectories;
|
||||
in
|
||||
current ++ children;
|
||||
|
||||
discoveredUnits =
|
||||
ensure (builtins.pathExists modulesRoot) "modules root does not exist: ${toString modulesRoot}"
|
||||
(walk [ ]);
|
||||
unitsById = builtins.listToAttrs (map (unit: lib.nameValuePair unit.id unit) discoveredUnits);
|
||||
|
||||
dependencyValidation = lib.foldl' (
|
||||
valid: unit:
|
||||
lib.foldl' (
|
||||
inner: includedId:
|
||||
if builtins.hasAttr includedId unitsById then
|
||||
inner
|
||||
else
|
||||
throw "unit registry: ${unit.id} includes missing unit '${includedId}'"
|
||||
) valid unit.meta.includes
|
||||
) true discoveredUnits;
|
||||
|
||||
units = builtins.seq dependencyValidation unitsById;
|
||||
unitIds = builtins.attrNames units;
|
||||
|
||||
getUnit =
|
||||
id: if builtins.hasAttr id units then units.${id} else throw "unit registry: unknown unit '${id}'";
|
||||
|
||||
validateUnitIds =
|
||||
ids:
|
||||
ensure (
|
||||
builtins.isList ids && lib.all builtins.isString ids
|
||||
) "selected units must be a list of strings" (map (id: builtins.seq (getUnit id) id) ids);
|
||||
|
||||
optionDefinitions = lib.foldl' lib.recursiveUpdate { } (
|
||||
map (
|
||||
unit:
|
||||
lib.setAttrByPath unit.optionPath (
|
||||
lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description =
|
||||
if unit.meta.description == null then
|
||||
"Whether to enable the ${unit.id} unit."
|
||||
else
|
||||
"Whether to enable ${unit.meta.description}.";
|
||||
}
|
||||
)
|
||||
) discoveredUnits
|
||||
);
|
||||
|
||||
enabled = config: unit: lib.getAttrFromPath unit.optionPath config;
|
||||
|
||||
enableUnit = id: lib.setAttrByPath (getUnit id).optionPath true;
|
||||
|
||||
includeConfig =
|
||||
config: unit: lib.mkIf (enabled config unit) (lib.mkMerge (map enableUnit unit.meta.includes));
|
||||
|
||||
fragmentClasses = {
|
||||
nixos = [
|
||||
"common"
|
||||
"nixos"
|
||||
];
|
||||
darwin = [
|
||||
"common"
|
||||
"darwin"
|
||||
];
|
||||
home = [ "home" ];
|
||||
};
|
||||
|
||||
applyFragment =
|
||||
{
|
||||
config,
|
||||
fragmentPath,
|
||||
options,
|
||||
specialArgs,
|
||||
unit,
|
||||
}:
|
||||
let
|
||||
fragment = import fragmentPath;
|
||||
directArgs = specialArgs // {
|
||||
inherit
|
||||
config
|
||||
lib
|
||||
options
|
||||
specialArgs
|
||||
unit
|
||||
;
|
||||
};
|
||||
fragmentArgSpec = builtins.functionArgs fragment;
|
||||
fragmentArgs = builtins.listToAttrs (
|
||||
lib.concatMap (
|
||||
name:
|
||||
if builtins.hasAttr name directArgs then
|
||||
[ (lib.nameValuePair name directArgs.${name}) ]
|
||||
else if fragmentArgSpec.${name} then
|
||||
[ ]
|
||||
else
|
||||
[ (lib.nameValuePair name config._module.args.${name}) ]
|
||||
) (builtins.attrNames fragmentArgSpec)
|
||||
);
|
||||
resultValue = if builtins.isFunction fragment then fragment fragmentArgs else fragment;
|
||||
result =
|
||||
ensure (builtins.isAttrs resultValue)
|
||||
"${unit.id}: ${builtins.baseNameOf fragmentPath} must return an attribute set"
|
||||
resultValue;
|
||||
forbiddenKeys = lib.filter (name: builtins.hasAttr name result) [
|
||||
"imports"
|
||||
"options"
|
||||
"config"
|
||||
];
|
||||
in
|
||||
ensure (forbiddenKeys == [ ])
|
||||
"${unit.id}: ${builtins.baseNameOf fragmentPath} is a configuration fragment and cannot define top-level ${lib.concatStringsSep ", " forbiddenKeys}"
|
||||
result;
|
||||
|
||||
externalImports = class: lib.concatMap (unit: unit.meta.imports.${class}) discoveredUnits;
|
||||
|
||||
mkModule =
|
||||
{ class }:
|
||||
ensure (builtins.hasAttr class fragmentClasses) "unsupported module class '${class}'" (
|
||||
builtins.seq dependencyValidation (
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
options,
|
||||
specialArgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
fragmentConfigs = lib.concatMap (
|
||||
unit:
|
||||
lib.filter (value: value != null) (
|
||||
map (
|
||||
fragmentClass:
|
||||
let
|
||||
fragmentPath = unit.fragments.${fragmentClass};
|
||||
in
|
||||
if fragmentPath == null then
|
||||
null
|
||||
else
|
||||
lib.mkIf (enabled config unit) (applyFragment {
|
||||
inherit
|
||||
config
|
||||
fragmentPath
|
||||
options
|
||||
specialArgs
|
||||
unit
|
||||
;
|
||||
})
|
||||
) fragmentClasses.${class}
|
||||
)
|
||||
) discoveredUnits;
|
||||
in
|
||||
{
|
||||
imports = externalImports class;
|
||||
options = optionDefinitions;
|
||||
config = lib.mkMerge ((map (includeConfig config) discoveredUnits) ++ fragmentConfigs);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
mkSelectionModule =
|
||||
selectedIds:
|
||||
let
|
||||
checkedIds = validateUnitIds (lib.unique selectedIds);
|
||||
in
|
||||
{
|
||||
config = lib.mkMerge (map enableUnit checkedIds);
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit
|
||||
getUnit
|
||||
mkModule
|
||||
mkSelectionModule
|
||||
unitIds
|
||||
units
|
||||
validateUnitIds
|
||||
;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
includes = [ "applications.missing" ];
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
imports = [ ];
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
system.stateVersion = 6;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
fileSystems."/" = {
|
||||
device = "/dev/null";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
system.stateVersion = "26.05";
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
marker ? "host",
|
||||
...
|
||||
}:
|
||||
{
|
||||
test.systemValues = [ "common:${marker}" ];
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
test.systemValues = [ "darwin" ];
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
test.homeValues = [ "home" ];
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
description = "alpha test application";
|
||||
|
||||
includes = [ "services.nested" ];
|
||||
|
||||
imports.nixos = [
|
||||
{
|
||||
options.test = {
|
||||
external = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "external-default";
|
||||
};
|
||||
systemValues = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
imports.darwin = [
|
||||
{
|
||||
options.test.systemValues = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
imports.home = [
|
||||
{
|
||||
options.test.homeValues = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
test.systemValues = [ "nixos" ];
|
||||
test.external = "set-by-nixos-fragment";
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
test.homeValues = [ "beta-home" ];
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
thisFileMustNotBeDiscovered = true;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
includes = [
|
||||
"applications.alpha"
|
||||
"applications.beta"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
imports.nixos = [
|
||||
{
|
||||
options.test.nested = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
test.nested = true;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
home = {
|
||||
username = "test";
|
||||
homeDirectory = if pkgs.stdenv.hostPlatform.isDarwin then "/Users/test" else "/home/test";
|
||||
stateVersion = "26.05";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
pkgs,
|
||||
}:
|
||||
let
|
||||
registry = import ../libs/registry.nix {
|
||||
inherit inputs lib;
|
||||
modulesRoot = ./fixtures/registry/modules;
|
||||
};
|
||||
|
||||
hostLib = import ../libs/hosts.nix {
|
||||
inherit inputs lib registry;
|
||||
};
|
||||
|
||||
baseModule = {
|
||||
options = {
|
||||
home = {
|
||||
username = lib.mkOption { type = lib.types.str; };
|
||||
homeDirectory = lib.mkOption { type = lib.types.str; };
|
||||
stateVersion = lib.mkOption { type = lib.types.str; };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
eval =
|
||||
class: selected:
|
||||
lib.evalModules {
|
||||
specialArgs = {
|
||||
inherit pkgs;
|
||||
marker = "special-arg";
|
||||
};
|
||||
modules = [
|
||||
baseModule
|
||||
(registry.mkModule { inherit class; })
|
||||
(registry.mkSelectionModule selected)
|
||||
];
|
||||
};
|
||||
|
||||
nixos = eval "nixos" [ "profiles.interface.test" ];
|
||||
darwin = eval "darwin" [ "applications.alpha" ];
|
||||
home = eval "home" [ "profiles.interface.test" ];
|
||||
|
||||
nixosHost = hostLib.mkNixos "registry-test" {
|
||||
system = "x86_64-linux";
|
||||
user = "test";
|
||||
path = ./fixtures/registry/hosts;
|
||||
profiles = [ "interface.test" ];
|
||||
};
|
||||
|
||||
darwinHost = hostLib.mkDarwin "registry-test-darwin" {
|
||||
system = "aarch64-darwin";
|
||||
user = "test";
|
||||
path = ./fixtures/registry/hosts;
|
||||
applications = [ "alpha" ];
|
||||
};
|
||||
|
||||
missingUnit = builtins.tryEval (
|
||||
builtins.deepSeq (registry.validateUnitIds [ "applications.missing" ]) true
|
||||
);
|
||||
|
||||
invalidDependencyRegistry = import ../libs/registry.nix {
|
||||
inherit inputs lib;
|
||||
modulesRoot = ./fixtures/registry-invalid-dependency/modules;
|
||||
};
|
||||
missingDependency = builtins.tryEval (builtins.deepSeq invalidDependencyRegistry.unitIds true);
|
||||
|
||||
invalidFragmentRegistry = import ../libs/registry.nix {
|
||||
inherit inputs lib;
|
||||
modulesRoot = ./fixtures/registry-invalid-fragment/modules;
|
||||
};
|
||||
invalidFragmentEvaluation = lib.evalModules {
|
||||
modules = [
|
||||
(invalidFragmentRegistry.mkModule { class = "home"; })
|
||||
(invalidFragmentRegistry.mkSelectionModule [ "applications.broken" ])
|
||||
];
|
||||
};
|
||||
invalidFragment = builtins.tryEval (builtins.deepSeq invalidFragmentEvaluation.config true);
|
||||
|
||||
assertions =
|
||||
assert
|
||||
registry.unitIds == [
|
||||
"applications.alpha"
|
||||
"applications.beta"
|
||||
"profiles.interface.test"
|
||||
"services.nested"
|
||||
"users.test"
|
||||
];
|
||||
assert !(builtins.elem "namespace" registry.unitIds);
|
||||
assert nixos.config.my.profiles.interface.test.enable;
|
||||
assert nixos.config.my.applications.alpha.enable;
|
||||
assert nixos.config.my.applications.beta.enable;
|
||||
assert nixos.config.my.services.nested.enable;
|
||||
assert nixos.config.test.nested;
|
||||
assert
|
||||
nixos.config.test.systemValues == [
|
||||
"common:special-arg"
|
||||
"nixos"
|
||||
];
|
||||
assert nixos.config.test.external == "set-by-nixos-fragment";
|
||||
assert
|
||||
darwin.config.test.systemValues == [
|
||||
"common:special-arg"
|
||||
"darwin"
|
||||
];
|
||||
assert
|
||||
home.config.test.homeValues == [
|
||||
"home"
|
||||
"beta-home"
|
||||
];
|
||||
assert nixosHost.config.my.profiles.interface.test.enable;
|
||||
assert nixosHost.config.home-manager.users.test.my.applications.alpha.enable;
|
||||
assert
|
||||
nixosHost.config.home-manager.users.test.test.homeValues == [
|
||||
"home"
|
||||
"beta-home"
|
||||
];
|
||||
assert darwinHost.config.my.applications.alpha.enable;
|
||||
assert darwinHost.config.home-manager.users.test.my.applications.alpha.enable;
|
||||
assert darwinHost.config.home-manager.users.test.test.homeValues == [ "home" ];
|
||||
assert
|
||||
darwinHost.config.test.systemValues == [
|
||||
"common:host"
|
||||
"darwin"
|
||||
];
|
||||
assert !missingUnit.success;
|
||||
assert !missingDependency.success;
|
||||
assert !invalidFragment.success;
|
||||
true;
|
||||
in
|
||||
assert assertions;
|
||||
pkgs.runCommand "unit-registry-evaluation-tests" { } ''
|
||||
touch "$out"
|
||||
''
|
||||
Reference in New Issue
Block a user