Merge branch 'refactor/snowflake' into v0.2.6-alpha
This commit is contained in:
commit
e7fdbf416c
30 changed files with 958 additions and 324 deletions
53
flake.lock
generated
53
flake.lock
generated
|
|
@ -9,11 +9,11 @@
|
|||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1766051518,
|
||||
"narHash": "sha256-znKOwPXQnt3o7lDb3hdf19oDo0BLP4MfBOYiWkEHoik=",
|
||||
"lastModified": 1770019181,
|
||||
"narHash": "sha256-hwsYgDnby50JNVpTRYlF3UR/Rrpt01OrxVuryF40CFY=",
|
||||
"owner": "serokell",
|
||||
"repo": "deploy-rs",
|
||||
"rev": "d5eff7f948535b9c723d60cd8239f8f11ddc90fa",
|
||||
"rev": "77c906c0ba56aabdbc72041bf9111b565cdd6171",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -68,11 +68,11 @@
|
|||
"spectrum": "spectrum"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1771365290,
|
||||
"narHash": "sha256-1XJOslVyF7yzf6yd/yl1VjGLywsbtwmQh3X1LuJcLI4=",
|
||||
"lastModified": 1773018425,
|
||||
"narHash": "sha256-fpgZBmZpKoEXEowBK/6m8g9FcOLWQ4UxhXHqCw2CpSM=",
|
||||
"owner": "microvm-nix",
|
||||
"repo": "microvm.nix",
|
||||
"rev": "789c90b164b55b4379e7a94af8b9c01489024c18",
|
||||
"rev": "25ebda3c558e923720c965832dc9a04f559a055c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -129,11 +129,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1768323494,
|
||||
"narHash": "sha256-yBXJLE6WCtrGo7LKiB6NOt6nisBEEkguC/lq/rP3zRQ=",
|
||||
"lastModified": 1773375660,
|
||||
"narHash": "sha256-SEzUWw2Rf5Ki3bcM26nSKgbeoqi2uYy8IHVBqOKjX3w=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2c3e5ec5df46d3aeee2a1da0bfedd74e21f4bf3a",
|
||||
"rev": "3e20095fe3c6cbb1ddcef89b26969a69a1570776",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -166,11 +166,11 @@
|
|||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1770975056,
|
||||
"narHash": "sha256-ZXTz/P3zUbbM6lNXzt91u8EwfNqhXpYMu8+wvFZqQHE=",
|
||||
"lastModified": 1773738366,
|
||||
"narHash": "sha256-oH22HyNHEdCoCQo734sQCHUr6C0jmGQJMZ13dsgEHkk=",
|
||||
"owner": "cry128",
|
||||
"repo": "nt",
|
||||
"rev": "f42dcdd49a7921a7f433512e83d5f93696632412",
|
||||
"rev": "f32c3a726a3d608d30aaaa1df2301c1eaf5ef8f4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -185,17 +185,38 @@
|
|||
"microvm": "microvm",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nt": "nt",
|
||||
"sops-nix": "sops-nix",
|
||||
"systems": "systems_3"
|
||||
}
|
||||
},
|
||||
"sops-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773096132,
|
||||
"narHash": "sha256-M3zEnq9OElB7zqc+mjgPlByPm1O5t2fbUrH3t/Hm5Ag=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "d1ff3b1034d5bab5d7d8086a7803c5a5968cd784",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"spectrum": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1759482047,
|
||||
"narHash": "sha256-H1wiXRQHxxPyMMlP39ce3ROKCwI5/tUn36P8x6dFiiQ=",
|
||||
"lastModified": 1772189877,
|
||||
"narHash": "sha256-i1p90Rgssb//aNiTDFq46ZG/fk3LmyRLChtp/9lddyA=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "c5d5786d3dc938af0b279c542d1e43bce381b4b9",
|
||||
"revCount": 996,
|
||||
"rev": "fe39e122d898f66e89ffa17d4f4209989ccb5358",
|
||||
"revCount": 1255,
|
||||
"type": "git",
|
||||
"url": "https://spectrum-os.org/git/spectrum"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
nt,
|
||||
...
|
||||
} @ inputs:
|
||||
import ./cerulean
|
||||
import ./nix
|
||||
{
|
||||
inherit inputs self nt;
|
||||
inherit (nt) mix;
|
||||
|
|
|
|||
|
|
@ -15,22 +15,28 @@
|
|||
mix,
|
||||
inputs,
|
||||
...
|
||||
} @ args:
|
||||
mix.newMixture args (mixture: {
|
||||
submods.public = [
|
||||
./snow
|
||||
];
|
||||
} @ args: let
|
||||
mixArgs =
|
||||
args
|
||||
// {
|
||||
inherit (inputs.nixpkgs) lib;
|
||||
};
|
||||
in
|
||||
mix.newMixture mixArgs (mixture: {
|
||||
submods.public = [
|
||||
./snow
|
||||
];
|
||||
|
||||
version = "0.2.6-alpha";
|
||||
version = "0.2.6-alpha";
|
||||
|
||||
overlays = [
|
||||
# build deploy-rs as a package not from the flake input,
|
||||
# hence we can rely on a nixpkg binary cache.
|
||||
inputs.deploy-rs.overlays.default
|
||||
];
|
||||
overlays = [
|
||||
# build deploy-rs as a package not from the flake input,
|
||||
# hence we can rely on a nixpkg binary cache.
|
||||
inputs.deploy-rs.overlays.default
|
||||
];
|
||||
|
||||
nixosModules = rec {
|
||||
default = cerulean;
|
||||
cerulean = ./nixos;
|
||||
};
|
||||
})
|
||||
nixosModules = rec {
|
||||
default = cerulean;
|
||||
cerulean = ./nixos;
|
||||
};
|
||||
})
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@
|
|||
node,
|
||||
pkgs,
|
||||
lib,
|
||||
_cerulean,
|
||||
_snow,
|
||||
...
|
||||
} @ args: {
|
||||
imports =
|
||||
[
|
||||
_cerulean.inputs.sops-nix.nixosModules.sops
|
||||
# _cerulean.inputs.microvm.nixosModules.microvm
|
||||
_snow.inputs.sops-nix.nixosModules.sops
|
||||
# _snow.inputs.microvm.nixosModules.microvm
|
||||
|
||||
# add support for `options.legacyImports`
|
||||
# ./legacy-imports.nix
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
(import /${root}/nixpkgs.nix)
|
||||
]
|
||||
# homemanager options declarations
|
||||
++ (lib.optional (_cerulean.homeManager != null) ./home.nix)
|
||||
++ (lib.optional (_snow.homeManager != null) ./home.nix)
|
||||
# remote deployment configuration
|
||||
++ (lib.optional (node.deploy.ssh.host != null) ./remote-deploy);
|
||||
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
(with pkgs; [
|
||||
sops
|
||||
])
|
||||
++ (with _cerulean.inputs; [
|
||||
++ (with _snow.inputs; [
|
||||
deploy-rs.packages.${system}.default
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
{
|
||||
_cerulean,
|
||||
_snow,
|
||||
config,
|
||||
root,
|
||||
lib,
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
;
|
||||
in {
|
||||
imports = [
|
||||
_cerulean.homeManager.nixosModules.default
|
||||
_snow.homeManager.nixosModules.default
|
||||
];
|
||||
|
||||
options = {
|
||||
|
|
@ -69,7 +69,7 @@ in {
|
|||
_module.args.username = name;
|
||||
});
|
||||
|
||||
extraSpecialArgs = _cerulean.specialArgs;
|
||||
extraSpecialArgs = _snow.specialArgs;
|
||||
sharedModules = [
|
||||
../home
|
||||
|
||||
|
|
|
|||
|
|
@ -12,180 +12,16 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
{
|
||||
this,
|
||||
self,
|
||||
inputs,
|
||||
systems,
|
||||
nt,
|
||||
mix,
|
||||
...
|
||||
} @ args: let
|
||||
inherit
|
||||
(builtins)
|
||||
all
|
||||
attrNames
|
||||
elem
|
||||
mapAttrs
|
||||
warn
|
||||
;
|
||||
} @ args:
|
||||
mix.newMixture (removeAttrs args ["this"]) (mixture: {
|
||||
submods.public = [
|
||||
./lib
|
||||
];
|
||||
|
||||
inherit (inputs.nixpkgs) lib;
|
||||
|
||||
inherit (nt) findImport;
|
||||
in
|
||||
mix.newMixture args (mixture: let
|
||||
inherit (mixture) mapNodes;
|
||||
in {
|
||||
includes.private = [
|
||||
./lib/nodes.nix
|
||||
];
|
||||
|
||||
inherit findImport;
|
||||
|
||||
# snow.flake
|
||||
flake = flakeInputs: root: let
|
||||
module = lib.evalModules {
|
||||
class = "snowflake";
|
||||
# TODO: abort if inputs contains reserved names
|
||||
specialArgs =
|
||||
(flakeInputs
|
||||
// {
|
||||
inherit systems root;
|
||||
inherit (this) snow;
|
||||
inputs = flakeInputs;
|
||||
})
|
||||
|> (x: builtins.removeAttrs x ["self" "nodes"]);
|
||||
|
||||
modules = [
|
||||
./module.nix
|
||||
({config, ...}: {
|
||||
_module.args = {
|
||||
self = config;
|
||||
nodes = config.nodes.nodes;
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
nodes = module.config.nodes;
|
||||
in rec {
|
||||
nixosConfigurations = mapNodes nodes (
|
||||
{
|
||||
base,
|
||||
lib,
|
||||
name,
|
||||
node,
|
||||
groupModules,
|
||||
...
|
||||
}: let
|
||||
homeManager =
|
||||
if node.homeManager != null
|
||||
then node.homeManager
|
||||
else if nodes.homeManager != null
|
||||
then nodes.homeManager
|
||||
else
|
||||
warn ''
|
||||
[snowflake] Neither `nodes.homeManager` nor `nodes.nodes.${name}.homeManager` were specified!
|
||||
[snowflake] home-manager will NOT be used! User configuration will be ignored!
|
||||
''
|
||||
null;
|
||||
|
||||
userArgs = nodes.args // node.args;
|
||||
ceruleanArgs = {
|
||||
inherit systems root base nodes node;
|
||||
inherit (node) system;
|
||||
inherit (this) snow;
|
||||
hostname = name;
|
||||
|
||||
_cerulean = {
|
||||
inherit inputs userArgs ceruleanArgs homeManager;
|
||||
specialArgs = userArgs // ceruleanArgs;
|
||||
};
|
||||
};
|
||||
specialArgs = assert (userArgs
|
||||
|> attrNames
|
||||
|> all (argName:
|
||||
! ceruleanArgs ? argName
|
||||
|| abort ''
|
||||
`specialArgs` are like super important to Cerulean my love... </3
|
||||
But `args.${argName}` is a reserved argument name :(
|
||||
''));
|
||||
ceruleanArgs._cerulean.specialArgs;
|
||||
in
|
||||
lib.nixosSystem {
|
||||
inherit (node) system;
|
||||
inherit specialArgs;
|
||||
modules =
|
||||
[
|
||||
self.nixosModules.default
|
||||
(findImport /${root}/hosts/${name})
|
||||
]
|
||||
++ (groupModules root)
|
||||
++ node.modules
|
||||
++ nodes.modules;
|
||||
}
|
||||
);
|
||||
|
||||
deploy.nodes = mapNodes nodes ({
|
||||
name,
|
||||
node,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(node.deploy)
|
||||
ssh
|
||||
user
|
||||
interactiveSudo
|
||||
remoteBuild
|
||||
rollback
|
||||
autoRollback
|
||||
magicRollback
|
||||
activationTimeout
|
||||
confirmTimeout
|
||||
;
|
||||
|
||||
nixosFor = system: inputs.deploy-rs.lib.${system}.activate.nixos;
|
||||
in {
|
||||
hostname =
|
||||
if ssh.host != null
|
||||
then ssh.host
|
||||
else "";
|
||||
|
||||
profilesOrder = ["default"]; # profiles priority
|
||||
profiles.default = {
|
||||
path = nixosFor node.system nixosConfigurations.${name};
|
||||
|
||||
user = user;
|
||||
sudo = "sudo -u";
|
||||
interactiveSudo = interactiveSudo;
|
||||
|
||||
fastConnection = false;
|
||||
|
||||
autoRollback = autoRollback -> rollback;
|
||||
magicRollback = magicRollback -> rollback;
|
||||
activationTimeout = activationTimeout;
|
||||
confirmTimeout = confirmTimeout;
|
||||
|
||||
remoteBuild = remoteBuild;
|
||||
sshUser = ssh.user;
|
||||
sshOpts =
|
||||
ssh.opts
|
||||
++ (
|
||||
if elem "-p" ssh.opts
|
||||
then []
|
||||
else ["-p" (toString ssh.port)]
|
||||
)
|
||||
++ (
|
||||
if elem "-A" ssh.opts
|
||||
then []
|
||||
else ["-A"]
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
checks =
|
||||
inputs.deploy-rs.lib
|
||||
|> mapAttrs (system: deployLib:
|
||||
deployLib.deployChecks deploy);
|
||||
};
|
||||
})
|
||||
includes.public = [
|
||||
./flake
|
||||
];
|
||||
})
|
||||
|
|
|
|||
68
nix/snow/flake/default.nix
Normal file
68
nix/snow/flake/default.nix
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
self,
|
||||
this,
|
||||
inputs,
|
||||
systems,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(builtins)
|
||||
attrNames
|
||||
concatStringsSep
|
||||
filter
|
||||
length
|
||||
warn
|
||||
;
|
||||
|
||||
inherit (inputs.nixpkgs) lib;
|
||||
in {
|
||||
# snow.flake
|
||||
# XXX: TODO: stop taking in root as parameter (maybe take self instead?)
|
||||
flake = flakeInputs: root: let
|
||||
snowflake = lib.evalModules {
|
||||
class = "snowflake";
|
||||
specialArgs = let
|
||||
reservedSpecialArgs = {
|
||||
# inherit (this) snow;
|
||||
snow = this;
|
||||
inherit systems root;
|
||||
inputs = flakeInputs;
|
||||
|
||||
_snowFlake = {
|
||||
inherit self inputs;
|
||||
};
|
||||
};
|
||||
|
||||
warnIfReserved = let
|
||||
getReservedNames = names:
|
||||
reservedSpecialArgs
|
||||
|> attrNames
|
||||
|> filter (name: names?${name});
|
||||
|
||||
reservedNames =
|
||||
flakeInputs
|
||||
|> attrNames
|
||||
|> getReservedNames;
|
||||
in
|
||||
(length reservedNames == 0)
|
||||
|| warn ''
|
||||
[snow] Your `flake.nix` declares inputs with reserved names!
|
||||
[snow] These will be accessible only via `inputs.''${NAME}`
|
||||
[snow] Please rename the following:
|
||||
[snow] ${concatStringsSep reservedNames ", "}
|
||||
''
|
||||
true;
|
||||
in
|
||||
assert warnIfReserved;
|
||||
flakeInputs // reservedSpecialArgs;
|
||||
|
||||
modules = [
|
||||
./nodes
|
||||
./modules
|
||||
./outputs
|
||||
(this.lib.findImport /${root}/snow)
|
||||
];
|
||||
};
|
||||
in
|
||||
snowflake.config.outputs;
|
||||
}
|
||||
3
nix/snow/flake/modules/README.md
Normal file
3
nix/snow/flake/modules/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Snow Module Backend
|
||||
This source code was tedious so it's just a modified version of the module backend of
|
||||
[github:hercules-ci/flake-parts](https://github.com/hercules-ci/flake-parts/tree/main/modules).
|
||||
69
nix/snow/flake/modules/apps.nix
Normal file
69
nix/snow/flake/modules/apps.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
lib,
|
||||
snow,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
|
||||
inherit
|
||||
(snow.lib)
|
||||
mkPerSystemFlakeOutput
|
||||
;
|
||||
|
||||
derivationType =
|
||||
lib.types.package
|
||||
// {
|
||||
check = lib.isDerivation;
|
||||
};
|
||||
|
||||
programType = lib.types.coercedTo derivationType lib.getExe lib.types.str;
|
||||
|
||||
appType = lib.types.submodule {
|
||||
options = {
|
||||
type = mkOption {
|
||||
type = lib.types.enum ["app"];
|
||||
default = "app";
|
||||
description = ''
|
||||
A type tag for `apps` consumers.
|
||||
'';
|
||||
};
|
||||
program = mkOption {
|
||||
type = programType;
|
||||
description = ''
|
||||
A path to an executable or a derivation with `meta.mainProgram`.
|
||||
'';
|
||||
};
|
||||
meta = mkOption {
|
||||
type = types.lazyAttrsOf lib.types.raw;
|
||||
default = {};
|
||||
# TODO refer to Nix manual 2.25
|
||||
description = ''
|
||||
Metadata information about the app.
|
||||
Standardized in Nix at <https://github.com/NixOS/nix/pull/11297>.
|
||||
|
||||
Note: `nix flake check` is only aware of the `description` attribute in `meta`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
mkPerSystemFlakeOutput {
|
||||
name = "apps";
|
||||
option = mkOption {
|
||||
type = types.lazyAttrsOf appType;
|
||||
default = {};
|
||||
description = ''
|
||||
Programs runnable with nix run `<name>`.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
default.program = "''${config.packages.hello}/bin/hello";
|
||||
}
|
||||
'';
|
||||
};
|
||||
file = ./apps.nix;
|
||||
}
|
||||
26
nix/snow/flake/modules/checks.nix
Normal file
26
nix/snow/flake/modules/checks.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
lib,
|
||||
snow,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
inherit
|
||||
(snow.lib)
|
||||
mkPerSystemFlakeOutput
|
||||
;
|
||||
in
|
||||
mkPerSystemFlakeOutput {
|
||||
name = "checks";
|
||||
option = mkOption {
|
||||
type = types.lazyAttrsOf types.package;
|
||||
default = {};
|
||||
description = ''
|
||||
Derivations to be built by [`nix flake check`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake-check.html).
|
||||
'';
|
||||
};
|
||||
file = ./checks.nix;
|
||||
}
|
||||
15
nix/snow/flake/modules/default.nix
Normal file
15
nix/snow/flake/modules/default.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{...}: {
|
||||
imports = [
|
||||
./outputs.nix
|
||||
|
||||
./apps.nix
|
||||
./checks.nix
|
||||
./devShells.nix
|
||||
./formatter.nix
|
||||
./legacyPackages.nix
|
||||
./nixosConfigurations.nix
|
||||
./nixosModules.nix
|
||||
./overlays.nix
|
||||
./packages.nix
|
||||
];
|
||||
}
|
||||
35
nix/snow/flake/modules/devShells.nix
Normal file
35
nix/snow/flake/modules/devShells.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
lib,
|
||||
snow,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
literalExpression
|
||||
;
|
||||
inherit
|
||||
(snow.lib)
|
||||
mkPerSystemFlakeOutput
|
||||
;
|
||||
in
|
||||
mkPerSystemFlakeOutput {
|
||||
name = "devShells";
|
||||
option = mkOption {
|
||||
type = types.lazyAttrsOf types.package;
|
||||
default = {};
|
||||
description = ''
|
||||
An attribute set of packages to be used as shells.
|
||||
[`nix develop .#<name>`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-develop.html) will run `devShells.<name>`.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
default = pkgs.mkShell {
|
||||
nativeBuildInputs = with pkgs; [ wget bat cargo ];
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
file = ./devShells.nix;
|
||||
}
|
||||
26
nix/snow/flake/modules/formatter.nix
Normal file
26
nix/snow/flake/modules/formatter.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
lib,
|
||||
snow,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
inherit
|
||||
(snow.lib)
|
||||
mkPerSystemFlakeOutput
|
||||
;
|
||||
in
|
||||
mkPerSystemFlakeOutput {
|
||||
name = "formatter";
|
||||
option = mkOption {
|
||||
type = types.nullOr types.package;
|
||||
default = null;
|
||||
description = ''
|
||||
A package used by [`nix fmt`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-fmt.html).
|
||||
'';
|
||||
};
|
||||
file = ./apps.nix;
|
||||
}
|
||||
26
nix/snow/flake/modules/legacyPackages.nix
Normal file
26
nix/snow/flake/modules/legacyPackages.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
lib,
|
||||
snow,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
inherit
|
||||
(snow.lib)
|
||||
mkPerSystemFlakeOutput
|
||||
;
|
||||
in
|
||||
mkPerSystemFlakeOutput {
|
||||
name = "legacyPackages";
|
||||
option = mkOption {
|
||||
type = types.lazyAttrsOf types.raw;
|
||||
default = {};
|
||||
description = ''
|
||||
Used for nixpkgs packages, also accessible via `nix build .#<name>` [`nix build .#<name>`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-build.html).
|
||||
'';
|
||||
};
|
||||
file = ./legacyPackages.nix;
|
||||
}
|
||||
35
nix/snow/flake/modules/nixosConfigurations.nix
Normal file
35
nix/snow/flake/modules/nixosConfigurations.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{lib, ...}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
literalExpression
|
||||
;
|
||||
in {
|
||||
options = {
|
||||
outputs.nixosConfigurations = mkOption {
|
||||
type = types.lazyAttrsOf types.raw;
|
||||
default = {};
|
||||
description = ''
|
||||
Instantiated NixOS configurations. Used by `nixos-rebuild`.
|
||||
|
||||
`nixosConfigurations` is for specific machines. If you want to expose
|
||||
reusable configurations, add them to [`nixosModules`](#opt-flake.nixosModules)
|
||||
in the form of modules (no `lib.nixosSystem`), so that you can reference
|
||||
them in this or another flake's `nixosConfigurations`.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
my-machine = inputs.nixpkgs.lib.nixosSystem {
|
||||
# system is not needed with freshly generated hardware-configuration.nix
|
||||
# system = "x86_64-linux"; # or set nixpkgs.hostPlatform in a module.
|
||||
modules = [
|
||||
./my-machine/nixos-configuration.nix
|
||||
config.nixosModules.my-module
|
||||
];
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
29
nix/snow/flake/modules/nixosModules.nix
Normal file
29
nix/snow/flake/modules/nixosModules.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
lib,
|
||||
moduleLocation,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mapAttrs
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
in {
|
||||
options = {
|
||||
outputs.nixosModules = mkOption {
|
||||
type = types.lazyAttrsOf types.deferredModule;
|
||||
default = {};
|
||||
apply = mapAttrs (k: v: {
|
||||
_class = "nixos";
|
||||
_file = "${toString moduleLocation}#nixosModules.${k}";
|
||||
imports = [v];
|
||||
});
|
||||
description = ''
|
||||
NixOS modules.
|
||||
|
||||
You may use this for reusable pieces of configuration, service modules, etc.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
46
nix/snow/flake/modules/outputs.nix
Normal file
46
nix/snow/flake/modules/outputs.nix
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
in {
|
||||
options = {
|
||||
outputs = mkOption {
|
||||
type = types.submoduleWith {
|
||||
modules = [
|
||||
{
|
||||
freeformType =
|
||||
types.lazyAttrsOf
|
||||
(types.unique
|
||||
{
|
||||
message = ''
|
||||
No option has been declared for this flake output attribute, so its definitions can't be merged automatically.
|
||||
Possible solutions:
|
||||
- Load a module that defines this flake output attribute
|
||||
- Declare an option for this flake output attribute
|
||||
- Make sure the output attribute is spelled correctly
|
||||
- Define the value only once, with a single definition in a single module
|
||||
'';
|
||||
}
|
||||
types.raw);
|
||||
}
|
||||
];
|
||||
};
|
||||
description = ''
|
||||
Raw flake output attributes. Any attribute can be set here, but some
|
||||
attributes are represented by options, to provide appropriate
|
||||
configuration merging.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
# ensure a minimal version is set
|
||||
outputs = {};
|
||||
};
|
||||
}
|
||||
31
nix/snow/flake/modules/overlays.nix
Normal file
31
nix/snow/flake/modules/overlays.nix
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{lib, ...}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
in {
|
||||
options = {
|
||||
outputs.overlays = mkOption {
|
||||
# uniq -> ordered: https://github.com/NixOS/nixpkgs/issues/147052
|
||||
# also update description when done
|
||||
type = types.lazyAttrsOf (types.uniq (types.functionTo (types.functionTo (types.lazyAttrsOf types.unspecified))));
|
||||
# This eta expansion exists for the sole purpose of making nix flake check happy.
|
||||
apply = lib.mapAttrs (_k: f: final: prev: f final prev);
|
||||
default = {};
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
default = final: prev: {};
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
An attribute set of [overlays](https://nixos.org/manual/nixpkgs/stable/#chap-overlays).
|
||||
|
||||
Note that the overlays themselves are not mergeable. While overlays
|
||||
can be composed, the order of composition is significant, but the
|
||||
module system does not guarantee sufficiently deterministic
|
||||
definition ordering, across versions and when changing `imports`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
29
nix/snow/flake/modules/packages.nix
Normal file
29
nix/snow/flake/modules/packages.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
lib,
|
||||
snow,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
|
||||
inherit
|
||||
(snow.lib)
|
||||
mkPerSystemFlakeOutput
|
||||
;
|
||||
in
|
||||
mkPerSystemFlakeOutput {
|
||||
name = "packages";
|
||||
option = mkOption {
|
||||
type = types.lazyAttrsOf types.package;
|
||||
default = {};
|
||||
description = ''
|
||||
An attribute set of packages to be built by [`nix build`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-build.html).
|
||||
|
||||
`nix build .#<name>` will build `packages.<name>`.
|
||||
'';
|
||||
};
|
||||
file = ./packages.nix;
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
{
|
||||
_snowFlake,
|
||||
lib,
|
||||
specialArgs,
|
||||
...
|
||||
|
|
@ -25,38 +26,20 @@
|
|||
in
|
||||
mkOption {
|
||||
description = ''
|
||||
Cerulean node declarations.
|
||||
Snowflake node declarations.
|
||||
'';
|
||||
type = types.submoduleWith {
|
||||
inherit specialArgs;
|
||||
|
||||
modules = [
|
||||
{
|
||||
imports = [./shared.nix];
|
||||
|
||||
options = {
|
||||
groups = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
example = lib.literalExpression "{ servers = { staging = {}; production = {}; }; }";
|
||||
description = ''
|
||||
Hierarchical groups that nodes can be a member of.
|
||||
'';
|
||||
};
|
||||
|
||||
nodes = mkOption {
|
||||
type = types.attrsOf (types.submoduleWith {
|
||||
inherit specialArgs;
|
||||
modules = [(import ./submodule.nix)];
|
||||
});
|
||||
# example = { ... }; # TODO
|
||||
description = ''
|
||||
Node (host systems) declarations.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
./nodes.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
nodes = {
|
||||
base = _snowFlake.inputs.nixpkgs;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -14,16 +14,24 @@
|
|||
{
|
||||
lib,
|
||||
systems,
|
||||
nodesConfig,
|
||||
groups,
|
||||
groupLibs,
|
||||
...
|
||||
}: {
|
||||
imports = [./shared.nix];
|
||||
|
||||
options = let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
|
||||
inherit
|
||||
(groupLibs)
|
||||
resolveGroupsInheritance
|
||||
;
|
||||
|
||||
flakeRef = types.either types.str types.path;
|
||||
in {
|
||||
enabled = lib.mkOption {
|
||||
type = types.bool;
|
||||
|
|
@ -43,6 +51,65 @@
|
|||
'';
|
||||
};
|
||||
|
||||
base = lib.mkOption {
|
||||
# In newer Nix versions, particularly with lazy trees, outPath of
|
||||
# flakes becomes a Nix-language path object. We deliberately allow this
|
||||
# to gracefully come through the interface in discussion with @roberth.
|
||||
#
|
||||
# See: https://github.com/NixOS/nixpkgs/pull/278522#discussion_r1460292639
|
||||
type = types.nullOr flakeRef;
|
||||
|
||||
default = nodesConfig.base;
|
||||
defaultText = "nodes.base";
|
||||
|
||||
example = lib.literalExpression "inputs.nixpkgs";
|
||||
|
||||
description = ''
|
||||
The path to the nixpkgs source used to build a system. A `base` package set
|
||||
is required to be set, and can be specified via either:
|
||||
1. `options.nodes.base` (default `base` used for all systems)
|
||||
2. `options.nodes.nodes.<name>.base` (takes prescedence over `options.nodes.base`)
|
||||
|
||||
This can also be optionally set if the NixOS system is not built with a flake but still uses
|
||||
pinned sources: set this to the store path for the nixpkgs sources used to build the system,
|
||||
as may be obtained by `fetchTarball`, for example.
|
||||
|
||||
Note: the name of the store path must be "source" due to
|
||||
<https://github.com/NixOS/nix/issues/7075>.
|
||||
'';
|
||||
};
|
||||
|
||||
homeManager = mkOption {
|
||||
type = types.nullOr flakeRef;
|
||||
default = nodesConfig.homeManager;
|
||||
defaultText = "nodes.homeManager";
|
||||
example = lib.literalExpression "inputs.home-manager";
|
||||
description = ''
|
||||
The path to the home-manager source. A `homeManager` flake reference
|
||||
is required to be set for `homes/` to be evaluated, and can be specified via either:
|
||||
1. `options.nodes.homeManager` (default `homManager` used for all systems)
|
||||
2. `options.nodes.nodes.<name>.homeManager` (takes prescedence over `options.nodes.homeManager`)
|
||||
'';
|
||||
};
|
||||
|
||||
modules = mkOption {
|
||||
type = types.listOf types.raw;
|
||||
default = [];
|
||||
example = lib.literalExpression "[ { environment.systemPackages = [ pkgs.git ]; } ]";
|
||||
description = ''
|
||||
Shared modules to import; equivalent to the NixOS module system's `extraModules`.
|
||||
'';
|
||||
};
|
||||
|
||||
args = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
example = lib.literalExpression "{ inherit inputs; }";
|
||||
description = ''
|
||||
Shared args to provided for each node; equivalent to the NixOS module system's `specialArgs`.
|
||||
'';
|
||||
};
|
||||
|
||||
groups = mkOption {
|
||||
# TODO: write a custom group type that validates better than types.attrs lol
|
||||
type = types.functionTo (types.listOf types.attrs);
|
||||
|
|
@ -51,6 +118,9 @@
|
|||
description = ''
|
||||
A function from the `groups` hierarchy to a list of groups this node inherits from.
|
||||
'';
|
||||
|
||||
# apply = groupsFn:
|
||||
# groupsFn nodesConfig.groups |> resolveGroupsInheritance;
|
||||
};
|
||||
|
||||
deploy = {
|
||||
|
|
@ -91,7 +161,7 @@
|
|||
example = false;
|
||||
description = ''
|
||||
Whether to enable interactive sudo (password based sudo).
|
||||
NOT RECOMMENDED. Use one of Cerulean's recommended auth methods instead.
|
||||
NOT RECOMMENDED. Use one of Snowflake's recommended auth methods instead.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -164,7 +234,7 @@
|
|||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "cerubld";
|
||||
default = "snowbld";
|
||||
example = "custom-user";
|
||||
description = ''
|
||||
The user to connect to over ssh during deployment.
|
||||
|
|
@ -183,7 +253,7 @@
|
|||
publicKeys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIeyZuUUmyUYrYaEJwEMvcXqZFYm1NaZab8klOyK6Imr me@puter"];
|
||||
example = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIeyZuUUmyUYrYaEJwEMvcXqZFYm1NaZab8klOyK6Imr me@myputer"];
|
||||
description = ''
|
||||
SSH public keys that will be authorized to the deployment user.
|
||||
This key is intended solely for deployment, allowing for fine-grained permission control.
|
||||
|
|
@ -201,4 +271,33 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
# config = let
|
||||
# throwGotNull = name:
|
||||
# throw ''
|
||||
# [snow] `nodes.<name>.${name}` must be set for all nodes! (got: <null>)
|
||||
# '';
|
||||
# givenSystem =
|
||||
# (config.system != null)
|
||||
# || throwGotNull "system";
|
||||
|
||||
# givenBase =
|
||||
# (config.base != null)
|
||||
# || throwGotNull "base";
|
||||
|
||||
# givenHomeManager =
|
||||
# (config.homeManager != null)
|
||||
# || throwGotNull "homeManager";
|
||||
|
||||
# givenDeployHost =
|
||||
# (config.deploy.ssh.host != null)
|
||||
# || throwGotNull "deploy.ssh.host";
|
||||
# in
|
||||
# assert givenSystem
|
||||
# && givenBase
|
||||
# && givenHomeManager
|
||||
# && givenDeployHost; {
|
||||
# # extend these from the nodes configuration
|
||||
# inherit (nodesConfig) modules args;
|
||||
# };
|
||||
}
|
||||
|
|
@ -11,7 +11,15 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
{lib, ...}: let
|
||||
{
|
||||
_snowFlake,
|
||||
snow,
|
||||
root,
|
||||
lib,
|
||||
config,
|
||||
specialArgs,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
|
|
@ -19,6 +27,11 @@
|
|||
;
|
||||
|
||||
flakeRef = types.either types.str types.path;
|
||||
|
||||
groupLibs = import ./groups.nix {
|
||||
inherit snow root;
|
||||
inherit (_snowFlake.inputs) nt;
|
||||
};
|
||||
in {
|
||||
options = {
|
||||
base = lib.mkOption {
|
||||
|
|
@ -49,6 +62,18 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
homeManager = mkOption {
|
||||
type = types.nullOr flakeRef;
|
||||
default = null;
|
||||
example = lib.literalExpression "inputs.home-manager";
|
||||
description = ''
|
||||
The path to the home-manager source. A `homeManager` flake reference
|
||||
is required to be set for `homes/` to be evaluated, and can be specified via either:
|
||||
1. `options.nodes.homeManager` (default `homManager` used for all systems)
|
||||
2. `options.nodes.nodes.<name>.homeManager` (takes prescedence over `options.nodes.homeManager`)
|
||||
'';
|
||||
};
|
||||
|
||||
modules = mkOption {
|
||||
type = types.listOf types.raw;
|
||||
default = [];
|
||||
|
|
@ -67,15 +92,27 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
homeManager = mkOption {
|
||||
type = types.nullOr flakeRef;
|
||||
default = null;
|
||||
example = lib.literalExpression "inputs.home-manager";
|
||||
groups = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
example = lib.literalExpression "{ servers = { staging = {}; production = {}; }; }";
|
||||
description = ''
|
||||
The path to the home-manager source. A `homeManager` flake reference
|
||||
is required to be set for `homes/` to be evaluated, and can be specified via either:
|
||||
1. `options.nodes.homeManager` (default `homManager` used for all systems)
|
||||
2. `options.nodes.nodes.<name>.homeManager` (takes prescedence over `options.nodes.homeManager`)
|
||||
Hierarchical groups that nodes can be a member of.
|
||||
'';
|
||||
};
|
||||
|
||||
nodes = mkOption {
|
||||
type = types.attrsOf (types.submoduleWith {
|
||||
specialArgs =
|
||||
specialArgs
|
||||
// {
|
||||
nodesConfig = config;
|
||||
inherit groupLibs;
|
||||
};
|
||||
modules = [./node.nix];
|
||||
});
|
||||
description = ''
|
||||
Node (host systems) declarations.
|
||||
'';
|
||||
};
|
||||
};
|
||||
10
nix/snow/flake/outputs/checks.nix
Normal file
10
nix/snow/flake/outputs/checks.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
config,
|
||||
_snowFlake,
|
||||
...
|
||||
}: {
|
||||
outputs.checks =
|
||||
_snowFlake.inputs.deploy-rs.lib
|
||||
|> builtins.mapAttrs (system: deployLib:
|
||||
deployLib.deployChecks config.outputs.deploy);
|
||||
}
|
||||
7
nix/snow/flake/outputs/default.nix
Normal file
7
nix/snow/flake/outputs/default.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{...}: {
|
||||
imports = [
|
||||
./checks.nix
|
||||
./deploy.nix
|
||||
./nixosConfigurations.nix
|
||||
];
|
||||
}
|
||||
63
nix/snow/flake/outputs/deploy.nix
Normal file
63
nix/snow/flake/outputs/deploy.nix
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
_snowFlake,
|
||||
snow,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
outputs.deploy.nodes = snow.lib.mapNodes config.nodes ({
|
||||
name,
|
||||
node,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(node.deploy)
|
||||
ssh
|
||||
user
|
||||
interactiveSudo
|
||||
remoteBuild
|
||||
rollback
|
||||
autoRollback
|
||||
magicRollback
|
||||
activationTimeout
|
||||
confirmTimeout
|
||||
;
|
||||
|
||||
nixosFor = system: _snowFlake.inputs.deploy-rs.lib.${system}.activate.nixos;
|
||||
in {
|
||||
hostname =
|
||||
if ssh.host != null
|
||||
then ssh.host
|
||||
else "";
|
||||
|
||||
profilesOrder = ["default"]; # profiles priority
|
||||
profiles.default = {
|
||||
path = nixosFor node.system config.outputs.nixosConfigurations.${name};
|
||||
|
||||
user = user;
|
||||
sudo = "sudo -u";
|
||||
interactiveSudo = interactiveSudo;
|
||||
|
||||
fastConnection = false;
|
||||
|
||||
autoRollback = autoRollback -> rollback;
|
||||
magicRollback = magicRollback -> rollback;
|
||||
activationTimeout = activationTimeout;
|
||||
confirmTimeout = confirmTimeout;
|
||||
|
||||
remoteBuild = remoteBuild;
|
||||
sshUser = ssh.user;
|
||||
sshOpts =
|
||||
ssh.opts
|
||||
++ (
|
||||
if builtins.elem "-p" ssh.opts
|
||||
then []
|
||||
else ["-p" (toString ssh.port)]
|
||||
)
|
||||
++ (
|
||||
if builtins.elem "-A" ssh.opts
|
||||
then []
|
||||
else ["-A"]
|
||||
);
|
||||
};
|
||||
});
|
||||
}
|
||||
84
nix/snow/flake/outputs/nixosConfigurations.nix
Normal file
84
nix/snow/flake/outputs/nixosConfigurations.nix
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
{
|
||||
_snowFlake,
|
||||
snow,
|
||||
config,
|
||||
systems,
|
||||
root,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(builtins)
|
||||
all
|
||||
attrNames
|
||||
warn
|
||||
;
|
||||
|
||||
inherit
|
||||
(config)
|
||||
nodes
|
||||
;
|
||||
in {
|
||||
outputs.nixosConfigurations = let
|
||||
groups = snow.lib.parseGroupDecls root config.nodes.groups;
|
||||
in
|
||||
snow.lib.mapNodes nodes (
|
||||
{
|
||||
base,
|
||||
lib,
|
||||
name,
|
||||
node,
|
||||
...
|
||||
}: let
|
||||
nodeGroups =
|
||||
(node.groups groups)
|
||||
|> snow.lib.resolveGroupsInheritance
|
||||
|> snow.lib.groupModules;
|
||||
|
||||
homeManager =
|
||||
if node.homeManager != null
|
||||
then node.homeManager
|
||||
else if nodes.homeManager != null
|
||||
then nodes.homeManager
|
||||
else
|
||||
warn ''
|
||||
[snowflake] Neither `nodes.homeManager` nor `nodes.nodes.${name}.homeManager` were specified!
|
||||
[snowflake] home-manager will NOT be used! User configuration will be ignored!
|
||||
''
|
||||
null;
|
||||
|
||||
userArgs = nodes.args // node.args;
|
||||
snowArgs = {
|
||||
inherit systems snow root base nodes node;
|
||||
inherit (node) system;
|
||||
hostname = name;
|
||||
|
||||
_snow = {
|
||||
inherit (_snowFlake) inputs;
|
||||
inherit userArgs snowArgs homeManager;
|
||||
specialArgs = userArgs // snowArgs;
|
||||
};
|
||||
};
|
||||
specialArgs = assert (userArgs
|
||||
|> attrNames
|
||||
|> all (argName:
|
||||
! snowArgs ? argName
|
||||
|| abort ''
|
||||
`specialArgs` are like super important to Snow my love... </3
|
||||
But `args.${argName}` is a reserved argument name :(
|
||||
''));
|
||||
snowArgs._snow.specialArgs;
|
||||
in
|
||||
lib.nixosSystem {
|
||||
inherit (node) system;
|
||||
inherit specialArgs;
|
||||
modules =
|
||||
[
|
||||
_snowFlake.self.nixosModules.default
|
||||
(snow.lib.findImport /${root}/hosts/${name})
|
||||
]
|
||||
++ nodeGroups
|
||||
++ node.modules
|
||||
++ nodes.modules;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -12,12 +12,14 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
{
|
||||
root,
|
||||
snow,
|
||||
nt,
|
||||
mix,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./nodes
|
||||
(snow.findImport /${root}/snow)
|
||||
} @ args:
|
||||
mix.newMixture args (mixture: {
|
||||
includes.public = [
|
||||
./util.nix
|
||||
./nixpkgs.nix
|
||||
./nodes.nix
|
||||
];
|
||||
}
|
||||
})
|
||||
54
nix/snow/lib/nixpkgs.nix
Normal file
54
nix/snow/lib/nixpkgs.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
|
||||
# A best effort, lenient estimate. Please use a recent nixpkgs lib if you
|
||||
# override it at all.
|
||||
minVersion = "23.05pre-git";
|
||||
|
||||
isNixpkgsValidVersion = let
|
||||
revInfo =
|
||||
if inputs.nixpkgs?rev
|
||||
then " (nixpkgs-lib.rev: ${inputs.nixpkgs.rev})"
|
||||
else "";
|
||||
in
|
||||
(builtins.compareVersions lib.version minVersion >= 0)
|
||||
|| abort ''
|
||||
The nixpkgs dependency of snow was overridden but is too old.
|
||||
The minimum supported version of nixpkgs-lib is ${minVersion},
|
||||
but the actual version is ${lib.version}${revInfo}.
|
||||
'';
|
||||
in
|
||||
assert isNixpkgsValidVersion; {
|
||||
# Helper function for defining a per-system option that
|
||||
# gets transposed by the usual flake system logic to a
|
||||
# top-level outputs attribute.
|
||||
mkPerSystemFlakeOutput = {
|
||||
name,
|
||||
option,
|
||||
file,
|
||||
}: {
|
||||
_file = file;
|
||||
|
||||
options = {
|
||||
outputs.${name} = mkOption {
|
||||
type = types.attrsWith {
|
||||
elemType = option.type;
|
||||
lazy = true;
|
||||
placeholder = "system";
|
||||
};
|
||||
default = {};
|
||||
description = ''
|
||||
See {option}`perSystem.${name}` for description and examples.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,17 +1,8 @@
|
|||
# Copyright 2025-2026 _cry64 (Emile Clark-Boman)
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
{nt, ...}: let
|
||||
{
|
||||
this,
|
||||
nt,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(builtins)
|
||||
concatLists
|
||||
|
|
@ -23,53 +14,9 @@
|
|||
typeOf
|
||||
;
|
||||
|
||||
inherit (nt.prim) uniq;
|
||||
|
||||
rootGroupName = "all";
|
||||
|
||||
parseGroupsDecl = groups: let
|
||||
validGroup = g:
|
||||
isAttrs g
|
||||
|| throw ''
|
||||
Cerulean Nexus groups must be provided as attribute sets, got "${typeOf g}" instead!
|
||||
Ensure all the group definitions are attribute sets under your call to `cerulean.mkNexus`.
|
||||
NOTE: Groups can be accessed via `self.groups.PATH.TO.YOUR.GROUP`
|
||||
'';
|
||||
delegate = parent: gName: g: let
|
||||
result =
|
||||
(g
|
||||
// {
|
||||
_name = gName;
|
||||
_parent = parent;
|
||||
})
|
||||
|> mapAttrs (name: value:
|
||||
if elem name ["_name" "_parent"]
|
||||
# ignore metadata fields
|
||||
then value
|
||||
else assert validGroup value; (delegate result name value));
|
||||
in
|
||||
result;
|
||||
in
|
||||
assert validGroup groups;
|
||||
delegate null rootGroupName groups;
|
||||
|
||||
getGroupModules = root: groups:
|
||||
# ensure root group is always added
|
||||
groups
|
||||
# add all inherited groups via _parent
|
||||
|> map (let
|
||||
delegate = g:
|
||||
if g._parent == null
|
||||
then [g]
|
||||
else [g] ++ delegate (g._parent);
|
||||
in
|
||||
delegate)
|
||||
# flatten recursion result
|
||||
|> concatLists
|
||||
# find import location
|
||||
|> map (group: nt.findImport /${root}/groups/${group._name})
|
||||
# filter by uniqueness
|
||||
|> nt.prim.unique
|
||||
# ignore missing groups
|
||||
|> filter pathExists;
|
||||
in {
|
||||
mapNodes = nodes: f:
|
||||
nodes.nodes
|
||||
|
|
@ -82,7 +29,7 @@ in {
|
|||
then nodes.base
|
||||
else
|
||||
abort ''
|
||||
Cerulean cannot construct nodes node "${name}" without a base package source.
|
||||
snow cannot construct nodes node "${name}" without a base package source.
|
||||
Ensure `nodes.nodes.*.base` or `nodes.base` is a flake reference to the github:NixOS/nixpkgs repository.
|
||||
'';
|
||||
in
|
||||
|
|
@ -90,7 +37,51 @@ in {
|
|||
inherit name node base;
|
||||
inherit (base) lib;
|
||||
|
||||
groups = node.groups (parseGroupsDecl nodes.groups);
|
||||
groupModules = root: getGroupModules root groups;
|
||||
inherit (node) groups;
|
||||
});
|
||||
|
||||
groupModules = map (group: group._module);
|
||||
|
||||
parseGroupDecls = root: groupDecls: let
|
||||
validGroup = g:
|
||||
isAttrs g
|
||||
|| throw ''
|
||||
Snow node groups must be provided as attribute sets, got "${typeOf g}" instead!
|
||||
Ensure all the group definitions are attribute sets under your call to `snow.flake`.
|
||||
'';
|
||||
delegate = parent: gName: g: let
|
||||
result =
|
||||
(g
|
||||
// {
|
||||
_name = gName;
|
||||
_parent = parent;
|
||||
_module = this.lib.findImport /${root}/groups/${gName};
|
||||
})
|
||||
|> mapAttrs (name: value:
|
||||
if elem name ["_name" "_parent" "_module"]
|
||||
# ignore metadata fields
|
||||
then value
|
||||
else assert validGroup value; (delegate result name value));
|
||||
in
|
||||
result;
|
||||
in
|
||||
assert validGroup groupDecls;
|
||||
delegate null rootGroupName groupDecls;
|
||||
|
||||
resolveGroupsInheritance = groups:
|
||||
groups
|
||||
# add all inherited groups via _parent
|
||||
|> map (let
|
||||
delegate = g:
|
||||
if g._parent == null
|
||||
then [g]
|
||||
else [g] ++ delegate (g._parent);
|
||||
in
|
||||
delegate)
|
||||
# flatten recursion result
|
||||
|> concatLists
|
||||
# ignore missing groups
|
||||
|> filter (group: pathExists group._module)
|
||||
# filter by uniqueness
|
||||
|> uniq;
|
||||
}
|
||||
|
|
|
|||
3
nix/snow/lib/util.nix
Normal file
3
nix/snow/lib/util.nix
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{nt, ...}: {
|
||||
inherit (nt) findImport;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue