switch to devlib repo and remove in-tree lib

This commit is contained in:
Pacman99 2021-05-04 21:48:49 -07:00
parent b8f7cdbe63
commit 8dabd0f569
34 changed files with 27 additions and 1432 deletions

View File

@ -69,7 +69,7 @@
"type": "github" "type": "github"
} }
}, },
"devos": { "devlib": {
"inputs": { "inputs": {
"deploy": "deploy", "deploy": "deploy",
"devshell": "devshell", "devshell": "devshell",
@ -79,13 +79,17 @@
"utils": "utils_2" "utils": "utils_2"
}, },
"locked": { "locked": {
"narHash": "sha256-/htTDxf3/n8lcL7Gnoi3+uamuY/KnlSMWDQ76dzQpac=", "lastModified": 1620188794,
"path": "./lib", "narHash": "sha256-BDwtrbUkrSnBQJBXuaJg9QBu3MYL0iuJPE8P30o0x7I=",
"type": "path" "owner": "divnix",
"repo": "devlib",
"rev": "ffda6add9eb984d986cf5b6a838a52334317302f",
"type": "github"
}, },
"original": { "original": {
"path": "./lib", "owner": "divnix",
"type": "path" "repo": "devlib",
"type": "github"
} }
}, },
"devshell": { "devshell": {
@ -321,7 +325,7 @@
"inputs": { "inputs": {
"ci-agent": "ci-agent", "ci-agent": "ci-agent",
"darwin": "darwin", "darwin": "darwin",
"devos": "devos", "devlib": "devlib",
"home": "home", "home": "home",
"latest": "latest", "latest": "latest",
"naersk": "naersk_2", "naersk": "naersk_2",

View File

@ -5,14 +5,9 @@
{ {
nixos.url = "nixpkgs/nixos-unstable"; nixos.url = "nixpkgs/nixos-unstable";
latest.url = "nixpkgs"; latest.url = "nixpkgs";
devos.url = "path:./lib"; # TODO: outfactor into separate repo devlib.url = "github:divnix/devlib";
devos.inputs = { devlib.inputs = {
nixpkgs.follows = "nixos"; nixpkgs.follows = "nixos";
# deploy.inputs = {
# flake-compat.follows = "flake-compat";
# naersk.follows = "naersk";
# nixpkgs.follows = "nixos";
# };
}; };
ci-agent = { ci-agent = {
@ -31,8 +26,8 @@
pkgs.inputs.nixpkgs.follows = "nixos"; pkgs.inputs.nixpkgs.follows = "nixos";
}; };
outputs = inputs@{ self, pkgs, devos, nixos, ci-agent, home, nixos-hardware, nur, ... }: outputs = inputs@{ self, pkgs, devlib, nixos, ci-agent, home, nixos-hardware, nur, ... }:
devos.lib.mkFlake { devlib.lib.mkFlake {
inherit self inputs; inherit self inputs;
channelsConfig = { allowUnfree = true; }; channelsConfig = { allowUnfree = true; };
@ -40,7 +35,7 @@
channels = { channels = {
nixos = { nixos = {
overlays = [ overlays = [
(devos.lib.pathsIn ./overlays) (devlib.lib.pathsIn ./overlays)
./pkgs/default.nix ./pkgs/default.nix
pkgs.overlay # for `srcs` pkgs.overlay # for `srcs`
nur.overlay nur.overlay
@ -49,6 +44,12 @@
latest = { }; latest = { };
}; };
sharedOverlays = [
(final: prev: {
ourlib = prev.devlib.extend (import ./lib);
})
];
nixos = { nixos = {
hostDefaults = { hostDefaults = {
system = "x86_64-linux"; system = "x86_64-linux";
@ -61,7 +62,7 @@
]; ];
}; };
hosts = nixos.lib.mkMerge [ hosts = nixos.lib.mkMerge [
(devos.lib.importHosts ./hosts) (devlib.lib.importHosts ./hosts)
{ /* set host specific properties here */ } { /* set host specific properties here */ }
]; ];
profiles = [ ./profiles ./users ]; profiles = [ ./profiles ./users ];
@ -79,9 +80,9 @@
}; };
}; };
homeConfigurations = devos.lib.mkHomeConfigurations self.nixosConfigurations; homeConfigurations = devlib.lib.mkHomeConfigurations self.nixosConfigurations;
deploy.nodes = devos.lib.mkDeployNodes self.nixosConfigurations { }; deploy.nodes = devlib.lib.mkDeployNodes self.nixosConfigurations { };
#defaultTemplate = self.templates.flk; #defaultTemplate = self.templates.flk;
templates.flk.path = ./.; templates.flk.path = ./.;

View File

@ -1,19 +0,0 @@
{ lib }:
rec {
# mapFilterAttrs ::
# (name -> value -> bool )
# (name -> value -> { name = any; value = any; })
# attrs
mapFilterAttrs = seive: f: attrs:
lib.filterAttrs
seive
(lib.mapAttrs' f attrs);
# Generate an attribute set by mapping a function over a list of values.
genAttrs' = values: f: lib.listToAttrs (map f values);
concatAttrs = lib.fold (attr: sum: lib.recursiveUpdate sum attr) { };
safeReadDir = path:
lib.optionalAttrs (builtins.pathExists (toString path)) (builtins.readDir (toString path));
}

2
lib/default.nix Normal file
View File

@ -0,0 +1,2 @@
lfinal: lprev: {
}

View File

@ -1,15 +0,0 @@
{ lib }:
nixosConfigurations:
with lib;
let
mkHomes = hostName: host:
mapAttrs' (user: v: nameValuePair "${user}@${hostName}" v.home)
# So this function is useful for non-devos hosts
(host.config.system.build.homes or host.config.home-manager.users);
hmConfigs = mapAttrs mkHomes nixosConfigurations;
in
foldl recursiveUpdate { } (attrValues hmConfigs)

View File

@ -1,166 +0,0 @@
{
"nodes": {
"deploy": {
"inputs": {
"flake-compat": "flake-compat",
"naersk": "naersk",
"nixpkgs": "nixpkgs",
"utils": "utils"
},
"locked": {
"lastModified": 1616406726,
"narHash": "sha256-n9zmgxR03QNrvs9/fHewqE0j3SjL7Y+cglBCFu3U3rg=",
"owner": "serokell",
"repo": "deploy-rs",
"rev": "9e405fbc5ab5bacbd271fd78c6b6b6877c4d9f8d",
"type": "github"
},
"original": {
"owner": "serokell",
"repo": "deploy-rs",
"type": "github"
}
},
"devshell": {
"locked": {
"lastModified": 1618523768,
"narHash": "sha256-Gev9da35pHUey3kGz/zrJFc/9ICs++vPCho7qB1mqd8=",
"owner": "numtide",
"repo": "devshell",
"rev": "709fe4d04a9101c9d224ad83f73416dce71baf21",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1606424373,
"narHash": "sha256-oq8d4//CJOrVj+EcOaSXvMebvuTkmBJuT5tzlfewUnQ=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "99f1c2157fba4bfe6211a321fd0ee43199025dbf",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1619345332,
"narHash": "sha256-qHnQkEp1uklKTpx3MvKtY6xzgcqXDsz5nLilbbuL+3A=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "2ebf2558e5bf978c7fb8ea927dfaed8fefab2e28",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1610392286,
"narHash": "sha256-3wFl5y+4YZO4SgRYK8WE7JIS3p0sxbgrGaQ6RMw+d98=",
"owner": "nmattia",
"repo": "naersk",
"rev": "d7bfbad3304fd768c0f93a4c3b50976275e6d4be",
"type": "github"
},
"original": {
"owner": "nmattia",
"ref": "master",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1610942247,
"narHash": "sha256-PKo1ATAlC6BmfYSRmX0TVmNoFbrec+A5OKcabGEu2yU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7d71001b796340b219d1bfa8552c81995017544a",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1619244632,
"narHash": "sha256-IDcbMRnyKO9WlQ5xzIlM3HfWAUKTy+3xSd+CvDGiLgE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5cecebfb2f76da7b93f19967e99b3ff4fb4d2850",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"deploy": "deploy",
"devshell": "devshell",
"nixpkgs": "nixpkgs_2",
"utils": "utils_2"
}
},
"utils": {
"locked": {
"lastModified": 1610051610,
"narHash": "sha256-U9rPz/usA1/Aohhk7Cmc2gBrEEKRzcW4nwPWMPwja4Y=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3982c9903e93927c2164caa727cd3f6a0e6d14cc",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"utils_2": {
"inputs": {
"flake-utils": "flake-utils"
},
"locked": {
"lastModified": 1619714004,
"narHash": "sha256-xoP81rWAM2cVpEFrQv9sUEIvNxGXAg4UH9kBt83a5u4=",
"owner": "gytis-ivaskevicius",
"repo": "flake-utils-plus",
"rev": "0642ac572a87a0beb78a7c6ddce1267aa5817d05",
"type": "github"
},
"original": {
"owner": "gytis-ivaskevicius",
"ref": "staging",
"repo": "flake-utils-plus",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@ -1,84 +0,0 @@
{
description = "DevOS environment configuriguration library.";
inputs =
{
deploy.url = "github:serokell/deploy-rs";
devshell.url = "github:numtide/devshell";
utils.url = "github:gytis-ivaskevicius/flake-utils-plus/staging";
};
outputs = inputs@{ self, nixpkgs, deploy, devshell, utils, ... }:
let
lib = nixpkgs.lib.makeExtensible (self:
let combinedLib = nixpkgs.lib // self; in
with self;
utils.lib // {
attrs = import ./attrs.nix { lib = combinedLib; };
lists = import ./lists.nix { lib = combinedLib; };
strings = import ./strings.nix { lib = combinedLib; };
modules = import ./modules.nix { lib = combinedLib; };
importers = import ./importers.nix { lib = combinedLib; };
generators = import ./generators.nix {
lib = combinedLib;
inherit deploy;
};
mkFlake = {
__functor = import ./mkFlake { lib = combinedLib; };
evalArgs = import ./mkFlake/evalArgs.nix { lib = combinedLib; };
};
pkgs-lib = import ./pkgs-lib {
lib = combinedLib;
inherit deploy devshell;
};
inherit (attrs) mapFilterAttrs genAttrs' safeReadDir concatAttrs;
inherit (lists) profileMap collectProfiles unifyOverlays;
inherit (strings) rgxToString;
inherit (importers) mkProfileAttrs pathsIn importHosts;
inherit (generators) mkSuites mkDeployNodes mkHomeConfigurations;
}
);
in
{
lib = with lib; utils.lib // {
inherit attrs lists modules importers generators;
inherit (lib)
mkFlake
pathsIn
importHosts
mkDeployNodes
mkHomeConfigurations;
};
}
//
utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
checks = {
tests = import ./tests {
inherit pkgs;
lib = nixpkgs.lib // lib;
};
};
packages = {
mkFlakeDoc = pkgs.writeText "mkFlakeOptions.md"
(
pkgs.nixosOptionsDoc {
inherit (lib.mkFlake.evalArgs { args = { }; }) options;
}
).optionsMDDoc;
};
}
);
}

View File

@ -1,50 +0,0 @@
{ lib, deploy }:
{
mkHomeConfigurations = nixosConfigurations:
with lib;
let
mkHomes = host: config:
mapAttrs' (user: v: nameValuePair "${user}@${host}" v.home)
config.config.system.build.homes;
hmConfigs = mapAttrs mkHomes nixosConfigurations;
in
foldl recursiveUpdate { } (attrValues hmConfigs);
mkDeployNodes = hosts: extraConfig:
/**
Synopsis: mkNodes _nixosConfigurations_
Generate the `nodes` attribute expected by deploy-rs
where _nixosConfigurations_ are `nodes`.
**/
lib.mapAttrs
(_: config: lib.recursiveUpdate
{
hostname = config.config.networking.hostName;
profiles.system = {
user = "root";
path = deploy.lib.x86_64-linux.activate.nixos config;
};
}
extraConfig)
hosts;
mkSuites = { suites, profiles }:
let
profileSet = lib.genAttrs' profiles (path: {
name = baseNameOf path;
value = lib.mkProfileAttrs (toString path);
});
definedSuites = suites profileSet;
allProfiles = lib.collectProfiles profileSet;
in
lib.mapAttrs (_: v: lib.profileMap v) definedSuites // {
inherit allProfiles;
};
}

View File

@ -1,64 +0,0 @@
{ lib }:
let
recImport = { dir, _import ? base: import "${dir}/${base}.nix" }:
lib.mapFilterAttrs
(_: v: v != null)
(n: v:
if n != "default.nix" && lib.hasSuffix ".nix" n && v == "regular"
then
let name = lib.removeSuffix ".nix" n; in lib.nameValuePair (name) (_import name)
else
lib.nameValuePair ("") (null))
(lib.safeReadDir dir);
mkProfileAttrs =
/**
Synopsis: mkProfileAttrs _path_
Recursively collect the subdirs of _path_ containing a default.nix into attrs.
This sets a contract, eliminating ambiguity for _default.nix_ living under the
profile directory.
Example:
let profiles = mkProfileAttrs ./profiles; in
assert profiles ? core.default; 0
**/
dir:
let
imports =
let
files = lib.safeReadDir dir;
p = n: v:
v == "directory"
&& n != "profiles";
in
lib.filterAttrs p files;
f = n: _:
lib.optionalAttrs
(lib.pathExists "${dir}/${n}/default.nix")
{ default = "${dir}/${n}"; }
// mkProfileAttrs "${dir}/${n}";
in
lib.mapAttrs f imports;
in
{
inherit recImport mkProfileAttrs;
pathsIn = dir:
let
fullPath = name: "${toString dir}/${name}";
in
map fullPath (lib.attrNames (lib.safeReadDir dir));
importHosts = dir:
recImport {
inherit dir;
_import = base: {
modules = import "${toString dir}/${base}.nix";
};
};
}

View File

@ -1,19 +0,0 @@
{ lib }:
{
collectProfiles = set:
let
collectNestedProfiles = set:
lib.mapAttrsToList
(n: v:
if builtins.isAttrs v then
[ v.default or null ] ++ collectNestedProfiles v
else null
)
set;
in
builtins.filter (x: x != null) (lib.flatten (collectNestedProfiles set));
profileMap = list: map (profile: profile.default) (lib.flatten list);
unifyOverlays = channels: map (o: if builtins.isFunction (o null null) then o channels else o);
}

View File

@ -1,99 +0,0 @@
{ lib }:
let
inherit (builtins) mapAttrs attrNames attrValues head isFunction;
in
_: { self, inputs, ... } @ args:
let
config = lib.mkFlake.evalArgs {
inherit args;
};
cfg = config.config;
otherArguments = removeAttrs args (attrNames config.options);
defaultModules = with lib.modules; [
(hmDefaults {
inherit (cfg.home) suites;
modules = cfg.home.modules ++ cfg.home.externalModules;
})
(globalDefaults {
inherit self inputs;
})
];
stripChannel = channel: removeAttrs channel [
# arguments in our channels api that shouldn't be passed to fup
"overlays"
];
getDefaultChannel = channels: channels.${cfg.nixos.hostDefaults.channelName};
# evalArgs sets channelName and system to null by default
# but for proper default handling in fup, null args have to be removed
stripHost = args: removeAttrs (lib.filterAttrs (_: arg: arg != null) args) [
# arguments in our hosts/hostDefaults api that shouldn't be passed to fup
"externalModules"
];
hosts = lib.mapAttrs (_: stripHost) cfg.nixos.hosts;
hostDefaults = stripHost cfg.nixos.hostDefaults;
in
lib.systemFlake (lib.mergeAny
{
inherit self inputs hosts;
inherit (cfg) channelsConfig supportedSystems;
channels = mapAttrs
(name: channel:
stripChannel (channel // {
# pass channels if "overlay" has three arguments
overlaysBuilder = channels: lib.unifyOverlays channels channel.overlays;
})
)
cfg.channels;
sharedOverlays = [
(final: prev: {
__dontExport = true;
devlib = lib;
})
];
hostDefaults = lib.mergeAny hostDefaults {
specialArgs.suites = cfg.nixos.suites;
modules = cfg.nixos.hostDefaults.externalModules ++ defaultModules;
builder = args: args.specialArgs.channel.input.lib.nixosSystem (lib.mergeAny args {
# So modules and functions can create their own version of the build
modules = [{ lib.builderArgs = args; }];
});
};
nixosModules = lib.exporter.modulesFromList cfg.nixos.hostDefaults.modules;
homeModules = lib.exporter.modulesFromList cfg.home.modules;
overlays = lib.exporter.overlaysFromChannelsExporter {
# since we can't detect overlays owned by self
# we have to filter out ones exported by the inputs
# optimally we would want a solution for NixOS/nix#4740
inherit inputs;
inherit (self) pkgs;
};
packagesBuilder = lib.builder.packagesFromOverlaysBuilderConstructor self.overlays;
checksBuilder = channels:
lib.pkgs-lib.tests.mkChecks {
pkgs = getDefaultChannel channels;
inherit (self.deploy) nodes;
hosts = self.nixosConfigurations;
homes = self.homeConfigurations;
};
devShellBuilder = channels:
lib.pkgs-lib.shell {
pkgs = getDefaultChannel channels;
};
}
otherArguments # for overlays list order
)

View File

@ -1,262 +0,0 @@
{ lib }:
{ args }:
let
argOpts = with lib; { config, ... }:
let
cfg = config;
inherit (config) self;
maybeImport = obj:
if (builtins.typeOf obj == "path") || (builtins.typeOf obj == "string") then
import obj
else
obj;
/* Custom types needed for arguments */
moduleType = with types; pathTo (anything // {
inherit (submodule { }) check;
description = "valid module";
});
# to export modules we need paths to get the name
exportModuleType = with types;
(addCheck path (x: moduleType.check (import x))) // {
description = "path to a module";
};
overlayType = pathTo (types.anything // {
check = builtins.isFunction;
description = "valid Nixpkgs overlay";
});
systemType = types.enum config.supportedSystems;
flakeType = with types; (addCheck attrs lib.isStorePath) // {
description = "nix flake";
};
# Apply maybeImport during merge and before check
# To simplify apply keys and improve type checking
pathTo = elemType: with types; coercedTo path maybeImport elemType;
pathToListOf = elemType: with types; pathTo (listOf elemType);
coercedListOf = elemType: with types;
coercedTo anything (x: flatten (singleton x)) (listOf elemType);
/* Submodules needed for API containers */
channelsModule = { name, ... }: {
options = with types; {
input = mkOption {
type = flakeType;
default = cfg.inputs.${name};
defaultText = "inputs.<name>";
description = ''
nixpkgs flake input to use for this channel
'';
};
overlays = mkOption {
type = coercedListOf overlayType;
default = [ ];
description = escape [ "<" ">" ] ''
overlays to apply to this channel
these will get exported under the 'overlays' flake output
as <channel>/<name> and any overlay pulled from ''\${inputs}
will be filtered out
'';
};
config = mkOption {
type = pathTo attrs;
default = { };
apply = lib.recursiveUpdate cfg.channelsConfig;
description = ''
nixpkgs config for this channel
'';
};
};
};
hostModule = {
options = with types; {
# anything null in hosts gets filtered out by mkFlake
system = mkOption {
type = (nullOr systemType) // {
description = "system defined in `supportedSystems`";
};
default = null;
description = ''
system for this host
'';
};
channelName = mkOption {
type = (nullOr (types.enum (builtins.attrNames config.channels))) // {
description = "a channel defined in `channels`";
};
default = null;
description = ''
Channel this host should follow
'';
};
};
};
# This is only needed for hostDefaults
# modules in each host don't get exported
externalModulesModule = {
options = {
externalModules = mkOption {
type = with types; listOf moduleType;
default = [ ];
description = ''
modules to include that won't be exported
meant importing modules from external flakes
'';
};
};
};
modulesModule = {
options = {
modules = mkOption {
type = with types; coercedListOf moduleType;
default = [ ];
description = ''
modules to include
'';
};
};
};
exportModulesModule = name: {
options = {
modules = mkOption {
type = with types; pathTo (coercedListOf exportModuleType);
default = [ ];
description = ''
modules to include in all hosts and export to ${name}Modules output
'';
};
};
};
# Home-manager's configs get exported automatically from nixos.hosts
# So there is no need for a host options in the home namespace
# This is only needed for nixos
includeHostsModule = name: {
options = with types; {
hostDefaults = mkOption {
type = submodule [
hostModule
externalModulesModule
(exportModulesModule name)
];
default = { };
description = ''
Defaults for all hosts.
the modules passed under hostDefaults will be exported
to the '${name}Modules' flake output.
They will also be added to all hosts.
'';
};
hosts = mkOption {
type = attrsOf (submodule [ hostModule modulesModule ]);
default = { };
description = ''
configurations to include in the ${name}Configurations output
'';
};
};
};
# profiles and suites - which are profile collections
profilesModule = { config, ... }: {
options = with types; {
profiles = mkOption {
type = listOf path;
default = [ ];
description = ''
profile folders that can be collected into suites
the name of the argument passed to suites is based
on the folder name.
[ ./profiles ] => { profiles }:
'';
};
suites = mkOption {
type = pathTo (functionTo attrs);
default = _: { };
apply = suites: lib.mkSuites {
inherit suites;
inherit (config) profiles;
};
description = ''
Function that takes profiles and returns suites for this config system
These can be accessed through the 'suites' special argument.
'';
};
};
};
in
{
# this does not get propagated to submodules
# to allow passing flake outputs directly to mkFlake
config._module.check = false;
options = with types; {
self = mkOption {
type = flakeType;
description = "The flake to create the devos outputs for";
};
inputs = mkOption {
type = attrsOf flakeType;
description = ''
inputs for this flake
used to set channel defaults and create registry
'';
};
supportedSystems = mkOption {
type = listOf str;
default = lib.defaultSystems;
description = ''
The systems supported by this flake
'';
};
channelsConfig = mkOption {
type = pathTo attrs;
default = { };
description = ''
nixpkgs config for all channels
'';
};
channels = mkOption {
type = attrsOf (submodule channelsModule);
default = { };
description = ''
nixpkgs channels to create
'';
};
nixos = mkOption {
type = submodule [ (includeHostsModule "nixos") profilesModule ];
default = { };
description = ''
hosts, modules, suites, and profiles for nixos
'';
};
home = mkOption {
type = submodule [
profilesModule
(exportModulesModule "home")
externalModulesModule
];
default = { };
description = ''
hosts, modules, suites, and profiles for home-manager
'';
};
};
};
in
lib.evalModules {
modules = [ argOpts args ];
}

View File

@ -1,119 +0,0 @@
{ lib }:
{
hmDefaults = { suites, modules }:
{ options, ... }: {
config = lib.optionalAttrs (options ? home-manager) {
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = { inherit suites; };
sharedModules = modules;
};
};
};
globalDefaults = { self, inputs }:
let
experimentalFeatures = [
"flakes"
"nix-command"
"ca-references"
"ca-derivations"
];
in
{ channel, config, pkgs, ... }: {
users.mutableUsers = lib.mkDefault false;
hardware.enableRedistributableFirmware = lib.mkDefault true;
nix.nixPath = [
"nixpkgs=${channel.input}"
"nixos-config=${self}/lib/compat/nixos"
"home-manager=${inputs.home}"
];
nix.registry = {
devos.flake = self;
nixos.flake = channel.input;
};
nix.extraOptions = ''
experimental-features = ${lib.concatStringsSep " "
experimentalFeatures
}
'';
_module.args = {
inherit self;
devlib = pkgs.devlib;
hosts = builtins.mapAttrs (_: host: host.config)
(removeAttrs self.nixosConfigurations [ config.networking.hostName ]);
};
system.configurationRevision = lib.mkIf (self ? rev) self.rev;
};
isoConfig = { self, inputs, fullHostConfig }:
{ config, modulesPath, suites, ... }: {
imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal-new-kernel.nix" ];
# avoid unwanted systemd service startups
# all strings in disabledModules get appended to modulesPath
# so convert each to list which can be coerced to string
disabledModules = map lib.singleton suites.allProfiles;
nix.registry = lib.mapAttrs (n: v: { flake = v; }) inputs;
isoImage.isoBaseName = "nixos-" + config.networking.hostName;
isoImage.contents = [{
source = self;
target = "/devos/";
}];
isoImage.storeContents = [
self.devShell.${config.nixpkgs.system}
# include also closures that are "switched off" by the
# above profile filter on the local config attribute
fullHostConfig.system.build.toplevel
];
# still pull in tools of deactivated profiles
environment.systemPackages = fullHostConfig.environment.systemPackages;
# confilcts with networking.wireless which might be slightly
# more useful on a stick
networking.networkmanager.enable = lib.mkForce false;
# confilcts with networking.wireless
networking.wireless.iwd.enable = lib.mkForce false;
# Set up a link-local boostrap network
# See also: https://github.com/NixOS/nixpkgs/issues/75515#issuecomment-571661659
networking.usePredictableInterfaceNames = lib.mkForce true; # so prefix matching works
networking.useNetworkd = lib.mkForce true;
networking.useDHCP = lib.mkForce false;
networking.dhcpcd.enable = lib.mkForce false;
systemd.network = {
# https://www.freedesktop.org/software/systemd/man/systemd.network.html
networks."boostrap-link-local" = {
matchConfig = {
Name = "en* wl* ww*";
};
networkConfig = {
Description = "Link-local host bootstrap network";
MulticastDNS = true;
LinkLocalAddressing = "ipv6";
DHCP = "yes";
};
address = [
# fall back well-known link-local for situations where MulticastDNS is not available
"fe80::47" # 47: n=14 i=9 x=24; n+i+x
];
extraConfig = ''
# Unique, yet stable. Based off the MAC address.
IPv6LinkLocalAddressGenerationMode = "eui64"
'';
};
};
};
}

View File

@ -1,6 +0,0 @@
{ lib, deploy, devshell }:
{
tests = import ./tests { inherit lib deploy; };
shell = import ./shell { inherit lib devshell deploy; };
}

View File

@ -1,55 +0,0 @@
{ lib, devshell, deploy }:
{ pkgs }:
let
overlays = [
devshell.overlay
(final: prev: {
deploy-rs =
deploy.packages.${prev.system}.deploy-rs;
})
];
pkgs' = import pkgs.path {
inherit (pkgs) system;
inherit overlays;
};
flk = pkgs'.callPackage ./flk.nix { };
installPkgs = (lib.nixosSystem {
inherit (pkgs') system;
modules = [ ];
}).config.system.build;
in
pkgs'.devshell.mkShell {
imports = [ (pkgs'.devshell.importTOML ./devshell.toml) ];
packages = with installPkgs; [
nixos-install
nixos-generate-config
nixos-enter
];
git.hooks = {
pre-commit.text = lib.fileContents ./pre-commit.sh;
};
commands = with pkgs'; [
{ package = flk; }
{
name = "nix";
help = pkgs'.nixFlakes.meta.description;
command = ''
${pkgs'.nixFlakes}/bin/nix --experimental-features "nix-command flakes ca-references" "${"\${@}"}"
'';
}
]
++ lib.optional (system != "i686-linux") { package = cachix; }
++ lib.optional (system == "x86_64-linux") {
name = "deploy";
package = deploy-rs;
help = "A simple multi-profile Nix-flake deploy tool.";
};
}

View File

@ -1,29 +0,0 @@
imports = [ "git.hooks" ]
[devshell]
packages = [
"git-crypt"
]
[[commands]]
package = "git"
category = "vcs"
[[commands]]
package = "nixpkgs-fmt"
category = "linters"
[[commands]]
package = "editorconfig-checker"
category = "linters"
[[commands]]
package = "python3Packages.grip"
category = "documentation"
[[commands]]
package = "mdbook"
category = "documentation"
[git.hooks]
enable = true

View File

@ -1,23 +0,0 @@
{ stdenv }:
let
name = "flk";
in
stdenv.mkDerivation {
inherit name;
src = ./flk.sh;
dontUnpack = true;
dontBuild = true;
installPhase = ''
mkdir -p $out/bin
install $src $out/bin/${name}
'';
checkPhase = ''
${stdenv.shell} -n -O extglob $out/bin/${name}
'';
meta.description = "Build, deploy, and install NixOS";
}

View File

@ -1,98 +0,0 @@
#!/usr/bin/env bash
[[ -d "$DEVSHELL_ROOT" ]] ||
{
echo "This script must be run from devos's devshell" >&2
exit 1
}
shopt -s extglob
HOSTNAME="$(hostname)"
usage () {
printf "%b\n" \
"\e[4mUsage\e[0m: $(basename $0) COMMAND [ARGS]\n" \
"\e[4mCommands\e[0m:"
printf " %-30s %s\n\n" \
"up" "Generate $DEVSHELL_ROOT/hosts/up-$HOSTNAME.nix" \
"update [INPUT]" "Update and commit the lock file, or specific input" \
"get (core|community) [DEST]" "Copy the desired template to DEST" \
"iso HOST" "Generate an ISO image of HOST" \
"install HOST [ARGS]" "Shortcut for nixos-install" \
"home HOST USER [switch]" "Home-manager config of USER from HOST" \
"HOST (switch|boot|test)" "Shortcut for nixos-rebuild"
}
case "$1" in
""|"-h"|"help"|*(-)"help")
usage
;;
"up")
mkdir -p "$DEVSHELL_ROOT/up"
nixos-generate-config --dir "$DEVSHELL_ROOT/up/$HOSTNAME"
printf "%s\n" \
"{ suites, ... }:" \
"{" \
" imports = [" \
" ../up/$HOSTNAME/configuration.nix" \
" ] ++ suites.core;" \
"}" > "$DEVSHELL_ROOT/hosts/up-$HOSTNAME.nix"
git add -f \
"$DEVSHELL_ROOT/up/$HOSTNAME" \
"$DEVSHELL_ROOT/hosts/up-$HOSTNAME.nix"
;;
"update")
if [[ -n "$2" ]]; then
if [[ -n "$3" ]]; then
(cd $2; nix flake list-inputs --update-input "$3")
else
(cd $2; nix flake update)
fi
nix flake list-inputs --update-input "$2" "$DEVSHELL_ROOT"
else
nix flake update "$DEVSHELL_ROOT"
fi
;;
"get")
if [[ "$2" == "core" || "$2" == "community" ]]; then
nix flake new -t "github:divnix/devos/$2" "${3:-flk}"
else
echo "flk get (core|community) [DEST]"
exit 1
fi
;;
"iso")
nix build \
"$DEVSHELL_ROOT#nixosConfigurations.$2.config.system.build.iso" \
"${@:3}"
;;
"install")
sudo nixos-install --flake "$DEVSHELL_ROOT#$2" "${@:3}"
;;
"home")
ref="$DEVSHELL_ROOT/#homeConfigurations.$3@$2.activationPackage"
if [[ "$4" == "switch" ]]; then
nix build "$ref" && result/activate &&
unlink result
else
nix build "$ref" "${@:4}"
fi
;;
*)
sudo nixos-rebuild --flake "$DEVSHELL_ROOT#$1" "${@:2}"
;;
esac

View File

@ -1,29 +0,0 @@
#!/usr/bin/env bash
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=$(${git}/bin/git hash-object -t tree /dev/null)
fi
diff="git diff-index --name-only --cached $against --diff-filter d"
nix_files=($($diff -- '*.nix'))
all_files=($($diff))
# Format staged nix files.
if [[ -n "${nix_files[@]}" ]]; then
nixpkgs-fmt "${nix_files[@]}" \
&& git add "${nix_files[@]}"
fi
# check editorconfig
editorconfig-checker -- "${all_files[@]}"
if [[ $? != '0' ]]; then
printf "%b\n" \
"\nCode is not aligned with .editorconfig" \
"Review the output and commit your fixes" >&2
exit 1
fi

View File

@ -1,56 +0,0 @@
{ lib, deploy }:
let
mkChecks = { pkgs, hosts, nodes, homes ? { } }:
let
deployHosts = lib.filterAttrs
(n: _: hosts.${n}.config.nixpkgs.system == pkgs.system)
nodes;
deployChecks = deploy.lib.${pkgs.system}.deployChecks { nodes = deployHosts; };
tests =
lib.optionalAttrs (deployHosts != { })
{
profilesTest = profilesTest {
inherit pkgs;
host = hosts.${(builtins.head (builtins.attrNames deployHosts))};
};
} // lib.mapAttrs (n: v: v.activationPackage) homes;
in
lib.recursiveUpdate tests deployChecks;
mkTest = { pkgs, host }:
let
nixosTesting =
(import "${toString pkgs.path}/nixos/lib/testing-python.nix" {
inherit (pkgs) system;
inherit (host.config.lib.builderArgs) specialArgs;
inherit pkgs;
extraConfigurations = host._module.args.modules;
});
in
test:
let
loadedTest =
if builtins.typeOf test == "path"
then import test
else test;
calledTest =
if pkgs.lib.isFunction loadedTest
then pkgs.callPackage loadedTest { }
else loadedTest;
in
nixosTesting.makeTest calledTest;
profilesTest = args@{ host, ... }: mkTest args {
name = "profiles";
machine = { suites, ... }: {
imports = suites.allProfiles;
};
testScript = ''
${host.config.networking.hostName}.systemctl("is-system-running --wait")
'';
};
in
{ inherit mkTest profilesTest mkChecks; }

View File

@ -1,93 +0,0 @@
{ pkgs, lib, ... }:
with lib;
lib.runTests {
testConcatAttrs = {
expr = concatAttrs [{ foo = 1; } { bar = 2; } { baz = 3; }];
expected = { foo = 1; bar = 2; baz = 3; };
};
testGenAttrs' = {
expr = genAttrs'
[ "/foo/bar" "/baz/buzz" ]
(path: {
name = baseNameOf path;
value = "${path}/fizz";
});
expected = { bar = "/foo/bar/fizz"; buzz = "/baz/buzz/fizz"; };
};
testMapFilterAttrs = {
expr = mapFilterAttrs
(n: v: n == "foobar" && v == 1)
(n: v: lib.nameValuePair ("${n}bar") (v + 1))
{ foo = 0; bar = 2; };
expected = { foobar = 1; };
};
testPathsIn = {
expr = pathsIn (toString ./testPathsIn);
expected = map toString [
./testPathsIn/bar
./testPathsIn/baz
./testPathsIn/foo
];
};
testPathsToImportedAttrs = {
expr =
pathsToImportedAttrs [
(toString ./testPathsToImportedAttrs/dir)
./testPathsToImportedAttrs/foo.nix
./testPathsToImportedAttrs/bar.nix
./testPathsToImportedAttrs/t.nix
./testPathsToImportedAttrs/f.nix
];
expected = {
dir = { a = 5; };
foo = { bar = 1; };
bar = { foo = 2; };
t = true;
f = false;
};
};
testRgxToString = lib.testAllTrue [
(rgxToString ".+x" "vxk" == "vx")
(rgxToString "^fo" "foo" == "fo")
(rgxToString "a?" "a" == "a")
(rgxToString "hat" "foohatbar" == "hat")
];
testSafeReadDir = {
expr = safeReadDir ./profiles // safeReadDir ./nonexistentdir;
expected = {
foo = "directory";
t = "directory";
};
};
testSuites =
let
profiles = os.mkProfileAttrs (toString ./profiles);
users = "";
userProfiles = "";
suites = { profiles, ... }: {
system.bar = [ profiles.foo ];
};
in
{
expr = os.mkSuites { inherit profiles users userProfiles suites; };
expected = {
system = {
bar = [ profiles.foo.default ];
allProfiles = [ profiles.foo.default profiles.t.default ];
allUsers = [ ];
};
};
};
}

View File

@ -1,20 +0,0 @@
{ lib }:
{
# returns matching part of _regex_ _string_; null indicates failure.
rgxToString = regex: string:
let
match =
let
head = lib.substring 0 1 regex;
sec = lib.substring 1 2 regex;
in
if head == "^"
|| head == "."
|| (sec == "*" || sec == "+" || sec == "?")
then builtins.match "(${regex}).*" string
else builtins.match ".*(${regex}).*" string;
in
if lib.isList match
then lib.head match
else null;
}

View File

@ -1,27 +0,0 @@
{ pkgs, lib }:
pkgs.runCommandNoCC "devos-lib-tests"
{
buildInputs = [
pkgs.nix
(
let tests = import ./lib.nix { inherit pkgs lib; }; in
if tests == [ ] then null
else throw (builtins.toJSON tests)
)
];
} ''
datadir="${pkgs.nix}/share"
export TEST_ROOT=$(pwd)/test-tmp
export NIX_BUILD_HOOK=
export NIX_CONF_DIR=$TEST_ROOT/etc
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix
export NIX_STORE_DIR=$TEST_ROOT/store
export PAGER=cat
cacheDir=$TEST_ROOT/binary-cache
nix-store --init
touch $out
''

View File

@ -1,70 +0,0 @@
{ pkgs, lib }:
with lib;
lib.runTests {
testConcatAttrs = {
expr = concatAttrs [{ foo = 1; } { bar = 2; } { baz = 3; }];
expected = { foo = 1; bar = 2; baz = 3; };
};
testGenAttrs' = {
expr = genAttrs'
[ "/foo/bar" "/baz/buzz" ]
(path: {
name = baseNameOf path;
value = "${path}/fizz";
});
expected = { bar = "/foo/bar/fizz"; buzz = "/baz/buzz/fizz"; };
};
testMapFilterAttrs = {
expr = mapFilterAttrs
(n: v: n == "foobar" && v == 1)
(n: v: lib.nameValuePair ("${n}bar") (v + 1))
{ foo = 0; bar = 2; };
expected = { foobar = 1; };
};
testPathsIn = {
expr = pathsIn (toString ./testPathsIn);
expected = map toString [
./testPathsIn/bar
./testPathsIn/baz
./testPathsIn/foo
];
};
testRgxToString = lib.testAllTrue [
(rgxToString ".+x" "vxk" == "vx")
(rgxToString "^fo" "foo" == "fo")
(rgxToString "a?" "a" == "a")
(rgxToString "hat" "foohatbar" == "hat")
];
testSafeReadDir = {
expr = safeReadDir ./profiles // safeReadDir ./nonexistentdir;
expected = {
foo = "directory";
t = "directory";
};
};
testSuites = {
expr = mkSuites {
suites = { profiles, ... }: with profiles; {
bar = [ foo ];
};
profiles = [ (./profiles) ];
};
expected = {
bar = [ (toString ./profiles/foo) ];
allProfiles = [
(toString ./profiles/foo)
(toString ./profiles/t)
];
};
};
}

View File

@ -1,3 +0,0 @@
{
bar = 5;
}

View File

@ -1 +0,0 @@

View File

@ -1 +0,0 @@
{ foo = 2; }

View File

@ -1 +0,0 @@
{ a = 5; }

View File

@ -1 +0,0 @@
true && false

View File

@ -1 +0,0 @@
{ bar = 1; }

View File

@ -1 +0,0 @@
true || false