From aaf9d6422bb3085ce1814f44a12f3843149cd0c6 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 8 Mar 2026 17:29:24 +1000 Subject: [PATCH 01/19] progress version --- cerulean/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cerulean/default.nix b/cerulean/default.nix index 80240c0..b95b117 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -21,7 +21,7 @@ mix.newMixture args (mixture: { ./snow ]; - version = "0.2.5-alpha"; + version = "0.2.6-alpha"; # WARNING: legacy mkFlake = mixture.snow.flake; From dc769da2bd0a8d8662d6e9250f9eef40466e032d Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 8 Mar 2026 17:29:43 +1000 Subject: [PATCH 02/19] remove legacy cerulean.mkFlake --- cerulean/default.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/cerulean/default.nix b/cerulean/default.nix index b95b117..6c488a1 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -23,9 +23,6 @@ mix.newMixture args (mixture: { version = "0.2.6-alpha"; - # WARNING: legacy - mkFlake = mixture.snow.flake; - overlays = [ # build deploy-rs as a package not from the flake input, # hence we can rely on a nixpkg binary cache. From 89e36243b2c6ab81f3663a70d16e969672181b25 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 8 Mar 2026 17:30:21 +1000 Subject: [PATCH 03/19] rename /cerulean -> /nix --- {cerulean => nix}/default.nix | 0 {cerulean => nix}/home/default.nix | 0 {cerulean => nix}/nixos/default.nix | 0 {cerulean => nix}/nixos/home.nix | 0 {cerulean => nix}/nixos/microvm-child.nix | 0 {cerulean => nix}/nixos/microvm-parent.nix | 0 {cerulean => nix}/nixos/nixpkgs.nix | 0 {cerulean => nix}/nixos/remote-deploy/default.nix | 0 {cerulean => nix}/snow/default.nix | 0 {cerulean => nix}/snow/lib/nodes.nix | 0 {cerulean => nix}/snow/module.nix | 0 {cerulean => nix}/snow/nodes/default.nix | 0 {cerulean => nix}/snow/nodes/shared.nix | 0 {cerulean => nix}/snow/nodes/submodule.nix | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename {cerulean => nix}/default.nix (100%) rename {cerulean => nix}/home/default.nix (100%) rename {cerulean => nix}/nixos/default.nix (100%) rename {cerulean => nix}/nixos/home.nix (100%) rename {cerulean => nix}/nixos/microvm-child.nix (100%) rename {cerulean => nix}/nixos/microvm-parent.nix (100%) rename {cerulean => nix}/nixos/nixpkgs.nix (100%) rename {cerulean => nix}/nixos/remote-deploy/default.nix (100%) rename {cerulean => nix}/snow/default.nix (100%) rename {cerulean => nix}/snow/lib/nodes.nix (100%) rename {cerulean => nix}/snow/module.nix (100%) rename {cerulean => nix}/snow/nodes/default.nix (100%) rename {cerulean => nix}/snow/nodes/shared.nix (100%) rename {cerulean => nix}/snow/nodes/submodule.nix (100%) diff --git a/cerulean/default.nix b/nix/default.nix similarity index 100% rename from cerulean/default.nix rename to nix/default.nix diff --git a/cerulean/home/default.nix b/nix/home/default.nix similarity index 100% rename from cerulean/home/default.nix rename to nix/home/default.nix diff --git a/cerulean/nixos/default.nix b/nix/nixos/default.nix similarity index 100% rename from cerulean/nixos/default.nix rename to nix/nixos/default.nix diff --git a/cerulean/nixos/home.nix b/nix/nixos/home.nix similarity index 100% rename from cerulean/nixos/home.nix rename to nix/nixos/home.nix diff --git a/cerulean/nixos/microvm-child.nix b/nix/nixos/microvm-child.nix similarity index 100% rename from cerulean/nixos/microvm-child.nix rename to nix/nixos/microvm-child.nix diff --git a/cerulean/nixos/microvm-parent.nix b/nix/nixos/microvm-parent.nix similarity index 100% rename from cerulean/nixos/microvm-parent.nix rename to nix/nixos/microvm-parent.nix diff --git a/cerulean/nixos/nixpkgs.nix b/nix/nixos/nixpkgs.nix similarity index 100% rename from cerulean/nixos/nixpkgs.nix rename to nix/nixos/nixpkgs.nix diff --git a/cerulean/nixos/remote-deploy/default.nix b/nix/nixos/remote-deploy/default.nix similarity index 100% rename from cerulean/nixos/remote-deploy/default.nix rename to nix/nixos/remote-deploy/default.nix diff --git a/cerulean/snow/default.nix b/nix/snow/default.nix similarity index 100% rename from cerulean/snow/default.nix rename to nix/snow/default.nix diff --git a/cerulean/snow/lib/nodes.nix b/nix/snow/lib/nodes.nix similarity index 100% rename from cerulean/snow/lib/nodes.nix rename to nix/snow/lib/nodes.nix diff --git a/cerulean/snow/module.nix b/nix/snow/module.nix similarity index 100% rename from cerulean/snow/module.nix rename to nix/snow/module.nix diff --git a/cerulean/snow/nodes/default.nix b/nix/snow/nodes/default.nix similarity index 100% rename from cerulean/snow/nodes/default.nix rename to nix/snow/nodes/default.nix diff --git a/cerulean/snow/nodes/shared.nix b/nix/snow/nodes/shared.nix similarity index 100% rename from cerulean/snow/nodes/shared.nix rename to nix/snow/nodes/shared.nix diff --git a/cerulean/snow/nodes/submodule.nix b/nix/snow/nodes/submodule.nix similarity index 100% rename from cerulean/snow/nodes/submodule.nix rename to nix/snow/nodes/submodule.nix From ff0d13034b7b7a615b114860a9fe38362224ec71 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 8 Mar 2026 17:32:45 +1000 Subject: [PATCH 04/19] "CHANGELOG" my ass, ts hasn't changed at all... --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd559bf..651f53e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,3 +31,11 @@ Minor patches ## v0.2.4-alpha - `homeManager` flake reference may now be specified in snowflake - `` + +## v0.2.5-alpha +>[!TODO] +> I've been too focused on upcoming changes... + +## v0.2.6-alpha +>[!TODO] +> I've been too focused on upcoming changes... From 2f49295004c92c14fc47b5ee2cd7bc3677ef096f Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 9 Mar 2026 02:43:40 +1000 Subject: [PATCH 05/19] backup bash cli --- {ceru => ceru.bak}/ceru | 0 {ceru => ceru.bak}/libceru.sh | 0 {ceru => ceru.bak}/subcmds/new/cache-key | 0 {ceru => ceru.bak}/subcmds/new/default.sh | 0 {ceru => ceru.bak}/subcmds/new/password | 0 {ceru => ceru.bak}/subcmds/new/ssh-key | 0 {ceru => ceru.bak}/subcmds/new/wg-key | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename {ceru => ceru.bak}/ceru (100%) rename {ceru => ceru.bak}/libceru.sh (100%) rename {ceru => ceru.bak}/subcmds/new/cache-key (100%) rename {ceru => ceru.bak}/subcmds/new/default.sh (100%) rename {ceru => ceru.bak}/subcmds/new/password (100%) rename {ceru => ceru.bak}/subcmds/new/ssh-key (100%) rename {ceru => ceru.bak}/subcmds/new/wg-key (100%) diff --git a/ceru/ceru b/ceru.bak/ceru similarity index 100% rename from ceru/ceru rename to ceru.bak/ceru diff --git a/ceru/libceru.sh b/ceru.bak/libceru.sh similarity index 100% rename from ceru/libceru.sh rename to ceru.bak/libceru.sh diff --git a/ceru/subcmds/new/cache-key b/ceru.bak/subcmds/new/cache-key similarity index 100% rename from ceru/subcmds/new/cache-key rename to ceru.bak/subcmds/new/cache-key diff --git a/ceru/subcmds/new/default.sh b/ceru.bak/subcmds/new/default.sh similarity index 100% rename from ceru/subcmds/new/default.sh rename to ceru.bak/subcmds/new/default.sh diff --git a/ceru/subcmds/new/password b/ceru.bak/subcmds/new/password similarity index 100% rename from ceru/subcmds/new/password rename to ceru.bak/subcmds/new/password diff --git a/ceru/subcmds/new/ssh-key b/ceru.bak/subcmds/new/ssh-key similarity index 100% rename from ceru/subcmds/new/ssh-key rename to ceru.bak/subcmds/new/ssh-key diff --git a/ceru/subcmds/new/wg-key b/ceru.bak/subcmds/new/wg-key similarity index 100% rename from ceru/subcmds/new/wg-key rename to ceru.bak/subcmds/new/wg-key From 0314109bc085d0283d3c488793d3d5fb10897f71 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 9 Mar 2026 02:44:50 +1000 Subject: [PATCH 06/19] begin cerulean's rust cli --- snow/Cargo.lock | 985 ++++++++++++++++++++++++++++++++++++++ snow/Cargo.toml | 16 + snow/flake.bak/crates.nix | 49 ++ snow/flake.bak/flake.lock | 787 ++++++++++++++++++++++++++++++ snow/flake.bak/flake.nix | 61 +++ snow/flake.lock | 82 ++++ snow/flake.nix | 99 ++++ snow/src/main.rs | 26 + 8 files changed, 2105 insertions(+) create mode 100644 snow/Cargo.lock create mode 100644 snow/Cargo.toml create mode 100644 snow/flake.bak/crates.nix create mode 100644 snow/flake.bak/flake.lock create mode 100644 snow/flake.bak/flake.nix create mode 100644 snow/flake.lock create mode 100644 snow/flake.nix create mode 100644 snow/src/main.rs diff --git a/snow/Cargo.lock b/snow/Cargo.lock new file mode 100644 index 0000000..0ab3568 --- /dev/null +++ b/snow/Cargo.lock @@ -0,0 +1,985 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "colored" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +dependencies = [ + "lazy_static", + "windows-sys 0.59.0", +] + +[[package]] +name = "cstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68523903c8ae5aacfa32a0d9ae60cadeb764e1da14ee0d26b1f3089f13a54636" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "ctor" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "colored", + "log", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "humantime" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nix-bindings-bdwgc-sys" +version = "0.2.1" +source = "git+https://github.com/nixops4/nix-bindings-rust#7de15fa26057c8cf0b6178ff166e529c09ea89a7" +dependencies = [ + "bindgen", + "pkg-config", +] + +[[package]] +name = "nix-bindings-expr" +version = "0.2.1" +source = "git+https://github.com/nixops4/nix-bindings-rust#7de15fa26057c8cf0b6178ff166e529c09ea89a7" +dependencies = [ + "anyhow", + "cstr", + "ctor", + "nix-bindings-bdwgc-sys", + "nix-bindings-expr-sys", + "nix-bindings-store", + "nix-bindings-store-sys", + "nix-bindings-util", + "nix-bindings-util-sys", + "pkg-config", + "tempfile", +] + +[[package]] +name = "nix-bindings-expr-sys" +version = "0.2.1" +source = "git+https://github.com/nixops4/nix-bindings-rust#7de15fa26057c8cf0b6178ff166e529c09ea89a7" +dependencies = [ + "bindgen", + "nix-bindings-store-sys", + "nix-bindings-util-sys", + "pkg-config", +] + +[[package]] +name = "nix-bindings-store" +version = "0.2.1" +source = "git+https://github.com/nixops4/nix-bindings-rust#7de15fa26057c8cf0b6178ff166e529c09ea89a7" +dependencies = [ + "anyhow", + "nix-bindings-store-sys", + "nix-bindings-util", + "nix-bindings-util-sys", + "pkg-config", + "zerocopy", +] + +[[package]] +name = "nix-bindings-store-sys" +version = "0.2.1" +source = "git+https://github.com/nixops4/nix-bindings-rust#7de15fa26057c8cf0b6178ff166e529c09ea89a7" +dependencies = [ + "bindgen", + "nix-bindings-util-sys", + "pkg-config", + "zerocopy", +] + +[[package]] +name = "nix-bindings-util" +version = "0.2.1" +source = "git+https://github.com/nixops4/nix-bindings-rust#7de15fa26057c8cf0b6178ff166e529c09ea89a7" +dependencies = [ + "anyhow", + "nix-bindings-util-sys", +] + +[[package]] +name = "nix-bindings-util-sys" +version = "0.2.1" +source = "git+https://github.com/nixops4/nix-bindings-rust#7de15fa26057c8cf0b6178ff166e529c09ea89a7" +dependencies = [ + "bindgen", + "pkg-config", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "snow" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "fern", + "humantime", + "log", + "nix-bindings-expr", + "nix-bindings-store", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zerocopy" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/snow/Cargo.toml b/snow/Cargo.toml new file mode 100644 index 0000000..0db7dcf --- /dev/null +++ b/snow/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "snow" +description = "Cerulean CLI (Wowzers!!)" +version = "0.1.0" +authors = ["_cry64 "] +edition = "2024" + +[dependencies] +nix-bindings-store = { git = "https://github.com/nixops4/nix-bindings-rust" } +nix-bindings-expr = { git = "https://github.com/nixops4/nix-bindings-rust" } + +anyhow = "1.0.102" +clap = { version = "4.5.60", features = ["derive"] } +log = "0.4.29" +fern = { version="0.7.1", features = ["colored"] } +humantime = "2.3.0" diff --git a/snow/flake.bak/crates.nix b/snow/flake.bak/crates.nix new file mode 100644 index 0000000..d47c0ab --- /dev/null +++ b/snow/flake.bak/crates.nix @@ -0,0 +1,49 @@ +{...}: { + perSystem = { + config, + pkgs, + ... + }: { + nix-bindings-rust.nixPackage = pkgs.nix; + + # declare projects + nci.projects."cerulean-project" = { + path = ./.; + # export all crates (packages and devshell) in flake outputs + # alternatively you can access the outputs and export them yourself + export = true; + + depsDrvConfig = { + imports = [config.nix-bindings-rust.nciBuildConfig]; + }; + }; + # configure crates + nci.crates."cerulean" = rec { + # profiles.release = rec { + default = true; + runTests = true; + + drvConfig = + depsDrvConfig + // { + env.CARGO_TERM_VERBOSE = "true"; + }; + + depsDrvConfig = rec { + env.LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:${builtins.toString (pkgs.lib.makeLibraryPath mkDerivation.buildInputs)}"; + + mkDerivation = { + buildInputs = with pkgs; [ + boehmgc.dev + nix.dev + ]; + nativeBuildInputs = with pkgs; [ + pkg-config + rustPlatform.bindgenHook + ]; + }; + }; + # }; + }; + }; +} diff --git a/snow/flake.bak/flake.lock b/snow/flake.bak/flake.lock new file mode 100644 index 0000000..419d1fe --- /dev/null +++ b/snow/flake.bak/flake.lock @@ -0,0 +1,787 @@ +{ + "nodes": { + "crane": { + "flake": false, + "locked": { + "lastModified": 1758758545, + "narHash": "sha256-NU5WaEdfwF6i8faJ2Yh+jcK9vVFrofLcwlD/mP65JrI=", + "owner": "ipetkov", + "repo": "crane", + "rev": "95d528a5f54eaba0d12102249ce42f4d01f4e364", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "ref": "v0.21.1", + "repo": "crane", + "type": "github" + } + }, + "crane_2": { + "flake": false, + "locked": { + "lastModified": 1758758545, + "narHash": "sha256-NU5WaEdfwF6i8faJ2Yh+jcK9vVFrofLcwlD/mP65JrI=", + "owner": "ipetkov", + "repo": "crane", + "rev": "95d528a5f54eaba0d12102249ce42f4d01f4e364", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "ref": "v0.21.1", + "repo": "crane", + "type": "github" + } + }, + "dream2nix": { + "inputs": { + "nixpkgs": [ + "nci", + "nixpkgs" + ], + "purescript-overlay": "purescript-overlay", + "pyproject-nix": "pyproject-nix" + }, + "locked": { + "lastModified": 1765953015, + "narHash": "sha256-5FBZbbWR1Csp3Y2icfRkxMJw/a/5FGg8hCXej2//bbI=", + "owner": "nix-community", + "repo": "dream2nix", + "rev": "69eb01fa0995e1e90add49d8ca5bcba213b0416f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "dream2nix", + "type": "github" + } + }, + "dream2nix_2": { + "inputs": { + "nixpkgs": [ + "nix-bindings-rust", + "nix-cargo-integration", + "nixpkgs" + ], + "purescript-overlay": "purescript-overlay_2", + "pyproject-nix": "pyproject-nix_2" + }, + "locked": { + "lastModified": 1765953015, + "narHash": "sha256-5FBZbbWR1Csp3Y2icfRkxMJw/a/5FGg8hCXej2//bbI=", + "owner": "nix-community", + "repo": "dream2nix", + "rev": "69eb01fa0995e1e90add49d8ca5bcba213b0416f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "dream2nix", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1772953398, + "narHash": "sha256-fTTHCaEvPLzWyZFxPud/G9HM3pNYmW/64Kj58hdH4+k=", + "owner": "nix-community", + "repo": "fenix", + "rev": "fc4863887d98fd879cf5f11af1d23d44d9bdd8ae", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "NixOS", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1769996383, + "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nix-bindings-rust", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "git-hooks-nix": { + "inputs": { + "flake-compat": [ + "nix-bindings-rust", + "nix" + ], + "gitignore": [ + "nix-bindings-rust", + "nix" + ], + "nixpkgs": [ + "nix-bindings-rust", + "nix", + "nixpkgs" + ], + "nixpkgs-stable": [ + "nix-bindings-rust", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1734279981, + "narHash": "sha256-NdaCraHPp8iYMWzdXAt5Nv6sA3MUzlCiGiR586TCwo0=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "aa9f40c906904ebd83da78e7f328cd8aeaeae785", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "mk-naked-shell": { + "flake": false, + "locked": { + "lastModified": 1681286841, + "narHash": "sha256-3XlJrwlR0nBiREnuogoa5i1b4+w/XPe0z8bbrJASw0g=", + "owner": "90-008", + "repo": "mk-naked-shell", + "rev": "7612f828dd6f22b7fb332cc69440e839d7ffe6bd", + "type": "github" + }, + "original": { + "owner": "90-008", + "repo": "mk-naked-shell", + "type": "github" + } + }, + "mk-naked-shell_2": { + "flake": false, + "locked": { + "lastModified": 1681286841, + "narHash": "sha256-3XlJrwlR0nBiREnuogoa5i1b4+w/XPe0z8bbrJASw0g=", + "owner": "90-008", + "repo": "mk-naked-shell", + "rev": "7612f828dd6f22b7fb332cc69440e839d7ffe6bd", + "type": "github" + }, + "original": { + "owner": "90-008", + "repo": "mk-naked-shell", + "type": "github" + } + }, + "nci": { + "inputs": { + "crane": "crane", + "dream2nix": "dream2nix", + "mk-naked-shell": "mk-naked-shell", + "nixpkgs": [ + "nixpkgs" + ], + "parts": "parts", + "rust-overlay": "rust-overlay", + "treefmt": "treefmt" + }, + "locked": { + "lastModified": 1772951573, + "narHash": "sha256-ALlAShJadjr4NpaqrJeXX8nrpqJGk571/1JVsSQ0OMI=", + "owner": "90-008", + "repo": "nix-cargo-integration", + "rev": "a7a34450d5a99c6bffa48497528ed9bf809085d6", + "type": "github" + }, + "original": { + "owner": "90-008", + "repo": "nix-cargo-integration", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": "flake-compat_2", + "flake-parts": "flake-parts_2", + "git-hooks-nix": "git-hooks-nix", + "nixpkgs": [ + "nix-bindings-rust", + "nixpkgs" + ], + "nixpkgs-23-11": "nixpkgs-23-11", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1772224943, + "narHash": "sha256-jJIlRLPPVYu860MVFx4gsRx3sskmLDSRWXXue5tYncw=", + "owner": "NixOS", + "repo": "nix", + "rev": "0acd0566e85e4597269482824711bcde7b518600", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nix", + "type": "github" + } + }, + "nix-bindings-rust": { + "inputs": { + "flake-parts": "flake-parts", + "nix": "nix", + "nix-cargo-integration": "nix-cargo-integration", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1772492331, + "narHash": "sha256-UrYoUqNVwXLtAB5Q/KIkm0xPLA0DeK+9YbB4HTES558=", + "owner": "nixops4", + "repo": "nix-bindings-rust", + "rev": "7de15fa26057c8cf0b6178ff166e529c09ea89a7", + "type": "github" + }, + "original": { + "owner": "nixops4", + "repo": "nix-bindings-rust", + "type": "github" + } + }, + "nix-cargo-integration": { + "inputs": { + "crane": "crane_2", + "dream2nix": "dream2nix_2", + "mk-naked-shell": "mk-naked-shell_2", + "nixpkgs": [ + "nix-bindings-rust", + "nixpkgs" + ], + "parts": "parts_2", + "rust-overlay": "rust-overlay_2", + "treefmt": "treefmt_2" + }, + "locked": { + "lastModified": 1772260057, + "narHash": "sha256-NaUqM0i6XIGdgRNxxQ9sfgCAVeE2Ko9rz7e19RsNUKw=", + "owner": "90-008", + "repo": "nix-cargo-integration", + "rev": "c783c5dff02c06f2af6226d4dd4d494542d0a4d2", + "type": "github" + }, + "original": { + "owner": "90-008", + "repo": "nix-cargo-integration", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1772198003, + "narHash": "sha256-I45esRSssFtJ8p/gLHUZ1OUaaTaVLluNkABkk6arQwE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "dd9b079222d43e1943b6ebd802f04fd959dc8e61", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-23-11": { + "locked": { + "lastModified": 1717159533, + "narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1769909678, + "narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "72716169fe93074c333e8d0173151350670b824c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-lib_2": { + "locked": { + "lastModified": 1772328832, + "narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1772773019, + "narHash": "sha256-E1bxHxNKfDoQUuvriG71+f+s/NT0qWkImXsYZNFFfCs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "aca4d95fce4914b3892661bcb80b8087293536c6", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "parts": { + "inputs": { + "nixpkgs-lib": [ + "nci", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1772408722, + "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nix-bindings-rust", + "nix-cargo-integration", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769996383, + "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "parts_3": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, + "locked": { + "lastModified": 1772408722, + "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "purescript-overlay": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "nci", + "dream2nix", + "nixpkgs" + ], + "slimlock": "slimlock" + }, + "locked": { + "lastModified": 1728546539, + "narHash": "sha256-Sws7w0tlnjD+Bjck1nv29NjC5DbL6nH5auL9Ex9Iz2A=", + "owner": "thomashoneyman", + "repo": "purescript-overlay", + "rev": "4ad4c15d07bd899d7346b331f377606631eb0ee4", + "type": "github" + }, + "original": { + "owner": "thomashoneyman", + "repo": "purescript-overlay", + "type": "github" + } + }, + "purescript-overlay_2": { + "inputs": { + "flake-compat": "flake-compat_3", + "nixpkgs": [ + "nix-bindings-rust", + "nix-cargo-integration", + "dream2nix", + "nixpkgs" + ], + "slimlock": "slimlock_2" + }, + "locked": { + "lastModified": 1728546539, + "narHash": "sha256-Sws7w0tlnjD+Bjck1nv29NjC5DbL6nH5auL9Ex9Iz2A=", + "owner": "thomashoneyman", + "repo": "purescript-overlay", + "rev": "4ad4c15d07bd899d7346b331f377606631eb0ee4", + "type": "github" + }, + "original": { + "owner": "thomashoneyman", + "repo": "purescript-overlay", + "type": "github" + } + }, + "pyproject-nix": { + "inputs": { + "nixpkgs": [ + "nci", + "dream2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1763017646, + "narHash": "sha256-Z+R2lveIp6Skn1VPH3taQIuMhABg1IizJd8oVdmdHsQ=", + "owner": "pyproject-nix", + "repo": "pyproject.nix", + "rev": "47bd6f296502842643078d66128f7b5e5370790c", + "type": "github" + }, + "original": { + "owner": "pyproject-nix", + "repo": "pyproject.nix", + "type": "github" + } + }, + "pyproject-nix_2": { + "inputs": { + "nixpkgs": [ + "nix-bindings-rust", + "nix-cargo-integration", + "dream2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1763017646, + "narHash": "sha256-Z+R2lveIp6Skn1VPH3taQIuMhABg1IizJd8oVdmdHsQ=", + "owner": "pyproject-nix", + "repo": "pyproject.nix", + "rev": "47bd6f296502842643078d66128f7b5e5370790c", + "type": "github" + }, + "original": { + "owner": "pyproject-nix", + "repo": "pyproject.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "fenix": "fenix", + "nci": "nci", + "nix-bindings-rust": "nix-bindings-rust", + "nixpkgs": "nixpkgs_2", + "parts": "parts_3", + "systems": "systems" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1772877513, + "narHash": "sha256-RcRGv2Bng5I9y75XwFX7oK2l6mLH1dtbTTG9U8qun0c=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "a1b86d600f88be98643e5dd61d6ed26eda17c09e", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nci", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1772939270, + "narHash": "sha256-HbxD5DJAKxzo0G8on5wdY+OZNiUWt3FTvGmXmVEmg7g=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "bb93f191a07c0165992ed6d0b4197ee5c7e6e641", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { + "inputs": { + "nixpkgs": [ + "nix-bindings-rust", + "nix-cargo-integration", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1772247314, + "narHash": "sha256-x6IFQ9bL7YYfW2m2z8D3Em2YtAA3HE8kiCFwai2fwrw=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "a1ab5e89ab12e1a37c0b264af6386a7472d68a15", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "slimlock": { + "inputs": { + "nixpkgs": [ + "nci", + "dream2nix", + "purescript-overlay", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688756706, + "narHash": "sha256-xzkkMv3neJJJ89zo3o2ojp7nFeaZc2G0fYwNXNJRFlo=", + "owner": "thomashoneyman", + "repo": "slimlock", + "rev": "cf72723f59e2340d24881fd7bf61cb113b4c407c", + "type": "github" + }, + "original": { + "owner": "thomashoneyman", + "repo": "slimlock", + "type": "github" + } + }, + "slimlock_2": { + "inputs": { + "nixpkgs": [ + "nix-bindings-rust", + "nix-cargo-integration", + "dream2nix", + "purescript-overlay", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688756706, + "narHash": "sha256-xzkkMv3neJJJ89zo3o2ojp7nFeaZc2G0fYwNXNJRFlo=", + "owner": "thomashoneyman", + "repo": "slimlock", + "rev": "cf72723f59e2340d24881fd7bf61cb113b4c407c", + "type": "github" + }, + "original": { + "owner": "thomashoneyman", + "repo": "slimlock", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "treefmt": { + "inputs": { + "nixpkgs": [ + "nci", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1772660329, + "narHash": "sha256-IjU1FxYqm+VDe5qIOxoW+pISBlGvVApRjiw/Y/ttJzY=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "3710e0e1218041bbad640352a0440114b1e10428", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt_2": { + "inputs": { + "nixpkgs": [ + "nix-bindings-rust", + "nix-cargo-integration", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770228511, + "narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "337a4fe074be1042a35086f15481d763b8ddc0e7", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/snow/flake.bak/flake.nix b/snow/flake.bak/flake.nix new file mode 100644 index 0000000..dade3d1 --- /dev/null +++ b/snow/flake.bak/flake.nix @@ -0,0 +1,61 @@ +{ + description = "Cerulean CLI"; + + inputs = { + systems.url = "github:nix-systems/default-linux"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + parts = { + url = "github:hercules-ci/flake-parts"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nci = { + url = "github:90-008/nix-cargo-integration"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nix-bindings-rust.url = "github:nixops4/nix-bindings-rust"; + + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = inputs @ { + parts, + nci, + nix-bindings-rust, + ... + }: + parts.lib.mkFlake {inherit inputs;} { + imports = [ + parts.flakeModules.easyOverlay + nci.flakeModule + nix-bindings-rust.modules.flake.default + ./crates.nix + ]; + + systems = import inputs.systems; + + perSystem = { + config, + pkgs, + ... + }: let + outputs = config.nci.outputs; + in { + overlayAttrs = { + cerulean = outputs."cerulean".packages.default; + }; + + # nix-bindings-rust.nixPackage = pkgs.nix; + + devShells.default = outputs."cerulean-project".devShell; + + packages = rec { + inherit (pkgs) cerulean; + default = cerulean; + }; + }; + }; +} diff --git a/snow/flake.lock b/snow/flake.lock new file mode 100644 index 0000000..67d4e29 --- /dev/null +++ b/snow/flake.lock @@ -0,0 +1,82 @@ +{ + "nodes": { + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1772953398, + "narHash": "sha256-fTTHCaEvPLzWyZFxPud/G9HM3pNYmW/64Kj58hdH4+k=", + "owner": "nix-community", + "repo": "fenix", + "rev": "fc4863887d98fd879cf5f11af1d23d44d9bdd8ae", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1772822230, + "narHash": "sha256-yf3iYLGbGVlIthlQIk5/4/EQDZNNEmuqKZkQssMljuw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "71caefce12ba78d84fe618cf61644dce01cf3a96", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "fenix": "fenix", + "nixpkgs": "nixpkgs", + "systems": "systems" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1772877513, + "narHash": "sha256-RcRGv2Bng5I9y75XwFX7oK2l6mLH1dtbTTG9U8qun0c=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "a1b86d600f88be98643e5dd61d6ed26eda17c09e", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/snow/flake.nix b/snow/flake.nix new file mode 100644 index 0000000..f2b9703 --- /dev/null +++ b/snow/flake.nix @@ -0,0 +1,99 @@ +{ + description = "Cerulean CLI"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + systems.url = "github:nix-systems/default"; + + fenix.url = "github:nix-community/fenix"; + fenix.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { + self, + nixpkgs, + ... + } @ inputs: let + systems = import inputs.systems; + + mkPkgs = system: repo: + import repo { + inherit system; + allowUnfree = false; + allowBroken = false; + overlays = builtins.attrValues self.overlays or {}; + }; + + forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system (mkPkgs system nixpkgs)); + in { + overlays.default = final: prev: { + libclang = prev.llvmPackages_21.libclang; + + # ttywire = pkgs.rustPlatform.buildRustPackage { + # pname = "cerulean"; + # version = "0.1.0"; + # src = ./.; + # + # cargoHash = "sha256-NxFdFCuB456uBeVeqT2bsRtBrIoLdijBaga7VB9KPF8="; + # + # # runtime dependencies (propagated out of derivation) + # buildInputs = with pkgs; [ + # boehmgc.dev + # nix.dev + # ]; + # + # # build-time/shellHook dependencies (not propagates) + # nativeBuildInputs = with pkgs; [ + # pkg-config + # ]; + # + # meta = with lib; { + # description = "Cerulean CLI"; + # homepage = "https://github.com/cry128/cerulean"; + # license = lib.licenses.asl20; + # maintainers = with maintainers; [ + # cry64 + # ]; + # }; + # }; + }; + + checks = self.packages or {}; + + # packages = forAllSystems ( + # system: pkgs: rec { + # inherit (pkgs) ttywire; + # default = ttywire; + # } + # ); + + devShells = forAllSystems ( + system: pkgs: { + default = pkgs.mkShell rec { + shell = "${pkgs.bash}/bin/bash"; + strictDeps = true; + + packages = with pkgs; [ + cargo + rustc + inputs.fenix.packages.${system}.complete.rustfmt + ]; + + # packages we should be able to link against + buildInputs = with pkgs; [ + boehmgc.dev + nix.dev + ]; + + # packages we run at build time / shellHook + nativeBuildInputs = with pkgs; [ + pkg-config + rustPlatform.bindgenHook + ]; + + LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:${builtins.toString (pkgs.lib.makeLibraryPath buildInputs)}"; + }; + } + ); + }; +} diff --git a/snow/src/main.rs b/snow/src/main.rs new file mode 100644 index 0000000..5a9d19d --- /dev/null +++ b/snow/src/main.rs @@ -0,0 +1,26 @@ +use nix_bindings_expr::eval_state::{gc_register_my_thread, init, EvalState}; +use nix_bindings_store::store::Store; +use std::collections::HashMap; + +fn main() -> anyhow::Result<()> { + // Initialize Nix library and register thread with GC + init()?; + let guard = gc_register_my_thread()?; + + // Open a store connection and create an evaluation state + let store = Store::open(None, HashMap::new())?; + let mut eval_state = EvalState::new(store, [])?; + + // Evaluate a Nix expression + let value = eval_state.eval_from_string("[1 2 3]", "")?; + + // Extract typed values + let elements: Vec<_> = eval_state.require_list_strict(&value)?; + for element in elements { + let num = eval_state.require_int(&element)?; + println!("Element: {}", num); + } + + drop(guard); + Ok(()) +} From 3e29615db9ac072029557b031ee814f820e49791 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 9 Mar 2026 02:46:41 +1000 Subject: [PATCH 07/19] example refactor snowflake module system --- nix/snow/default.nix | 173 +--------- nix/snow/flake/default.nix | 38 +++ nix/snow/flake/lib.nix.bak | 318 ++++++++++++++++++ nix/snow/{ => flake}/module.nix | 0 nix/snow/flake/modules/apps.nix | 61 ++++ nix/snow/flake/modules/checks.nix | 21 ++ nix/snow/flake/modules/debug.nix | 78 +++++ nix/snow/flake/modules/devShells.nix | 30 ++ nix/snow/flake/modules/flake.nix | 47 +++ nix/snow/flake/modules/formatter.nix | 52 +++ nix/snow/flake/modules/legacyPackages.nix | 21 ++ nix/snow/flake/modules/moduleWithSystem.nix | 32 ++ .../flake/modules/nixosConfigurations.nix | 36 ++ nix/snow/flake/modules/nixosModules.nix | 26 ++ nix/snow/flake/modules/nixpkgs.nix | 26 ++ nix/snow/flake/modules/overlays.nix | 32 ++ nix/snow/flake/modules/packages.nix | 23 ++ nix/snow/flake/modules/perSystem.nix | 159 +++++++++ nix/snow/flake/modules/transposition.nix | 132 ++++++++ nix/snow/flake/modules/withSystem.nix | 37 ++ nix/snow/{ => flake}/nodes/default.nix | 0 nix/snow/{ => flake}/nodes/shared.nix | 0 nix/snow/{ => flake}/nodes/submodule.nix | 0 nix/snow/flake/outputs/checks.nix | 5 + nix/snow/flake/outputs/deploy.nix | 57 ++++ .../flake/outputs/nixosConfigurations.nix | 67 ++++ 26 files changed, 1306 insertions(+), 165 deletions(-) create mode 100644 nix/snow/flake/default.nix create mode 100644 nix/snow/flake/lib.nix.bak rename nix/snow/{ => flake}/module.nix (100%) create mode 100644 nix/snow/flake/modules/apps.nix create mode 100644 nix/snow/flake/modules/checks.nix create mode 100644 nix/snow/flake/modules/debug.nix create mode 100644 nix/snow/flake/modules/devShells.nix create mode 100644 nix/snow/flake/modules/flake.nix create mode 100644 nix/snow/flake/modules/formatter.nix create mode 100644 nix/snow/flake/modules/legacyPackages.nix create mode 100644 nix/snow/flake/modules/moduleWithSystem.nix create mode 100644 nix/snow/flake/modules/nixosConfigurations.nix create mode 100644 nix/snow/flake/modules/nixosModules.nix create mode 100644 nix/snow/flake/modules/nixpkgs.nix create mode 100644 nix/snow/flake/modules/overlays.nix create mode 100644 nix/snow/flake/modules/packages.nix create mode 100644 nix/snow/flake/modules/perSystem.nix create mode 100644 nix/snow/flake/modules/transposition.nix create mode 100644 nix/snow/flake/modules/withSystem.nix rename nix/snow/{ => flake}/nodes/default.nix (100%) rename nix/snow/{ => flake}/nodes/shared.nix (100%) rename nix/snow/{ => flake}/nodes/submodule.nix (100%) create mode 100644 nix/snow/flake/outputs/checks.nix create mode 100644 nix/snow/flake/outputs/deploy.nix create mode 100644 nix/snow/flake/outputs/nixosConfigurations.nix diff --git a/nix/snow/default.nix b/nix/snow/default.nix index 6993ff1..15c67da 100644 --- a/nix/snow/default.nix +++ b/nix/snow/default.nix @@ -12,180 +12,23 @@ # 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 - ; - - inherit (inputs.nixpkgs) lib; - inherit (nt) findImport; in mix.newMixture args (mixture: let inherit (mixture) mapNodes; in { - includes.private = [ - ./lib/nodes.nix - ]; + includes = { + private = [ + ./lib/nodes.nix + ]; + public = [ + ./flake + ]; + }; 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... 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); - }; }) diff --git a/nix/snow/flake/default.nix b/nix/snow/flake/default.nix new file mode 100644 index 0000000..fad3c6d --- /dev/null +++ b/nix/snow/flake/default.nix @@ -0,0 +1,38 @@ +{ + this, + inputs, + systems, + ... +}: let + inherit (inputs.nixpkgs) lib; +in { + # snow.flake + flake = flakeInputs: root: let + snowflake = lib.evalModules { + class = "snowflake"; + # XXX: TODO: abort if inputs contains reserved names + specialArgs = + (flakeInputs + // { + inherit (this) snow; + inherit systems root; + inputs = flakeInputs; + }) + # XXX: TODO: + # |> (x: builtins.removeAttrs x ["self" "nodes"]); + |> (x: builtins.removeAttrs x ["self"]); + + modules = [ + ./module.nix + ({config, ...}: { + _module.args = { + self = config; + # XXX: TODO: + # nodes = config.nodes.nodes; + }; + }) + ]; + }; + in + snowflake.config.outputs; +} diff --git a/nix/snow/flake/lib.nix.bak b/nix/snow/flake/lib.nix.bak new file mode 100644 index 0000000..c8ea2ba --- /dev/null +++ b/nix/snow/flake/lib.nix.bak @@ -0,0 +1,318 @@ +{ lib + # Optionally a string with extra version info to be included in the error message + # in case is lib is out of date. Empty or starts with space. +, revInfo ? "" +}: +let + inherit (lib) + mkOption + mkOptionType + defaultFunctor + isAttrs + isFunction + showOption + throwIf + types + warnIf + getAttrFromPath + setAttrByPath + attrByPath + optionalAttrs + ; + inherit (lib.modules) + mkAliasAndWrapDefsWithPriority; + inherit (lib.types) + path + submoduleWith + ; + + # Polyfill isFlake until Nix with https://github.com/NixOS/nix/pull/7207 is common + isFlake = maybeFlake: + if maybeFlake ? _type + then maybeFlake._type == "flake" + else maybeFlake ? inputs && maybeFlake ? outputs && maybeFlake ? sourceInfo; + + /** + Deprecated for any use except type-merging into `perSystem`. + Use `lib.types.deferredModuleWith` instead, and add `apply = m: [ m ];` if needed. + + The deferredModule type was pioneered in flake-parts for the `perSystem` option. + The Nixpkgs version has an improved merge function that returns a single module, + whereas this version returns a list. The flake-parts version was not updated to + match this improvement in Nixpkgs. + + # History + + This predates `lib.types.deferredModuleWith`, added in Nixpkgs 22.11 + (https://github.com/NixOS/nixpkgs/pull/163617). + Documented as deprecated in flake-parts in January 2026. + */ + deferredModuleWith = + attrs@{ staticModules ? [ ] }: mkOptionType { + name = "deferredModule"; + description = "module"; + check = x: isAttrs x || isFunction x || path.check x; + merge = loc: defs: staticModules ++ map (def: lib.setDefaultModuleLocation "${def.file}, via option ${showOption loc}" def.value) defs; + inherit (submoduleWith { modules = staticModules; }) + getSubOptions + getSubModules; + substSubModules = m: deferredModuleWith (attrs // { + staticModules = m; + }); + functor = defaultFunctor "deferredModuleWith" // { + type = deferredModuleWith; + payload = { + inherit staticModules; + }; + binOp = lhs: rhs: { + staticModules = lhs.staticModules ++ rhs.staticModules; + }; + }; + }; + + # Internal: preserves legacy list-merge behavior for perSystem type-merging. + mkLegacyDeferredModuleType = + module: + deferredModuleWith { + staticModules = [ module ]; + }; + + errorExample = '' + For example: + + outputs = inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { /* module */ }; + + To avoid an infinite recursion, *DO NOT* pass `self.inputs` and + *DO NOT* pass `inherit (self) inputs`, but pass the output function + arguments as `inputs` like above. + ''; + + flake-parts-lib = rec { + evalFlakeModule = + args@ + { inputs ? self.inputs + , specialArgs ? { } + + # legacy + , self ? inputs.self or (throw '' + When invoking flake-parts, you must pass all the flake output arguments, + and not just `self.inputs`. + + ${errorExample} + '') + , moduleLocation ? "${self.outPath}/flake.nix" + }: + let + inputsPos = builtins.unsafeGetAttrPos "inputs" args; + errorLocation = + # Best case: user makes it explicit + args.moduleLocation or ( + # Slightly worse: Nix does not technically commit to unsafeGetAttrPos semantics + if inputsPos != null + then inputsPos.file + # Slightly worse: self may not be valid when an error occurs + else if args?inputs.self.outPath + then args.inputs.self.outPath + "/flake.nix" + # Fallback + else "" + ); + in + throwIf + (!args?self && !args?inputs) '' + When invoking flake-parts, you must pass in the flake output arguments. + + ${errorExample} + '' + warnIf + (!args?inputs) '' + When invoking flake-parts, it is recommended to pass all the flake output + arguments in the `inputs` parameter. If you only pass `self`, it's not + possible to use the `inputs` module argument in the module `imports`. + + Please pass the output function arguments. ${errorExample} + '' + + (module: + lib.evalModules { + specialArgs = { + inherit self flake-parts-lib moduleLocation; + inputs = args.inputs or /* legacy, warned above */ self.inputs; + } // specialArgs; + modules = [ ./all-modules.nix (lib.setDefaultModuleLocation errorLocation module) ]; + class = "flake"; + } + ); + + # Function to extract the default flakeModule from + # what may be a flake, returning the argument unmodified + # if it's not a flake. + # + # Useful to map over an 'imports' list to make it less + # verbose in the common case. + defaultModule = maybeFlake: + if isFlake maybeFlake + then maybeFlake.flakeModules.default or maybeFlake + else maybeFlake; + + mkFlake = args: module: + let + eval = flake-parts-lib.evalFlakeModule args module; + in + eval.config.flake; + + /** + Deprecated. Declare options directly, e.g. `options.foo.bar = mkOption { ... }`, + provided that `foo` is already declared as a submodule option. + + In flake-parts, `flake` is declared as a submodule option by the core modules, + so `options.flake.` declarations work directly. + + This function wraps option declarations in a submodule, allowing them to + be merged into an existing submodule option. For example, if `foo` is + already declared as a submodule option, using + `options.foo = mkSubmoduleOptions { bar = mkOption {...}; }` would add + `bar` to the `foo` submodule. + + # History + + This was a workaround for https://github.com/NixOS/nixpkgs/issues/146882, + fixed in Nixpkgs 22.05 by https://github.com/NixOS/nixpkgs/pull/156533. + With the fix, declaring `options.foo.bar` directly works when `foo` is + already a submodule option. Documented as deprecated in flake-parts in January 2026. + */ + mkSubmoduleOptions = + options: + mkOption { + type = types.submoduleWith { + modules = [{ inherit options; }]; + }; + }; + + /** + Deprecated. Use mkPerSystemType/mkPerSystemOption for `perSystem` type-merging, or + use Nixpkgs `types.deferredModule` directly, noting the lack of list wrapping; + see `deferredModuleWith` docs. + */ + mkDeferredModuleType = mkLegacyDeferredModuleType; + + /** + Given a module, construct an option type suitable for type-merging into `perSystem`'s type. + */ + mkPerSystemType = mkLegacyDeferredModuleType; + + /** + Deprecated. Use mkPerSystemOption for `perSystem` type-merging, or + use `mkOption` and Nixpkgs `types.deferredModule` directly, noting the + lack of list wrapping; see `deferredModuleWith` docs. + */ + mkDeferredModuleOption = + module: + mkOption { + type = flake-parts-lib.mkPerSystemType module; + }; + + /** + Given a module, construct an option declaration suitable for merging into the core `perSystem` module. + */ + mkPerSystemOption = mkDeferredModuleOption; + + # Polyfill https://github.com/NixOS/nixpkgs/pull/344216 + # Nixpkgs master 2024-12-09, Nixpkgs 25.05 + attrsWith = types.attrsWith or ({ elemType, lazy ? false, placeholder ? "name" }: + if lazy then types.attrsOf elemType else types.lazyAttrsOf elemType); + + # Helper function for defining a per-system option that + # gets transposed by the usual flake system logic to a + # top-level flake attribute. + mkTransposedPerSystemModule = { name, option, file }: { + _file = file; + + options = { + flake.${name} = mkOption { + type = attrsWith { + elemType = option.type; + lazy = true; + placeholder = "system"; + }; + default = { }; + description = '' + See {option}`perSystem.${name}` for description and examples. + ''; + }; + + perSystem = flake-parts-lib.mkPerSystemOption { + _file = file; + + options.${name} = option; + }; + }; + + config = { + transposition.${name} = { }; + }; + }; + + # Needed pending https://github.com/NixOS/nixpkgs/pull/198450 + mkAliasOptionModule = from: to: { config, options, ... }: + let + fromOpt = getAttrFromPath from options; + toOf = attrByPath to + (abort "Renaming error: option `${showOption to}' does not exist."); + toType = let opt = attrByPath to { } options; in opt.type or (types.submodule { }); + in + { + options = setAttrByPath from (mkOption + { + visible = true; + description = "Alias of {option}`${showOption to}`."; + apply = x: (toOf config); + } // optionalAttrs (toType != null) { + type = toType; + }); + config = mkAliasAndWrapDefsWithPriority (setAttrByPath to) fromOpt; + }; + + # Helper function for importing while preserving module location. To be added + # in nixpkgs: https://github.com/NixOS/nixpkgs/pull/230588 + # I expect these functions to remain identical. This one will stick around + # for a while to support older nixpkgs-lib. + importApply = + modulePath: staticArgs: + lib.setDefaultModuleLocation modulePath (import modulePath staticArgs); + + inherit (import ./lib/memoize/memoize.nix { + inherit lib; + }) memoizeStr; + + /** + `importAndPublish name module` returns a module that both imports the `module`, and exposes it as flake attribute `modules.flake.${name}`. + + This also imports the optional [`modules`](https://flake.parts/options/flake-parts-modules.html) module to support that. + */ + importAndPublish = name: module: { lib, ... }: { + _class = "flake"; + imports = [ + module + ./extras/modules.nix + ]; + flake.modules.flake.${name} = module; + }; + }; + + # A best effort, lenient estimate. Please use a recent nixpkgs lib if you + # override it at all. + minVersion = "23.05pre-git"; + +in + +if builtins.compareVersions lib.version minVersion < 0 +then + abort '' + The nixpkgs-lib dependency of flake-parts was overridden but is too old. + The minimum supported version of nixpkgs-lib is ${minVersion}, + but the actual version is ${lib.version}${revInfo}. + '' +else + + flake-parts-lib diff --git a/nix/snow/module.nix b/nix/snow/flake/module.nix similarity index 100% rename from nix/snow/module.nix rename to nix/snow/flake/module.nix diff --git a/nix/snow/flake/modules/apps.nix b/nix/snow/flake/modules/apps.nix new file mode 100644 index 0000000..3030d32 --- /dev/null +++ b/nix/snow/flake/modules/apps.nix @@ -0,0 +1,61 @@ +{ lib, flake-parts-lib, ... }: +let + inherit (lib) + mkOption + types + ; + inherit (flake-parts-lib) + mkTransposedPerSystemModule + ; + + programType = lib.types.coercedTo derivationType lib.getExe lib.types.str; + + derivationType = lib.types.package // { + check = lib.isDerivation; + }; + + 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 . + + Note: `nix flake check` is only aware of the `description` attribute in `meta`. + ''; + }; + }; + }; +in +mkTransposedPerSystemModule { + name = "apps"; + option = mkOption { + type = types.lazyAttrsOf appType; + default = { }; + description = '' + Programs runnable with nix run ``. + ''; + example = lib.literalExpression '' + { + default.program = "''${config.packages.hello}/bin/hello"; + } + ''; + }; + file = ./apps.nix; +} diff --git a/nix/snow/flake/modules/checks.nix b/nix/snow/flake/modules/checks.nix new file mode 100644 index 0000000..9e7ceae --- /dev/null +++ b/nix/snow/flake/modules/checks.nix @@ -0,0 +1,21 @@ +{ lib, flake-parts-lib, ... }: +let + inherit (lib) + mkOption + types + ; + inherit (flake-parts-lib) + mkTransposedPerSystemModule + ; +in +mkTransposedPerSystemModule { + 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; +} diff --git a/nix/snow/flake/modules/debug.nix b/nix/snow/flake/modules/debug.nix new file mode 100644 index 0000000..995f13b --- /dev/null +++ b/nix/snow/flake/modules/debug.nix @@ -0,0 +1,78 @@ +{ config, flake-parts-lib, lib, options, getSystem, extendModules, ... }: +let + inherit (lib) + mapAttrs + mkIf + mkOption + optionalAttrs + types + ; + inherit (flake-parts-lib) + mkPerSystemOption + ; + + mkDebugConfig = { config, options, extendModules }: config // { + inherit config; + inherit (config) _module; + inherit options; + inherit extendModules; + }; +in +{ + options = { + debug = mkOption { + type = types.bool; + default = false; + description = '' + Whether to add the attributes `debug`, `allSystems` and `currentSystem` + to the flake output. When `true`, this allows inspection of options via + `nix repl`. + + ``` + $ nix repl + nix-repl> :lf . + nix-repl> currentSystem._module.args.pkgs.hello + «derivation /nix/store/7vf0d0j7majv1ch1xymdylyql80cn5fp-hello-2.12.1.drv» + ``` + + Each of `debug`, `allSystems.` and `currentSystem` is an + attribute set consisting of the `config` attributes, plus the extra + attributes `_module`, `config`, `options`, `extendModules`. So note that + these are not part of the `config` parameter, but are merged in for + debugging convenience. + + - `debug`: The top-level options + - `allSystems`: The `perSystem` submodule applied to the configured `systems`. + - `currentSystem`: Shortcut into `allSystems`. Only available in impure mode. + Works for arbitrary system values. + + See [Expore and debug option values](../debug.html) for more examples. + ''; + }; + perSystem = mkPerSystemOption + ({ options, config, extendModules, ... }: { + _file = ./formatter.nix; + options = { + debug = mkOption { + description = '' + Values to return in e.g. `allSystems.` when + [`debug = true`](#opt-debug). + ''; + type = types.lazyAttrsOf types.raw; + }; + }; + config = { + debug = mkDebugConfig { inherit config options extendModules; }; + }; + }); + }; + + config = mkIf config.debug { + flake = { + debug = mkDebugConfig { inherit config options extendModules; }; + allSystems = mapAttrs (_s: c: c.debug) config.allSystems; + } // optionalAttrs (builtins?currentSystem) { + currentSystem = (getSystem builtins.currentSystem).debug; + }; + }; +} diff --git a/nix/snow/flake/modules/devShells.nix b/nix/snow/flake/modules/devShells.nix new file mode 100644 index 0000000..c0cc6c5 --- /dev/null +++ b/nix/snow/flake/modules/devShells.nix @@ -0,0 +1,30 @@ +{ lib, flake-parts-lib, ... }: +let + inherit (lib) + mkOption + types + literalExpression + ; + inherit (flake-parts-lib) + mkTransposedPerSystemModule + ; +in +mkTransposedPerSystemModule { + name = "devShells"; + option = mkOption { + type = types.lazyAttrsOf types.package; + default = { }; + description = '' + An attribute set of packages to be used as shells. + [`nix develop .#`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-develop.html) will run `devShells.`. + ''; + example = literalExpression '' + { + default = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ wget bat cargo ]; + }; + } + ''; + }; + file = ./devShells.nix; +} diff --git a/nix/snow/flake/modules/flake.nix b/nix/snow/flake/modules/flake.nix new file mode 100644 index 0000000..871f04d --- /dev/null +++ b/nix/snow/flake/modules/flake.nix @@ -0,0 +1,47 @@ +{ + lib, + config, + ... +}: let + inherit + (lib) + mkOption + types + ; + + flake = 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 + Many modules are listed at https://flake.parts + - 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. + ''; + }; +in { + options = { + inherit flake; + output = {inherit flake;}; + }; + + config = {inherit (config) flake;}; +} diff --git a/nix/snow/flake/modules/formatter.nix b/nix/snow/flake/modules/formatter.nix new file mode 100644 index 0000000..e2959ed --- /dev/null +++ b/nix/snow/flake/modules/formatter.nix @@ -0,0 +1,52 @@ +{ config, lib, flake-parts-lib, ... }: +let + inherit (lib) + filterAttrs + mapAttrs + mkOption + optionalAttrs + types + ; + inherit (flake-parts-lib) + mkPerSystemOption + ; +in +{ + options = { + flake.formatter = mkOption { + type = types.lazyAttrsOf types.package; + default = { }; + description = '' + An attribute set of per system a package used by [`nix fmt`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-fmt.html). + ''; + }; + + perSystem = mkPerSystemOption { + _file = ./formatter.nix; + options = { + formatter = 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). + ''; + }; + }; + }; + }; + config = { + flake.formatter = + mapAttrs + (k: v: v.formatter) + (filterAttrs + (k: v: v.formatter != null) + config.allSystems + ); + + perInput = system: flake: + optionalAttrs (flake?formatter.${system}) { + formatter = flake.formatter.${system}; + }; + + }; +} diff --git a/nix/snow/flake/modules/legacyPackages.nix b/nix/snow/flake/modules/legacyPackages.nix new file mode 100644 index 0000000..fb17e14 --- /dev/null +++ b/nix/snow/flake/modules/legacyPackages.nix @@ -0,0 +1,21 @@ +{ lib, flake-parts-lib, ... }: +let + inherit (lib) + mkOption + types + ; + inherit (flake-parts-lib) + mkTransposedPerSystemModule + ; +in +mkTransposedPerSystemModule { + name = "legacyPackages"; + option = mkOption { + type = types.lazyAttrsOf types.raw; + default = { }; + description = '' + An attribute set of unmergeable values. This is also used by [`nix build .#`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-build.html). + ''; + }; + file = ./legacyPackages.nix; +} diff --git a/nix/snow/flake/modules/moduleWithSystem.nix b/nix/snow/flake/modules/moduleWithSystem.nix new file mode 100644 index 0000000..e5c7008 --- /dev/null +++ b/nix/snow/flake/modules/moduleWithSystem.nix @@ -0,0 +1,32 @@ +{ withSystem, ... }: +{ + config = { + _module.args = { + moduleWithSystem = + module: + + { config, ... }: + let + system = + config._module.args.system or + config._module.args.pkgs.stdenv.hostPlatform.system or + (throw "moduleWithSystem: Could not determine the configuration's system parameter for this module system application."); + + allArgs = withSystem system (args: args); + + lazyArgsPerParameter = f: builtins.mapAttrs + (k: v: allArgs.${k} or (throw "moduleWithSystem: module argument `${k}` does not exist.")) + (builtins.functionArgs f); + + # Use reflection to make the call lazy in the argument. + # Restricts args to the ones declared. + callLazily = f: a: f (lazyArgsPerParameter f); + in + { + imports = [ + (callLazily module allArgs) + ]; + }; + }; + }; +} diff --git a/nix/snow/flake/modules/nixosConfigurations.nix b/nix/snow/flake/modules/nixosConfigurations.nix new file mode 100644 index 0000000..597132d --- /dev/null +++ b/nix/snow/flake/modules/nixosConfigurations.nix @@ -0,0 +1,36 @@ +{ lib, ... }: +let + inherit (lib) + mkOption + types + literalExpression + ; +in +{ + options = { + flake.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 + ]; + }; + } + ''; + }; + }; +} diff --git a/nix/snow/flake/modules/nixosModules.nix b/nix/snow/flake/modules/nixosModules.nix new file mode 100644 index 0000000..86ee9cc --- /dev/null +++ b/nix/snow/flake/modules/nixosModules.nix @@ -0,0 +1,26 @@ +{ self, lib, moduleLocation, ... }: +let + inherit (lib) + mapAttrs + mkOption + types + ; +in +{ + options = { + flake.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. + ''; + }; + }; +} diff --git a/nix/snow/flake/modules/nixpkgs.nix b/nix/snow/flake/modules/nixpkgs.nix new file mode 100644 index 0000000..44df915 --- /dev/null +++ b/nix/snow/flake/modules/nixpkgs.nix @@ -0,0 +1,26 @@ +# +# Nixpkgs module. The only exception to the rule. +# +# Provides a `pkgs` argument in `perSystem`. +# +# Arguably, this shouldn't be in flake-parts, but in nixpkgs. +# Nixpkgs could define its own module that does this, which would be +# a more consistent UX, but for now this will do. +# +# The existence of this module does not mean that other flakes' logic +# will be accepted into flake-parts, because it's against the +# spirit of Flakes. +# +{ + config = { + perSystem = { inputs', lib, ... }: { + config = { + _module.args.pkgs = lib.mkOptionDefault ( + builtins.seq + (inputs'.nixpkgs or (throw "flake-parts: The flake does not have a `nixpkgs` input. Please add it, or set `perSystem._module.args.pkgs` yourself.")) + inputs'.nixpkgs.legacyPackages + ); + }; + }; + }; +} diff --git a/nix/snow/flake/modules/overlays.nix b/nix/snow/flake/modules/overlays.nix new file mode 100644 index 0000000..172336c --- /dev/null +++ b/nix/snow/flake/modules/overlays.nix @@ -0,0 +1,32 @@ +{ lib, ... }: +let + inherit (lib) + mkOption + types + ; +in +{ + options = { + flake.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`. + ''; + }; + }; +} diff --git a/nix/snow/flake/modules/packages.nix b/nix/snow/flake/modules/packages.nix new file mode 100644 index 0000000..20f0071 --- /dev/null +++ b/nix/snow/flake/modules/packages.nix @@ -0,0 +1,23 @@ +{ lib, flake-parts-lib, ... }: +let + inherit (lib) + mkOption + types + ; + inherit (flake-parts-lib) + mkTransposedPerSystemModule + ; +in +mkTransposedPerSystemModule { + 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 .#` will build `packages.`. + ''; + }; + file = ./packages.nix; +} diff --git a/nix/snow/flake/modules/perSystem.nix b/nix/snow/flake/modules/perSystem.nix new file mode 100644 index 0000000..d4890ef --- /dev/null +++ b/nix/snow/flake/modules/perSystem.nix @@ -0,0 +1,159 @@ +{ config, lib, flake-parts-lib, self, ... }: +let + inherit (lib) + genAttrs + mapAttrs + mkOption + types + ; + inherit (lib.strings) + escapeNixIdentifier + ; + inherit (flake-parts-lib) + mkPerSystemType + ; + + rootConfig = config; + + # Stubs for self and inputs. While it'd be possible to define aliases + # inside perSystem, that is not a general solution, and it would make + # top.config harder to discover, stretching the learning curve rather + # than flattening it. + + throwAliasError' = param: + throw '' + `${param}` (without `'`) is not a `perSystem` module argument, but a + module argument of the top level config. + + The following is an example usage of `${param}`. Note that its binding + is in the `top` parameter list, which is declared by the top level module + rather than the `perSystem` module. + + top@{ config, lib, ${param}, ... }: { + perSystem = { config, ${param}', ... }: { + # in scope here: + # - ${param} + # - ${param}' + # - config (of perSystem) + # - top.config (note the `top@` pattern) + }; + } + ''; + + throwAliasError = param: + throw '' + `${param}` is not a `perSystem` module argument, but a module argument of + the top level config. + + The following is an example usage of `${param}`. Note that its binding + is in the `top` parameter list, which is declared by the top level module + rather than the `perSystem` module. + + top@{ config, lib, ${param}, ... }: { + perSystem = { config, ... }: { + # in scope here: + # - ${param} + # - config (of perSystem) + # - top.config (note the `top@` pattern) + }; + } + ''; + + /** + We primarily use `systems` to help memoize the per system context, but that + doesn't extend to arbitrary `system`s. + For that, we use the slightly less efficient, but perfectly acceptable + `memoizeStr` function. + */ + otherMemoizedSystems = flake-parts-lib.memoizeStr config.perSystem; + +in +{ + options = { + systems = mkOption { + description = '' + All the system types to enumerate in the flake output subattributes. + + In other words, all valid values for `system` in e.g. `packages..foo`. + ''; + type = types.listOf types.str; + }; + + perInput = mkOption { + description = '' + A function that pre-processes flake inputs. + + It is called for users of `perSystem` such that `inputs'.''${name} = config.perInput system inputs.''${name}`. + + This is used for [`inputs'`](../module-arguments.html#inputs) and [`self'`](../module-arguments.html#self). + + The attributes returned by the `perInput` function definitions are merged into a single namespace (per input), + so each module should return an attribute set with usually only one or two predictable attribute names. Otherwise, + the `inputs'` namespace gets polluted. + ''; + type = types.functionTo (types.functionTo (types.lazyAttrsOf types.unspecified)); + }; + + perSystem = mkOption { + description = '' + A function from system to flake-like attributes omitting the `` attribute. + + Modules defined here have access to the suboptions and [some convenient module arguments](../module-arguments.html). + ''; + type = mkPerSystemType ({ config, system, ... }: { + _file = ./perSystem.nix; + config = { + _module.args.inputs' = + mapAttrs + (inputName: input: + builtins.addErrorContext "while retrieving system-dependent attributes for input ${escapeNixIdentifier inputName}" ( + if input._type or null == "flake" + then rootConfig.perInput system input + else + throw "Trying to retrieve system-dependent attributes for input ${escapeNixIdentifier inputName}, but this input is not a flake. Perhaps flake = false was added to the input declarations by mistake, or you meant to use a different input, or you meant to use plain old inputs, not inputs'." + ) + ) + self.inputs; + _module.args.self' = + builtins.addErrorContext "while retrieving system-dependent attributes for a flake's own outputs" ( + rootConfig.perInput system self + ); + + # Custom error messages + _module.args.self = throwAliasError' "self"; + _module.args.inputs = throwAliasError' "inputs"; + _module.args.getSystem = throwAliasError "getSystem"; + _module.args.withSystem = throwAliasError "withSystem"; + _module.args.moduleWithSystem = throwAliasError "moduleWithSystem"; + }; + }); + apply = modules: system: + (lib.evalModules { + inherit modules; + prefix = [ "perSystem" system ]; + specialArgs = { + inherit system; + }; + class = "perSystem"; + }).config; + }; + + allSystems = mkOption { + type = types.lazyAttrsOf types.unspecified; + description = "The system-specific config for each of systems."; + internal = true; + }; + }; + + config = { + allSystems = genAttrs config.systems config.perSystem; + _module.args.getSystem = system: config.allSystems.${system} or (otherMemoizedSystems system); + + # The warning is there for a reason. Only use this in situations where the + # performance cost has already been incurred, such as in `flakeModules.easyOverlay`, + # where we run in the context of an overlay, and the performance cost of the + # extra `pkgs` makes the cost of running `perSystem` probably negligible. + _module.args.getSystemIgnoreWarning = system: config.allSystems.${system} or (config.perSystem system); + }; + +} diff --git a/nix/snow/flake/modules/transposition.nix b/nix/snow/flake/modules/transposition.nix new file mode 100644 index 0000000..d532e76 --- /dev/null +++ b/nix/snow/flake/modules/transposition.nix @@ -0,0 +1,132 @@ +{ config, lib, flake-parts-lib, ... }: + +let + inherit (lib) + filterAttrs + mapAttrs + mkOption + types + ; + inherit (lib.strings) + escapeNixIdentifier + ; + + transpositionModule = { + options = { + adHoc = mkOption { + type = types.bool; + default = false; + description = '' + Whether to provide a stub option declaration for {option}`perSystem.`. + + The stub option declaration does not support merging and lacks + documentation, so you are recommended to declare the {option}`perSystem.` + option yourself and avoid {option}`adHoc`. + ''; + }; + }; + }; + + perInputAttributeError = { flake, attrName, system, attrConfig }: + # This uses flake.outPath for lack of a better identifier. + # Consider adding a perInput variation that has a normally-redundant argument for the input name. + # Tested manually with + # perSystem = { inputs', ... }: { + # packages.extra = inputs'.nixpkgs.extra; + # packages.default = inputs'.nixpkgs.packages.default; + # packages.veryWrong = (top.config.perInput "x86_64-linux" inputs'.nixpkgs.legacyPackages.hello).packages.default; + # }; + # transposition.extra = {}; + let + attrPath = "${escapeNixIdentifier attrName}.${escapeNixIdentifier system}"; + flakeIdentifier = + if flake._type or null != "flake" + then + throw "An attempt was made to access attribute ${attrPath} on a value that's supposed to be a flake, but may not be a proper flake." + else + builtins.addErrorContext "while trying to find out how to describe what is supposedly a flake, whose attribute ${attrPath} was accessed but does not exist" ( + toString flake.outPath + ); + # This ought to be generalized by extending attrConfig, but this is the only known and common mistake for now. + alternateAttrNameHint = + if attrName == "packages" && flake?legacyPackages + then # Unfortunately we can't just switch them out, because that will put packages *sets* where single packages are expected in user code, resulting in potentially much worse and more confusing errors down the line. + "\nIt does define legacyPackages; try that instead?" + else ""; + in + if flake?${attrName} + then + throw '' + Attempt to access ${attrPath} of flake ${flakeIdentifier}, but it does not have it. + It does have attribute ${escapeNixIdentifier attrName}, so it appears that it does not support system type ${escapeNixIdentifier system}. + '' + else + throw '' + Attempt to access ${attrPath} of flake ${flakeIdentifier}, but it does not have attribute ${escapeNixIdentifier attrName}.${alternateAttrNameHint} + ''; + + +in +{ + options = { + transposition = lib.mkOption { + description = '' + A helper that defines transposed attributes in the flake outputs. + + When you define `transposition.foo = { };`, definitions are added to the effect of (pseudo-code): + + ```nix + flake.foo.''${system} = (perSystem system).foo; + perInput = system: inputFlake: inputFlake.foo.''${system}; + ``` + + Transposition is the operation that swaps the indices of a data structure. + Here it refers specifically to the transposition between + + ```plain + perSystem: .''${system}.''${attribute} + outputs: .''${attribute}.''${system} + ``` + + It also defines the reverse operation in [{option}`perInput`](#opt-perInput). + ''; + type = + types.lazyAttrsOf + (types.submoduleWith { modules = [ transpositionModule ]; }); + }; + }; + + config = { + flake = + lib.mapAttrs + (attrName: attrConfig: + mapAttrs + (system: v: v.${attrName} or ( + abort '' + Could not find option ${attrName} in the perSystem module. It is required to declare such an option whenever transposition. is defined (and in this instance is ${attrName}). + '')) + config.allSystems + ) + config.transposition; + + perInput = + system: flake: + mapAttrs + (attrName: attrConfig: + flake.${attrName}.${system} or ( + throw (perInputAttributeError { inherit system flake attrName attrConfig; }) + ) + ) + config.transposition; + + perSystem = { + options = + mapAttrs + (k: v: lib.mkOption { }) + (filterAttrs + (k: v: v.adHoc) + config.transposition + ); + }; + }; +} diff --git a/nix/snow/flake/modules/withSystem.nix b/nix/snow/flake/modules/withSystem.nix new file mode 100644 index 0000000..161eece --- /dev/null +++ b/nix/snow/flake/modules/withSystem.nix @@ -0,0 +1,37 @@ +{ lib, flake-parts-lib, getSystem, ... }: +let + inherit (lib) + mkOption + types + ; + inherit (flake-parts-lib) + mkPerSystemOption + ; +in +{ + options = { + perSystem = mkPerSystemOption ({ config, options, specialArgs, ... }: { + _file = ./perSystem.nix; + options = { + allModuleArgs = mkOption { + type = types.lazyAttrsOf (types.raw or types.unspecified); + internal = true; + readOnly = true; + description = "Internal option that exposes _module.args, for use by withSystem."; + }; + }; + config = { + allModuleArgs = config._module.args // specialArgs // { inherit config options; }; + }; + }); + }; + + config = { + _module.args = { + withSystem = + system: f: + f + (getSystem system).allModuleArgs; + }; + }; +} diff --git a/nix/snow/nodes/default.nix b/nix/snow/flake/nodes/default.nix similarity index 100% rename from nix/snow/nodes/default.nix rename to nix/snow/flake/nodes/default.nix diff --git a/nix/snow/nodes/shared.nix b/nix/snow/flake/nodes/shared.nix similarity index 100% rename from nix/snow/nodes/shared.nix rename to nix/snow/flake/nodes/shared.nix diff --git a/nix/snow/nodes/submodule.nix b/nix/snow/flake/nodes/submodule.nix similarity index 100% rename from nix/snow/nodes/submodule.nix rename to nix/snow/flake/nodes/submodule.nix diff --git a/nix/snow/flake/outputs/checks.nix b/nix/snow/flake/outputs/checks.nix new file mode 100644 index 0000000..21fd677 --- /dev/null +++ b/nix/snow/flake/outputs/checks.nix @@ -0,0 +1,5 @@ + checks = + inputs.deploy-rs.lib + |> mapAttrs (system: deployLib: + deployLib.deployChecks deploy); + diff --git a/nix/snow/flake/outputs/deploy.nix b/nix/snow/flake/outputs/deploy.nix new file mode 100644 index 0000000..08caa8f --- /dev/null +++ b/nix/snow/flake/outputs/deploy.nix @@ -0,0 +1,57 @@ + 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"] + ); + }; + }); + diff --git a/nix/snow/flake/outputs/nixosConfigurations.nix b/nix/snow/flake/outputs/nixosConfigurations.nix new file mode 100644 index 0000000..799758d --- /dev/null +++ b/nix/snow/flake/outputs/nixosConfigurations.nix @@ -0,0 +1,67 @@ +# { +# _module = { ... }; +# _type = "configuration"; +# class = null; +# config = { ... }; +# extendModules = «lambda extendModules @ /nix/store/9hfp0agnm43kz72l5lpfn9var5p0x2fa-source/lib/modules.nix:340:9»; +# graph = [ ... ]; +# options = { ... }; +# type = { ... }; +# } + 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... Date: Mon, 9 Mar 2026 02:54:01 +1000 Subject: [PATCH 08/19] da future --- TODO.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/TODO.md b/TODO.md index 7a23e43..26ecbc1 100755 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,14 @@ ## Next +- [ ] figure out how Cerulean could aid CI/CD (ie hydra + nix-unit) + you can + https://github.com/NotAShelf/nix-bindings/tree/main/nix-bindings + https://notashelf.github.io/nix-bindings/nix_bindings/#structs + https://github.com/nixops4/nix-bindings-rust + https://nix.dev/manual/nix/2.34/c-api.html + +- [ ] write a key management system that supports activation time, run time, and build time + https://docs.aws.amazon.com/kms/latest/developerguide/overview.html + - [ ] formalize how the snow flake system compiles outputs, this would remove the need for `mapNodes` - [ ] groups should allow you to set node configuration defaults From b1b17434146d1d54ce4ccfa3f080f313888bdf56 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Mar 2026 21:01:02 +1000 Subject: [PATCH 09/19] warn if reserved inputs provided --- nix/snow/flake/default.nix | 54 ++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/nix/snow/flake/default.nix b/nix/snow/flake/default.nix index fad3c6d..b90126b 100644 --- a/nix/snow/flake/default.nix +++ b/nix/snow/flake/default.nix @@ -4,23 +4,55 @@ systems, ... }: let + inherit + (builtins) + attrNames + concatStringsSep + filter + length + removeAttrs + warn + ; + inherit (inputs.nixpkgs) lib; in { # snow.flake flake = flakeInputs: root: let snowflake = lib.evalModules { class = "snowflake"; - # XXX: TODO: abort if inputs contains reserved names - specialArgs = - (flakeInputs - // { - inherit (this) snow; - inherit systems root; - inputs = flakeInputs; - }) - # XXX: TODO: - # |> (x: builtins.removeAttrs x ["self" "nodes"]); - |> (x: builtins.removeAttrs x ["self"]); + specialArgs = let + reservedInputs = { + inherit (this) snow; + inherit systems root; + inputs = flakeInputs; + }; + + warnIfReserved = let + getReservedNames = names: + reservedInputs + |> attrNames + |> filter (name: names?${name}); + + reservedNames = + flakeInputs + |> attrNames + |> getReservedNames; + in + (length reservedNames == 0) + || warn '' + [snow] Your `flake.nix` declares inputs using reserved names! + [snow] These will be accessible only via `inputs.''${NAME}` + [snow] Please rename the following: + [snow] ${concatStringsSep reservedNames ", "} + '' + true; + in + assert warnIfReserved; + flakeInputs + // reservedInputs + # XXX: TODO: + # |> (x: builtins.removeAttrs x ["self" "nodes"]); + |> (x: removeAttrs x ["self"]); modules = [ ./module.nix From d891a92357a3c49a751c526e6a390559415c697e Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Mar 2026 22:18:28 +1000 Subject: [PATCH 10/19] redesign module hierarchy --- nix/snow/flake/default.nix | 20 +- nix/snow/flake/lib.nix | 49 +++ nix/snow/flake/lib.nix.bak | 318 ------------------ nix/snow/flake/module.nix | 1 + nix/snow/flake/modules/README.md | 3 + nix/snow/flake/modules/apps.nix | 62 ++-- nix/snow/flake/modules/checks.nix | 37 +- nix/snow/flake/modules/debug.nix | 78 ----- nix/snow/flake/modules/default.nix | 15 + nix/snow/flake/modules/devShells.nix | 53 +-- nix/snow/flake/modules/formatter.nix | 62 +--- nix/snow/flake/modules/legacyPackages.nix | 37 +- nix/snow/flake/modules/moduleWithSystem.nix | 32 -- .../flake/modules/nixosConfigurations.nix | 13 +- nix/snow/flake/modules/nixosModules.nix | 19 +- nix/snow/flake/modules/nixpkgs.nix | 26 -- .../flake/modules/{flake.nix => outputs.nix} | 5 +- nix/snow/flake/modules/overlays.nix | 13 +- nix/snow/flake/modules/packages.nix | 40 ++- nix/snow/flake/modules/perSystem.nix | 159 --------- nix/snow/flake/modules/transposition.nix | 132 -------- nix/snow/flake/modules/withSystem.nix | 37 -- 22 files changed, 244 insertions(+), 967 deletions(-) create mode 100644 nix/snow/flake/lib.nix delete mode 100644 nix/snow/flake/lib.nix.bak create mode 100644 nix/snow/flake/modules/README.md delete mode 100644 nix/snow/flake/modules/debug.nix create mode 100644 nix/snow/flake/modules/default.nix delete mode 100644 nix/snow/flake/modules/moduleWithSystem.nix delete mode 100644 nix/snow/flake/modules/nixpkgs.nix rename nix/snow/flake/modules/{flake.nix => outputs.nix} (94%) delete mode 100644 nix/snow/flake/modules/perSystem.nix delete mode 100644 nix/snow/flake/modules/transposition.nix delete mode 100644 nix/snow/flake/modules/withSystem.nix diff --git a/nix/snow/flake/default.nix b/nix/snow/flake/default.nix index b90126b..9c5d1f5 100644 --- a/nix/snow/flake/default.nix +++ b/nix/snow/flake/default.nix @@ -10,7 +10,6 @@ concatStringsSep filter length - removeAttrs warn ; @@ -21,7 +20,7 @@ in { snowflake = lib.evalModules { class = "snowflake"; specialArgs = let - reservedInputs = { + reservedSpecialArgs = { inherit (this) snow; inherit systems root; inputs = flakeInputs; @@ -29,7 +28,7 @@ in { warnIfReserved = let getReservedNames = names: - reservedInputs + reservedSpecialArgs |> attrNames |> filter (name: names?${name}); @@ -40,7 +39,7 @@ in { in (length reservedNames == 0) || warn '' - [snow] Your `flake.nix` declares inputs using reserved names! + [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 ", "} @@ -48,21 +47,10 @@ in { true; in assert warnIfReserved; - flakeInputs - // reservedInputs - # XXX: TODO: - # |> (x: builtins.removeAttrs x ["self" "nodes"]); - |> (x: removeAttrs x ["self"]); + flakeInputs // reservedSpecialArgs; modules = [ ./module.nix - ({config, ...}: { - _module.args = { - self = config; - # XXX: TODO: - # nodes = config.nodes.nodes; - }; - }) ]; }; in diff --git a/nix/snow/flake/lib.nix b/nix/snow/flake/lib.nix new file mode 100644 index 0000000..43326c9 --- /dev/null +++ b/nix/snow/flake/lib.nix @@ -0,0 +1,49 @@ +{ + lib, + revInfo ? "", +}: 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 = + (builtins.compareVersions lib.version minVersion < 0) + # XXX: TODO: make this message snow specific + || abort '' + The nixpkgs-lib dependency of flake-parts 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. + ''; + }; + }; + }; + } diff --git a/nix/snow/flake/lib.nix.bak b/nix/snow/flake/lib.nix.bak deleted file mode 100644 index c8ea2ba..0000000 --- a/nix/snow/flake/lib.nix.bak +++ /dev/null @@ -1,318 +0,0 @@ -{ lib - # Optionally a string with extra version info to be included in the error message - # in case is lib is out of date. Empty or starts with space. -, revInfo ? "" -}: -let - inherit (lib) - mkOption - mkOptionType - defaultFunctor - isAttrs - isFunction - showOption - throwIf - types - warnIf - getAttrFromPath - setAttrByPath - attrByPath - optionalAttrs - ; - inherit (lib.modules) - mkAliasAndWrapDefsWithPriority; - inherit (lib.types) - path - submoduleWith - ; - - # Polyfill isFlake until Nix with https://github.com/NixOS/nix/pull/7207 is common - isFlake = maybeFlake: - if maybeFlake ? _type - then maybeFlake._type == "flake" - else maybeFlake ? inputs && maybeFlake ? outputs && maybeFlake ? sourceInfo; - - /** - Deprecated for any use except type-merging into `perSystem`. - Use `lib.types.deferredModuleWith` instead, and add `apply = m: [ m ];` if needed. - - The deferredModule type was pioneered in flake-parts for the `perSystem` option. - The Nixpkgs version has an improved merge function that returns a single module, - whereas this version returns a list. The flake-parts version was not updated to - match this improvement in Nixpkgs. - - # History - - This predates `lib.types.deferredModuleWith`, added in Nixpkgs 22.11 - (https://github.com/NixOS/nixpkgs/pull/163617). - Documented as deprecated in flake-parts in January 2026. - */ - deferredModuleWith = - attrs@{ staticModules ? [ ] }: mkOptionType { - name = "deferredModule"; - description = "module"; - check = x: isAttrs x || isFunction x || path.check x; - merge = loc: defs: staticModules ++ map (def: lib.setDefaultModuleLocation "${def.file}, via option ${showOption loc}" def.value) defs; - inherit (submoduleWith { modules = staticModules; }) - getSubOptions - getSubModules; - substSubModules = m: deferredModuleWith (attrs // { - staticModules = m; - }); - functor = defaultFunctor "deferredModuleWith" // { - type = deferredModuleWith; - payload = { - inherit staticModules; - }; - binOp = lhs: rhs: { - staticModules = lhs.staticModules ++ rhs.staticModules; - }; - }; - }; - - # Internal: preserves legacy list-merge behavior for perSystem type-merging. - mkLegacyDeferredModuleType = - module: - deferredModuleWith { - staticModules = [ module ]; - }; - - errorExample = '' - For example: - - outputs = inputs@{ flake-parts, ... }: - flake-parts.lib.mkFlake { inherit inputs; } { /* module */ }; - - To avoid an infinite recursion, *DO NOT* pass `self.inputs` and - *DO NOT* pass `inherit (self) inputs`, but pass the output function - arguments as `inputs` like above. - ''; - - flake-parts-lib = rec { - evalFlakeModule = - args@ - { inputs ? self.inputs - , specialArgs ? { } - - # legacy - , self ? inputs.self or (throw '' - When invoking flake-parts, you must pass all the flake output arguments, - and not just `self.inputs`. - - ${errorExample} - '') - , moduleLocation ? "${self.outPath}/flake.nix" - }: - let - inputsPos = builtins.unsafeGetAttrPos "inputs" args; - errorLocation = - # Best case: user makes it explicit - args.moduleLocation or ( - # Slightly worse: Nix does not technically commit to unsafeGetAttrPos semantics - if inputsPos != null - then inputsPos.file - # Slightly worse: self may not be valid when an error occurs - else if args?inputs.self.outPath - then args.inputs.self.outPath + "/flake.nix" - # Fallback - else "" - ); - in - throwIf - (!args?self && !args?inputs) '' - When invoking flake-parts, you must pass in the flake output arguments. - - ${errorExample} - '' - warnIf - (!args?inputs) '' - When invoking flake-parts, it is recommended to pass all the flake output - arguments in the `inputs` parameter. If you only pass `self`, it's not - possible to use the `inputs` module argument in the module `imports`. - - Please pass the output function arguments. ${errorExample} - '' - - (module: - lib.evalModules { - specialArgs = { - inherit self flake-parts-lib moduleLocation; - inputs = args.inputs or /* legacy, warned above */ self.inputs; - } // specialArgs; - modules = [ ./all-modules.nix (lib.setDefaultModuleLocation errorLocation module) ]; - class = "flake"; - } - ); - - # Function to extract the default flakeModule from - # what may be a flake, returning the argument unmodified - # if it's not a flake. - # - # Useful to map over an 'imports' list to make it less - # verbose in the common case. - defaultModule = maybeFlake: - if isFlake maybeFlake - then maybeFlake.flakeModules.default or maybeFlake - else maybeFlake; - - mkFlake = args: module: - let - eval = flake-parts-lib.evalFlakeModule args module; - in - eval.config.flake; - - /** - Deprecated. Declare options directly, e.g. `options.foo.bar = mkOption { ... }`, - provided that `foo` is already declared as a submodule option. - - In flake-parts, `flake` is declared as a submodule option by the core modules, - so `options.flake.` declarations work directly. - - This function wraps option declarations in a submodule, allowing them to - be merged into an existing submodule option. For example, if `foo` is - already declared as a submodule option, using - `options.foo = mkSubmoduleOptions { bar = mkOption {...}; }` would add - `bar` to the `foo` submodule. - - # History - - This was a workaround for https://github.com/NixOS/nixpkgs/issues/146882, - fixed in Nixpkgs 22.05 by https://github.com/NixOS/nixpkgs/pull/156533. - With the fix, declaring `options.foo.bar` directly works when `foo` is - already a submodule option. Documented as deprecated in flake-parts in January 2026. - */ - mkSubmoduleOptions = - options: - mkOption { - type = types.submoduleWith { - modules = [{ inherit options; }]; - }; - }; - - /** - Deprecated. Use mkPerSystemType/mkPerSystemOption for `perSystem` type-merging, or - use Nixpkgs `types.deferredModule` directly, noting the lack of list wrapping; - see `deferredModuleWith` docs. - */ - mkDeferredModuleType = mkLegacyDeferredModuleType; - - /** - Given a module, construct an option type suitable for type-merging into `perSystem`'s type. - */ - mkPerSystemType = mkLegacyDeferredModuleType; - - /** - Deprecated. Use mkPerSystemOption for `perSystem` type-merging, or - use `mkOption` and Nixpkgs `types.deferredModule` directly, noting the - lack of list wrapping; see `deferredModuleWith` docs. - */ - mkDeferredModuleOption = - module: - mkOption { - type = flake-parts-lib.mkPerSystemType module; - }; - - /** - Given a module, construct an option declaration suitable for merging into the core `perSystem` module. - */ - mkPerSystemOption = mkDeferredModuleOption; - - # Polyfill https://github.com/NixOS/nixpkgs/pull/344216 - # Nixpkgs master 2024-12-09, Nixpkgs 25.05 - attrsWith = types.attrsWith or ({ elemType, lazy ? false, placeholder ? "name" }: - if lazy then types.attrsOf elemType else types.lazyAttrsOf elemType); - - # Helper function for defining a per-system option that - # gets transposed by the usual flake system logic to a - # top-level flake attribute. - mkTransposedPerSystemModule = { name, option, file }: { - _file = file; - - options = { - flake.${name} = mkOption { - type = attrsWith { - elemType = option.type; - lazy = true; - placeholder = "system"; - }; - default = { }; - description = '' - See {option}`perSystem.${name}` for description and examples. - ''; - }; - - perSystem = flake-parts-lib.mkPerSystemOption { - _file = file; - - options.${name} = option; - }; - }; - - config = { - transposition.${name} = { }; - }; - }; - - # Needed pending https://github.com/NixOS/nixpkgs/pull/198450 - mkAliasOptionModule = from: to: { config, options, ... }: - let - fromOpt = getAttrFromPath from options; - toOf = attrByPath to - (abort "Renaming error: option `${showOption to}' does not exist."); - toType = let opt = attrByPath to { } options; in opt.type or (types.submodule { }); - in - { - options = setAttrByPath from (mkOption - { - visible = true; - description = "Alias of {option}`${showOption to}`."; - apply = x: (toOf config); - } // optionalAttrs (toType != null) { - type = toType; - }); - config = mkAliasAndWrapDefsWithPriority (setAttrByPath to) fromOpt; - }; - - # Helper function for importing while preserving module location. To be added - # in nixpkgs: https://github.com/NixOS/nixpkgs/pull/230588 - # I expect these functions to remain identical. This one will stick around - # for a while to support older nixpkgs-lib. - importApply = - modulePath: staticArgs: - lib.setDefaultModuleLocation modulePath (import modulePath staticArgs); - - inherit (import ./lib/memoize/memoize.nix { - inherit lib; - }) memoizeStr; - - /** - `importAndPublish name module` returns a module that both imports the `module`, and exposes it as flake attribute `modules.flake.${name}`. - - This also imports the optional [`modules`](https://flake.parts/options/flake-parts-modules.html) module to support that. - */ - importAndPublish = name: module: { lib, ... }: { - _class = "flake"; - imports = [ - module - ./extras/modules.nix - ]; - flake.modules.flake.${name} = module; - }; - }; - - # A best effort, lenient estimate. Please use a recent nixpkgs lib if you - # override it at all. - minVersion = "23.05pre-git"; - -in - -if builtins.compareVersions lib.version minVersion < 0 -then - abort '' - The nixpkgs-lib dependency of flake-parts was overridden but is too old. - The minimum supported version of nixpkgs-lib is ${minVersion}, - but the actual version is ${lib.version}${revInfo}. - '' -else - - flake-parts-lib diff --git a/nix/snow/flake/module.nix b/nix/snow/flake/module.nix index 79b8804..1aacd0b 100644 --- a/nix/snow/flake/module.nix +++ b/nix/snow/flake/module.nix @@ -18,6 +18,7 @@ }: { imports = [ ./nodes + ./modules (snow.findImport /${root}/snow) ]; } diff --git a/nix/snow/flake/modules/README.md b/nix/snow/flake/modules/README.md new file mode 100644 index 0000000..d19dbc1 --- /dev/null +++ b/nix/snow/flake/modules/README.md @@ -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). diff --git a/nix/snow/flake/modules/apps.nix b/nix/snow/flake/modules/apps.nix index 3030d32..75cc4be 100644 --- a/nix/snow/flake/modules/apps.nix +++ b/nix/snow/flake/modules/apps.nix @@ -1,23 +1,31 @@ -{ lib, flake-parts-lib, ... }: -let - inherit (lib) +{ + lib, + snow, + ... +}: let + inherit + (lib) mkOption types ; - inherit (flake-parts-lib) - mkTransposedPerSystemModule + + inherit + (snow) + mkPerSystemFlakeOutput ; - programType = lib.types.coercedTo derivationType lib.getExe lib.types.str; + derivationType = + lib.types.package + // { + check = lib.isDerivation; + }; - 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" ]; + type = lib.types.enum ["app"]; default = "app"; description = '' A type tag for `apps` consumers. @@ -31,7 +39,7 @@ let }; meta = mkOption { type = types.lazyAttrsOf lib.types.raw; - default = { }; + default = {}; # TODO refer to Nix manual 2.25 description = '' Metadata information about the app. @@ -43,19 +51,19 @@ let }; }; in -mkTransposedPerSystemModule { - name = "apps"; - option = mkOption { - type = types.lazyAttrsOf appType; - default = { }; - description = '' - Programs runnable with nix run ``. - ''; - example = lib.literalExpression '' - { - default.program = "''${config.packages.hello}/bin/hello"; - } - ''; - }; - file = ./apps.nix; -} + mkPerSystemFlakeOutput { + name = "apps"; + option = mkOption { + type = types.lazyAttrsOf appType; + default = {}; + description = '' + Programs runnable with nix run ``. + ''; + example = lib.literalExpression '' + { + default.program = "''${config.packages.hello}/bin/hello"; + } + ''; + }; + file = ./apps.nix; + } diff --git a/nix/snow/flake/modules/checks.nix b/nix/snow/flake/modules/checks.nix index 9e7ceae..a8a7280 100644 --- a/nix/snow/flake/modules/checks.nix +++ b/nix/snow/flake/modules/checks.nix @@ -1,21 +1,26 @@ -{ lib, flake-parts-lib, ... }: -let - inherit (lib) +{ + lib, + snow, + ... +}: let + inherit + (lib) mkOption types ; - inherit (flake-parts-lib) - mkTransposedPerSystemModule + inherit + (snow) + mkPerSystemFlakeOutput ; in -mkTransposedPerSystemModule { - 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; -} + 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; + } diff --git a/nix/snow/flake/modules/debug.nix b/nix/snow/flake/modules/debug.nix deleted file mode 100644 index 995f13b..0000000 --- a/nix/snow/flake/modules/debug.nix +++ /dev/null @@ -1,78 +0,0 @@ -{ config, flake-parts-lib, lib, options, getSystem, extendModules, ... }: -let - inherit (lib) - mapAttrs - mkIf - mkOption - optionalAttrs - types - ; - inherit (flake-parts-lib) - mkPerSystemOption - ; - - mkDebugConfig = { config, options, extendModules }: config // { - inherit config; - inherit (config) _module; - inherit options; - inherit extendModules; - }; -in -{ - options = { - debug = mkOption { - type = types.bool; - default = false; - description = '' - Whether to add the attributes `debug`, `allSystems` and `currentSystem` - to the flake output. When `true`, this allows inspection of options via - `nix repl`. - - ``` - $ nix repl - nix-repl> :lf . - nix-repl> currentSystem._module.args.pkgs.hello - «derivation /nix/store/7vf0d0j7majv1ch1xymdylyql80cn5fp-hello-2.12.1.drv» - ``` - - Each of `debug`, `allSystems.` and `currentSystem` is an - attribute set consisting of the `config` attributes, plus the extra - attributes `_module`, `config`, `options`, `extendModules`. So note that - these are not part of the `config` parameter, but are merged in for - debugging convenience. - - - `debug`: The top-level options - - `allSystems`: The `perSystem` submodule applied to the configured `systems`. - - `currentSystem`: Shortcut into `allSystems`. Only available in impure mode. - Works for arbitrary system values. - - See [Expore and debug option values](../debug.html) for more examples. - ''; - }; - perSystem = mkPerSystemOption - ({ options, config, extendModules, ... }: { - _file = ./formatter.nix; - options = { - debug = mkOption { - description = '' - Values to return in e.g. `allSystems.` when - [`debug = true`](#opt-debug). - ''; - type = types.lazyAttrsOf types.raw; - }; - }; - config = { - debug = mkDebugConfig { inherit config options extendModules; }; - }; - }); - }; - - config = mkIf config.debug { - flake = { - debug = mkDebugConfig { inherit config options extendModules; }; - allSystems = mapAttrs (_s: c: c.debug) config.allSystems; - } // optionalAttrs (builtins?currentSystem) { - currentSystem = (getSystem builtins.currentSystem).debug; - }; - }; -} diff --git a/nix/snow/flake/modules/default.nix b/nix/snow/flake/modules/default.nix new file mode 100644 index 0000000..e6914a0 --- /dev/null +++ b/nix/snow/flake/modules/default.nix @@ -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 + ]; +} diff --git a/nix/snow/flake/modules/devShells.nix b/nix/snow/flake/modules/devShells.nix index c0cc6c5..7116e6b 100644 --- a/nix/snow/flake/modules/devShells.nix +++ b/nix/snow/flake/modules/devShells.nix @@ -1,30 +1,35 @@ -{ lib, flake-parts-lib, ... }: -let - inherit (lib) +{ + lib, + snow, + ... +}: let + inherit + (lib) mkOption types literalExpression ; - inherit (flake-parts-lib) - mkTransposedPerSystemModule + inherit + (snow) + mkPerSystemFlakeOutput ; in -mkTransposedPerSystemModule { - name = "devShells"; - option = mkOption { - type = types.lazyAttrsOf types.package; - default = { }; - description = '' - An attribute set of packages to be used as shells. - [`nix develop .#`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-develop.html) will run `devShells.`. - ''; - example = literalExpression '' - { - default = pkgs.mkShell { - nativeBuildInputs = with pkgs; [ wget bat cargo ]; - }; - } - ''; - }; - file = ./devShells.nix; -} + mkPerSystemFlakeOutput { + name = "devShells"; + option = mkOption { + type = types.lazyAttrsOf types.package; + default = {}; + description = '' + An attribute set of packages to be used as shells. + [`nix develop .#`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-develop.html) will run `devShells.`. + ''; + example = literalExpression '' + { + default = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ wget bat cargo ]; + }; + } + ''; + }; + file = ./devShells.nix; + } diff --git a/nix/snow/flake/modules/formatter.nix b/nix/snow/flake/modules/formatter.nix index e2959ed..44e07c2 100644 --- a/nix/snow/flake/modules/formatter.nix +++ b/nix/snow/flake/modules/formatter.nix @@ -1,52 +1,26 @@ -{ config, lib, flake-parts-lib, ... }: -let - inherit (lib) - filterAttrs - mapAttrs +{ + lib, + snow, + ... +}: let + inherit + (lib) mkOption - optionalAttrs types ; - inherit (flake-parts-lib) - mkPerSystemOption + inherit + (snow) + mkPerSystemFlakeOutput ; in -{ - options = { - flake.formatter = mkOption { - type = types.lazyAttrsOf types.package; - default = { }; + mkPerSystemFlakeOutput { + name = "formatter"; + option = mkOption { + type = types.nullOr types.package; + default = null; description = '' - An attribute set of per system a package used by [`nix fmt`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-fmt.html). + A package used by [`nix fmt`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-fmt.html). ''; }; - - perSystem = mkPerSystemOption { - _file = ./formatter.nix; - options = { - formatter = 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). - ''; - }; - }; - }; - }; - config = { - flake.formatter = - mapAttrs - (k: v: v.formatter) - (filterAttrs - (k: v: v.formatter != null) - config.allSystems - ); - - perInput = system: flake: - optionalAttrs (flake?formatter.${system}) { - formatter = flake.formatter.${system}; - }; - - }; -} + file = ./apps.nix; + } diff --git a/nix/snow/flake/modules/legacyPackages.nix b/nix/snow/flake/modules/legacyPackages.nix index fb17e14..f167c93 100644 --- a/nix/snow/flake/modules/legacyPackages.nix +++ b/nix/snow/flake/modules/legacyPackages.nix @@ -1,21 +1,26 @@ -{ lib, flake-parts-lib, ... }: -let - inherit (lib) +{ + lib, + snow, + ... +}: let + inherit + (lib) mkOption types ; - inherit (flake-parts-lib) - mkTransposedPerSystemModule + inherit + (snow) + mkPerSystemFlakeOutput ; in -mkTransposedPerSystemModule { - name = "legacyPackages"; - option = mkOption { - type = types.lazyAttrsOf types.raw; - default = { }; - description = '' - An attribute set of unmergeable values. This is also used by [`nix build .#`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-build.html). - ''; - }; - file = ./legacyPackages.nix; -} + mkPerSystemFlakeOutput { + name = "legacyPackages"; + option = mkOption { + type = types.lazyAttrsOf types.raw; + default = {}; + description = '' + Used for nixpkgs packages, also accessible via `nix build .#` [`nix build .#`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-build.html). + ''; + }; + file = ./legacyPackages.nix; + } diff --git a/nix/snow/flake/modules/moduleWithSystem.nix b/nix/snow/flake/modules/moduleWithSystem.nix deleted file mode 100644 index e5c7008..0000000 --- a/nix/snow/flake/modules/moduleWithSystem.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ withSystem, ... }: -{ - config = { - _module.args = { - moduleWithSystem = - module: - - { config, ... }: - let - system = - config._module.args.system or - config._module.args.pkgs.stdenv.hostPlatform.system or - (throw "moduleWithSystem: Could not determine the configuration's system parameter for this module system application."); - - allArgs = withSystem system (args: args); - - lazyArgsPerParameter = f: builtins.mapAttrs - (k: v: allArgs.${k} or (throw "moduleWithSystem: module argument `${k}` does not exist.")) - (builtins.functionArgs f); - - # Use reflection to make the call lazy in the argument. - # Restricts args to the ones declared. - callLazily = f: a: f (lazyArgsPerParameter f); - in - { - imports = [ - (callLazily module allArgs) - ]; - }; - }; - }; -} diff --git a/nix/snow/flake/modules/nixosConfigurations.nix b/nix/snow/flake/modules/nixosConfigurations.nix index 597132d..7db8077 100644 --- a/nix/snow/flake/modules/nixosConfigurations.nix +++ b/nix/snow/flake/modules/nixosConfigurations.nix @@ -1,16 +1,15 @@ -{ lib, ... }: -let - inherit (lib) +{lib, ...}: let + inherit + (lib) mkOption types literalExpression ; -in -{ +in { options = { - flake.nixosConfigurations = mkOption { + outputs.nixosConfigurations = mkOption { type = types.lazyAttrsOf types.raw; - default = { }; + default = {}; description = '' Instantiated NixOS configurations. Used by `nixos-rebuild`. diff --git a/nix/snow/flake/modules/nixosModules.nix b/nix/snow/flake/modules/nixosModules.nix index 86ee9cc..6819570 100644 --- a/nix/snow/flake/modules/nixosModules.nix +++ b/nix/snow/flake/modules/nixosModules.nix @@ -1,20 +1,23 @@ -{ self, lib, moduleLocation, ... }: -let - inherit (lib) +{ + lib, + moduleLocation, + ... +}: let + inherit + (lib) mapAttrs mkOption types ; -in -{ +in { options = { - flake.nixosModules = mkOption { + outputs.nixosModules = mkOption { type = types.lazyAttrsOf types.deferredModule; - default = { }; + default = {}; apply = mapAttrs (k: v: { _class = "nixos"; _file = "${toString moduleLocation}#nixosModules.${k}"; - imports = [ v ]; + imports = [v]; }); description = '' NixOS modules. diff --git a/nix/snow/flake/modules/nixpkgs.nix b/nix/snow/flake/modules/nixpkgs.nix deleted file mode 100644 index 44df915..0000000 --- a/nix/snow/flake/modules/nixpkgs.nix +++ /dev/null @@ -1,26 +0,0 @@ -# -# Nixpkgs module. The only exception to the rule. -# -# Provides a `pkgs` argument in `perSystem`. -# -# Arguably, this shouldn't be in flake-parts, but in nixpkgs. -# Nixpkgs could define its own module that does this, which would be -# a more consistent UX, but for now this will do. -# -# The existence of this module does not mean that other flakes' logic -# will be accepted into flake-parts, because it's against the -# spirit of Flakes. -# -{ - config = { - perSystem = { inputs', lib, ... }: { - config = { - _module.args.pkgs = lib.mkOptionDefault ( - builtins.seq - (inputs'.nixpkgs or (throw "flake-parts: The flake does not have a `nixpkgs` input. Please add it, or set `perSystem._module.args.pkgs` yourself.")) - inputs'.nixpkgs.legacyPackages - ); - }; - }; - }; -} diff --git a/nix/snow/flake/modules/flake.nix b/nix/snow/flake/modules/outputs.nix similarity index 94% rename from nix/snow/flake/modules/flake.nix rename to nix/snow/flake/modules/outputs.nix index 871f04d..3539f5c 100644 --- a/nix/snow/flake/modules/flake.nix +++ b/nix/snow/flake/modules/outputs.nix @@ -9,7 +9,7 @@ types ; - flake = mkOption { + outputs = mkOption { type = types.submoduleWith { modules = [ { @@ -39,8 +39,7 @@ }; in { options = { - inherit flake; - output = {inherit flake;}; + inherit outputs; }; config = {inherit (config) flake;}; diff --git a/nix/snow/flake/modules/overlays.nix b/nix/snow/flake/modules/overlays.nix index 172336c..55423c2 100644 --- a/nix/snow/flake/modules/overlays.nix +++ b/nix/snow/flake/modules/overlays.nix @@ -1,19 +1,18 @@ -{ lib, ... }: -let - inherit (lib) +{lib, ...}: let + inherit + (lib) mkOption types ; -in -{ +in { options = { - flake.overlays = mkOption { + 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 = { }; + default = {}; example = lib.literalExpression '' { default = final: prev: {}; diff --git a/nix/snow/flake/modules/packages.nix b/nix/snow/flake/modules/packages.nix index 20f0071..517c758 100644 --- a/nix/snow/flake/modules/packages.nix +++ b/nix/snow/flake/modules/packages.nix @@ -1,23 +1,29 @@ -{ lib, flake-parts-lib, ... }: -let - inherit (lib) +{ + lib, + snow, + ... +}: let + inherit + (lib) mkOption types ; - inherit (flake-parts-lib) - mkTransposedPerSystemModule + + inherit + (snow) + mkPerSystemFlakeOutput ; in -mkTransposedPerSystemModule { - 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). + 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 .#` will build `packages.`. - ''; - }; - file = ./packages.nix; -} + `nix build .#` will build `packages.`. + ''; + }; + file = ./packages.nix; + } diff --git a/nix/snow/flake/modules/perSystem.nix b/nix/snow/flake/modules/perSystem.nix deleted file mode 100644 index d4890ef..0000000 --- a/nix/snow/flake/modules/perSystem.nix +++ /dev/null @@ -1,159 +0,0 @@ -{ config, lib, flake-parts-lib, self, ... }: -let - inherit (lib) - genAttrs - mapAttrs - mkOption - types - ; - inherit (lib.strings) - escapeNixIdentifier - ; - inherit (flake-parts-lib) - mkPerSystemType - ; - - rootConfig = config; - - # Stubs for self and inputs. While it'd be possible to define aliases - # inside perSystem, that is not a general solution, and it would make - # top.config harder to discover, stretching the learning curve rather - # than flattening it. - - throwAliasError' = param: - throw '' - `${param}` (without `'`) is not a `perSystem` module argument, but a - module argument of the top level config. - - The following is an example usage of `${param}`. Note that its binding - is in the `top` parameter list, which is declared by the top level module - rather than the `perSystem` module. - - top@{ config, lib, ${param}, ... }: { - perSystem = { config, ${param}', ... }: { - # in scope here: - # - ${param} - # - ${param}' - # - config (of perSystem) - # - top.config (note the `top@` pattern) - }; - } - ''; - - throwAliasError = param: - throw '' - `${param}` is not a `perSystem` module argument, but a module argument of - the top level config. - - The following is an example usage of `${param}`. Note that its binding - is in the `top` parameter list, which is declared by the top level module - rather than the `perSystem` module. - - top@{ config, lib, ${param}, ... }: { - perSystem = { config, ... }: { - # in scope here: - # - ${param} - # - config (of perSystem) - # - top.config (note the `top@` pattern) - }; - } - ''; - - /** - We primarily use `systems` to help memoize the per system context, but that - doesn't extend to arbitrary `system`s. - For that, we use the slightly less efficient, but perfectly acceptable - `memoizeStr` function. - */ - otherMemoizedSystems = flake-parts-lib.memoizeStr config.perSystem; - -in -{ - options = { - systems = mkOption { - description = '' - All the system types to enumerate in the flake output subattributes. - - In other words, all valid values for `system` in e.g. `packages..foo`. - ''; - type = types.listOf types.str; - }; - - perInput = mkOption { - description = '' - A function that pre-processes flake inputs. - - It is called for users of `perSystem` such that `inputs'.''${name} = config.perInput system inputs.''${name}`. - - This is used for [`inputs'`](../module-arguments.html#inputs) and [`self'`](../module-arguments.html#self). - - The attributes returned by the `perInput` function definitions are merged into a single namespace (per input), - so each module should return an attribute set with usually only one or two predictable attribute names. Otherwise, - the `inputs'` namespace gets polluted. - ''; - type = types.functionTo (types.functionTo (types.lazyAttrsOf types.unspecified)); - }; - - perSystem = mkOption { - description = '' - A function from system to flake-like attributes omitting the `` attribute. - - Modules defined here have access to the suboptions and [some convenient module arguments](../module-arguments.html). - ''; - type = mkPerSystemType ({ config, system, ... }: { - _file = ./perSystem.nix; - config = { - _module.args.inputs' = - mapAttrs - (inputName: input: - builtins.addErrorContext "while retrieving system-dependent attributes for input ${escapeNixIdentifier inputName}" ( - if input._type or null == "flake" - then rootConfig.perInput system input - else - throw "Trying to retrieve system-dependent attributes for input ${escapeNixIdentifier inputName}, but this input is not a flake. Perhaps flake = false was added to the input declarations by mistake, or you meant to use a different input, or you meant to use plain old inputs, not inputs'." - ) - ) - self.inputs; - _module.args.self' = - builtins.addErrorContext "while retrieving system-dependent attributes for a flake's own outputs" ( - rootConfig.perInput system self - ); - - # Custom error messages - _module.args.self = throwAliasError' "self"; - _module.args.inputs = throwAliasError' "inputs"; - _module.args.getSystem = throwAliasError "getSystem"; - _module.args.withSystem = throwAliasError "withSystem"; - _module.args.moduleWithSystem = throwAliasError "moduleWithSystem"; - }; - }); - apply = modules: system: - (lib.evalModules { - inherit modules; - prefix = [ "perSystem" system ]; - specialArgs = { - inherit system; - }; - class = "perSystem"; - }).config; - }; - - allSystems = mkOption { - type = types.lazyAttrsOf types.unspecified; - description = "The system-specific config for each of systems."; - internal = true; - }; - }; - - config = { - allSystems = genAttrs config.systems config.perSystem; - _module.args.getSystem = system: config.allSystems.${system} or (otherMemoizedSystems system); - - # The warning is there for a reason. Only use this in situations where the - # performance cost has already been incurred, such as in `flakeModules.easyOverlay`, - # where we run in the context of an overlay, and the performance cost of the - # extra `pkgs` makes the cost of running `perSystem` probably negligible. - _module.args.getSystemIgnoreWarning = system: config.allSystems.${system} or (config.perSystem system); - }; - -} diff --git a/nix/snow/flake/modules/transposition.nix b/nix/snow/flake/modules/transposition.nix deleted file mode 100644 index d532e76..0000000 --- a/nix/snow/flake/modules/transposition.nix +++ /dev/null @@ -1,132 +0,0 @@ -{ config, lib, flake-parts-lib, ... }: - -let - inherit (lib) - filterAttrs - mapAttrs - mkOption - types - ; - inherit (lib.strings) - escapeNixIdentifier - ; - - transpositionModule = { - options = { - adHoc = mkOption { - type = types.bool; - default = false; - description = '' - Whether to provide a stub option declaration for {option}`perSystem.`. - - The stub option declaration does not support merging and lacks - documentation, so you are recommended to declare the {option}`perSystem.` - option yourself and avoid {option}`adHoc`. - ''; - }; - }; - }; - - perInputAttributeError = { flake, attrName, system, attrConfig }: - # This uses flake.outPath for lack of a better identifier. - # Consider adding a perInput variation that has a normally-redundant argument for the input name. - # Tested manually with - # perSystem = { inputs', ... }: { - # packages.extra = inputs'.nixpkgs.extra; - # packages.default = inputs'.nixpkgs.packages.default; - # packages.veryWrong = (top.config.perInput "x86_64-linux" inputs'.nixpkgs.legacyPackages.hello).packages.default; - # }; - # transposition.extra = {}; - let - attrPath = "${escapeNixIdentifier attrName}.${escapeNixIdentifier system}"; - flakeIdentifier = - if flake._type or null != "flake" - then - throw "An attempt was made to access attribute ${attrPath} on a value that's supposed to be a flake, but may not be a proper flake." - else - builtins.addErrorContext "while trying to find out how to describe what is supposedly a flake, whose attribute ${attrPath} was accessed but does not exist" ( - toString flake.outPath - ); - # This ought to be generalized by extending attrConfig, but this is the only known and common mistake for now. - alternateAttrNameHint = - if attrName == "packages" && flake?legacyPackages - then # Unfortunately we can't just switch them out, because that will put packages *sets* where single packages are expected in user code, resulting in potentially much worse and more confusing errors down the line. - "\nIt does define legacyPackages; try that instead?" - else ""; - in - if flake?${attrName} - then - throw '' - Attempt to access ${attrPath} of flake ${flakeIdentifier}, but it does not have it. - It does have attribute ${escapeNixIdentifier attrName}, so it appears that it does not support system type ${escapeNixIdentifier system}. - '' - else - throw '' - Attempt to access ${attrPath} of flake ${flakeIdentifier}, but it does not have attribute ${escapeNixIdentifier attrName}.${alternateAttrNameHint} - ''; - - -in -{ - options = { - transposition = lib.mkOption { - description = '' - A helper that defines transposed attributes in the flake outputs. - - When you define `transposition.foo = { };`, definitions are added to the effect of (pseudo-code): - - ```nix - flake.foo.''${system} = (perSystem system).foo; - perInput = system: inputFlake: inputFlake.foo.''${system}; - ``` - - Transposition is the operation that swaps the indices of a data structure. - Here it refers specifically to the transposition between - - ```plain - perSystem: .''${system}.''${attribute} - outputs: .''${attribute}.''${system} - ``` - - It also defines the reverse operation in [{option}`perInput`](#opt-perInput). - ''; - type = - types.lazyAttrsOf - (types.submoduleWith { modules = [ transpositionModule ]; }); - }; - }; - - config = { - flake = - lib.mapAttrs - (attrName: attrConfig: - mapAttrs - (system: v: v.${attrName} or ( - abort '' - Could not find option ${attrName} in the perSystem module. It is required to declare such an option whenever transposition. is defined (and in this instance is ${attrName}). - '')) - config.allSystems - ) - config.transposition; - - perInput = - system: flake: - mapAttrs - (attrName: attrConfig: - flake.${attrName}.${system} or ( - throw (perInputAttributeError { inherit system flake attrName attrConfig; }) - ) - ) - config.transposition; - - perSystem = { - options = - mapAttrs - (k: v: lib.mkOption { }) - (filterAttrs - (k: v: v.adHoc) - config.transposition - ); - }; - }; -} diff --git a/nix/snow/flake/modules/withSystem.nix b/nix/snow/flake/modules/withSystem.nix deleted file mode 100644 index 161eece..0000000 --- a/nix/snow/flake/modules/withSystem.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ lib, flake-parts-lib, getSystem, ... }: -let - inherit (lib) - mkOption - types - ; - inherit (flake-parts-lib) - mkPerSystemOption - ; -in -{ - options = { - perSystem = mkPerSystemOption ({ config, options, specialArgs, ... }: { - _file = ./perSystem.nix; - options = { - allModuleArgs = mkOption { - type = types.lazyAttrsOf (types.raw or types.unspecified); - internal = true; - readOnly = true; - description = "Internal option that exposes _module.args, for use by withSystem."; - }; - }; - config = { - allModuleArgs = config._module.args // specialArgs // { inherit config options; }; - }; - }); - }; - - config = { - _module.args = { - withSystem = - system: f: - f - (getSystem system).allModuleArgs; - }; - }; -} From f819933c8d9e1ff4fb85d52aca075b36bed6ad45 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Mar 2026 01:10:36 +1000 Subject: [PATCH 11/19] node inheritance + group parsing --- nix/snow/default.nix | 5 +- nix/snow/flake/modules/outputs.nix | 1 - nix/snow/flake/nodes/default.nix | 35 ++--- nix/snow/flake/nodes/groups.nix | 73 ++++++++++ .../flake/nodes/{submodule.nix => node.nix} | 103 +++++++++++++- .../flake/nodes/{shared.nix => nodes.nix} | 51 +++++-- nix/snow/flake/outputs/checks.nix | 15 +- nix/snow/flake/outputs/deploy.nix | 133 +++++++++++------- .../flake/outputs/nixosConfigurations.nix | 126 ++++++++++------- nix/snow/lib/default.nix | 27 ++++ nix/snow/{flake/lib.nix => lib/nixpkgs.nix} | 10 +- nix/snow/lib/nodes.nix | 96 ------------- 12 files changed, 422 insertions(+), 253 deletions(-) create mode 100644 nix/snow/flake/nodes/groups.nix rename nix/snow/flake/nodes/{submodule.nix => node.nix} (62%) rename nix/snow/flake/nodes/{shared.nix => nodes.nix} (81%) create mode 100644 nix/snow/lib/default.nix rename nix/snow/{flake/lib.nix => lib/nixpkgs.nix} (83%) delete mode 100644 nix/snow/lib/nodes.nix diff --git a/nix/snow/default.nix b/nix/snow/default.nix index 15c67da..c90685e 100644 --- a/nix/snow/default.nix +++ b/nix/snow/default.nix @@ -18,15 +18,14 @@ } @ args: let inherit (nt) findImport; in - mix.newMixture args (mixture: let - inherit (mixture) mapNodes; - in { + mix.newMixture args (mixture: { includes = { private = [ ./lib/nodes.nix ]; public = [ ./flake + ./lib.nix ]; }; diff --git a/nix/snow/flake/modules/outputs.nix b/nix/snow/flake/modules/outputs.nix index 3539f5c..551186a 100644 --- a/nix/snow/flake/modules/outputs.nix +++ b/nix/snow/flake/modules/outputs.nix @@ -21,7 +21,6 @@ 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 - Many modules are listed at https://flake.parts - 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 diff --git a/nix/snow/flake/nodes/default.nix b/nix/snow/flake/nodes/default.nix index d3bc9b7..d7b6a82 100644 --- a/nix/snow/flake/nodes/default.nix +++ b/nix/snow/flake/nodes/default.nix @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. { + _snow, 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 = _snow.inputs.nixpkgs; + }; + }; } diff --git a/nix/snow/flake/nodes/groups.nix b/nix/snow/flake/nodes/groups.nix new file mode 100644 index 0000000..b22cac0 --- /dev/null +++ b/nix/snow/flake/nodes/groups.nix @@ -0,0 +1,73 @@ +# # 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 + inherit + (builtins) + concatLists + elem + filter + isAttrs + mapAttrs + pathExists + typeOf + ; + + rootGroupName = "all"; +in { + parseGroupsDecl = groups: 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`. + 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; +} diff --git a/nix/snow/flake/nodes/submodule.nix b/nix/snow/flake/nodes/node.nix similarity index 62% rename from nix/snow/flake/nodes/submodule.nix rename to nix/snow/flake/nodes/node.nix index 6b4ae05..a368d24 100644 --- a/nix/snow/flake/nodes/submodule.nix +++ b/nix/snow/flake/nodes/node.nix @@ -14,16 +14,18 @@ { lib, systems, + config, + nodesConfig, ... }: { - imports = [./shared.nix]; - options = let inherit (lib) mkOption types ; + + flakeRef = types.either types.str types.path; in { enabled = lib.mkOption { type = types.bool; @@ -43,6 +45,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..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 + . + ''; + }; + + 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..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 +112,9 @@ description = '' A function from the `groups` hierarchy to a list of groups this node inherits from. ''; + + apply = groupsFn: + groupsFn nodesConfig.groups; }; deploy = { @@ -91,7 +155,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 +228,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 +247,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 +265,33 @@ }; }; }; + + config = let + throwGotNull = name: + throw '' + [snow] `nodes..${name}` must be set for all nodes! (got: ) + ''; + 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; + }; } diff --git a/nix/snow/flake/nodes/shared.nix b/nix/snow/flake/nodes/nodes.nix similarity index 81% rename from nix/snow/flake/nodes/shared.nix rename to nix/snow/flake/nodes/nodes.nix index c840d22..58a9e1a 100644 --- a/nix/snow/flake/nodes/shared.nix +++ b/nix/snow/flake/nodes/nodes.nix @@ -11,7 +11,13 @@ # 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 +{ + _snow, + lib, + config, + specialArgs, + ... +}: let inherit (lib) mkOption @@ -19,6 +25,8 @@ ; flakeRef = types.either types.str types.path; + + groupLibs = import ./groups.nix {inherit (_snow.inputs) nt;}; in { options = { base = lib.mkOption { @@ -49,6 +57,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..homeManager` (takes prescedence over `options.nodes.homeManager`) + ''; + }; + modules = mkOption { type = types.listOf types.raw; default = []; @@ -67,15 +87,28 @@ 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..homeManager` (takes prescedence over `options.nodes.homeManager`) + Hierarchical groups that nodes can be a member of. + ''; + + apply = groupLibs.parseGroupsDecl; + }; + + nodes = mkOption { + type = types.attrsOf (types.submoduleWith { + specialArgs = + specialArgs + // { + nodeConfig = config; + }; + modules = [./node.nix]; + }); + description = '' + Node (host systems) declarations. ''; }; }; diff --git a/nix/snow/flake/outputs/checks.nix b/nix/snow/flake/outputs/checks.nix index 21fd677..a25ba32 100644 --- a/nix/snow/flake/outputs/checks.nix +++ b/nix/snow/flake/outputs/checks.nix @@ -1,5 +1,10 @@ - checks = - inputs.deploy-rs.lib - |> mapAttrs (system: deployLib: - deployLib.deployChecks deploy); - +{ + config, + _snow, + ... +}: { + outputs.checks = + _snow.inputs.deploy-rs.lib + |> builtins.mapAttrs (system: deployLib: + deployLib.deployChecks config.outputs.deploy); +} diff --git a/nix/snow/flake/outputs/deploy.nix b/nix/snow/flake/outputs/deploy.nix index 08caa8f..c8d39a9 100644 --- a/nix/snow/flake/outputs/deploy.nix +++ b/nix/snow/flake/outputs/deploy.nix @@ -1,57 +1,90 @@ - deploy.nodes = mapNodes nodes ({ - name, - node, - ... - }: let - inherit - (node.deploy) - ssh - user - interactiveSudo - remoteBuild - rollback - autoRollback - magicRollback - activationTimeout - confirmTimeout - ; +{ + _snow, + config, + ... +}: let + inherit + (builtins) + mapAttrs + ; - nixosFor = system: inputs.deploy-rs.lib.${system}.activate.nixos; - in { - hostname = - if ssh.host != null - then ssh.host - else ""; + mapNodes = nodes: f: + nodes.nodes + |> mapAttrs (name: node: let + # use per-node base or default to nodes' base + base = + if node.base != null + then node.base + else if nodes.base != null + then nodes.base + else + abort '' + 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 + f rec { + inherit name node base; + inherit (base) lib; - profilesOrder = ["default"]; # profiles priority - profiles.default = { - path = nixosFor node.system nixosConfigurations.${name}; + groups = node.groups (parseGroupsDecl nodes.groups); + groupModules = root: getGroupModules root groups; + }); +in { + outputs.deploy.nodes = mapNodes config.nodes ({ + name, + node, + ... + }: let + inherit + (node.deploy) + ssh + user + interactiveSudo + remoteBuild + rollback + autoRollback + magicRollback + activationTimeout + confirmTimeout + ; - user = user; - sudo = "sudo -u"; - interactiveSudo = interactiveSudo; + nixosFor = system: _snow.inputs.deploy-rs.lib.${system}.activate.nixos; + in { + hostname = + if ssh.host != null + then ssh.host + else ""; - fastConnection = false; + profilesOrder = ["default"]; # profiles priority + profiles.default = { + path = nixosFor node.system config.outputs.nixosConfigurations.${name}; - autoRollback = autoRollback -> rollback; - magicRollback = magicRollback -> rollback; - activationTimeout = activationTimeout; - confirmTimeout = confirmTimeout; + user = user; + sudo = "sudo -u"; + interactiveSudo = interactiveSudo; - 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"] - ); - }; - }); + 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"] + ); + }; + }); +} diff --git a/nix/snow/flake/outputs/nixosConfigurations.nix b/nix/snow/flake/outputs/nixosConfigurations.nix index 799758d..2ca88b6 100644 --- a/nix/snow/flake/outputs/nixosConfigurations.nix +++ b/nix/snow/flake/outputs/nixosConfigurations.nix @@ -8,60 +8,78 @@ # options = { ... }; # type = { ... }; # } - 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; +{ + snow, + config, + systems, + root, + ... +}: let + inherit + (builtins) + all + attrNames + warn + ; - userArgs = nodes.args // node.args; - ceruleanArgs = { - inherit systems root base nodes node; - inherit (node) system; - inherit (this) snow; - hostname = name; + inherit + (config) + nodes + ; +in { + outputs.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; - _cerulean = { - inherit inputs userArgs ceruleanArgs homeManager; - specialArgs = userArgs // ceruleanArgs; - }; + userArgs = nodes.args // node.args; + snowArgs = { + inherit systems snow root base nodes node; + inherit (node) system; + hostname = name; + + _snow = { + inherit inputs userArgs snowArgs homeManager; + specialArgs = userArgs // snowArgs; }; - specialArgs = assert (userArgs - |> attrNames - |> all (argName: - ! ceruleanArgs ? argName - || abort '' - `specialArgs` are like super important to Cerulean my love... attrNames + |> all (argName: + ! snowArgs ? argName + || abort '' + `specialArgs` are like super important to Snow my love... 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 - |> mapAttrs (name: node: let - # use per-node base or default to nodes' base - base = - if node.base != null - then node.base - else if nodes.base != null - then nodes.base - else - abort '' - Cerulean 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 - f rec { - inherit name node base; - inherit (base) lib; - - groups = node.groups (parseGroupsDecl nodes.groups); - groupModules = root: getGroupModules root groups; - }); -} From 16cfbe4da15c6d965c07460f1b341805a20d8e41 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Mar 2026 01:13:21 +1000 Subject: [PATCH 12/19] fix cerulean->nix bad import --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 80faf5c..83bb612 100644 --- a/flake.nix +++ b/flake.nix @@ -44,7 +44,7 @@ nt, ... } @ inputs: - import ./cerulean + import ./nix { inherit inputs self nt; inherit (nt) mix; From f4dca25c28135abd9284cfce5ecfdeda8f0018ae Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Mar 2026 01:13:28 +1000 Subject: [PATCH 13/19] progress flake.lock --- flake.lock | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/flake.lock b/flake.lock index fc8e402..a8c1976 100644 --- a/flake.lock +++ b/flake.lock @@ -185,9 +185,30 @@ "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": { From 855430ef16eb0340facb632075ff898831d3ae8d Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Mar 2026 01:13:50 +1000 Subject: [PATCH 14/19] fix snow/default.nix not updated (use snow/lib) --- nix/snow/default.nix | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/nix/snow/default.nix b/nix/snow/default.nix index c90685e..5f95f46 100644 --- a/nix/snow/default.nix +++ b/nix/snow/default.nix @@ -11,23 +11,12 @@ # 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, - mix, - ... -} @ args: let - inherit (nt) findImport; -in - mix.newMixture args (mixture: { - includes = { - private = [ - ./lib/nodes.nix - ]; - public = [ - ./flake - ./lib.nix - ]; - }; - - inherit findImport; - }) +{mix, ...} @ args: +mix.newMixture args (mixture: { + includes = { + public = [ + ./flake + ./lib + ]; + }; +}) From f1eddd8e500352a753b6bdf82ad6f9c1b3359260 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Mar 2026 20:35:03 +1000 Subject: [PATCH 15/19] TODO secrets+home management --- TODO.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TODO.md b/TODO.md index 26ecbc1..6960151 100755 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,6 @@ ## Next +- [ ] secrets management pleaseeeeeeeeeeeeeeeeeeeeee + - [ ] figure out how Cerulean could aid CI/CD (ie hydra + nix-unit) you can https://github.com/NotAShelf/nix-bindings/tree/main/nix-bindings @@ -6,6 +8,9 @@ https://github.com/nixops4/nix-bindings-rust https://nix.dev/manual/nix/2.34/c-api.html +- [ ] move home management to `~/.snow/flake.nix`, then the `/etc/snow/flake.nix` + will only contain base definitions for the home + - [ ] write a key management system that supports activation time, run time, and build time https://docs.aws.amazon.com/kms/latest/developerguide/overview.html From 6c1a0a5d3395c5416d39e67a47bcdf7c1762613e Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Mar 2026 20:37:59 +1000 Subject: [PATCH 16/19] minimal working state --- flake.lock | 32 ++--- nix/default.nix | 38 +++--- nix/nixos/default.nix | 10 +- nix/nixos/home.nix | 6 +- nix/snow/default.nix | 21 +-- nix/snow/flake/default.nix | 14 +- nix/snow/flake/module.nix | 24 ---- nix/snow/flake/modules/apps.nix | 2 +- nix/snow/flake/modules/checks.nix | 2 +- nix/snow/flake/modules/devShells.nix | 2 +- nix/snow/flake/modules/formatter.nix | 2 +- nix/snow/flake/modules/legacyPackages.nix | 2 +- nix/snow/flake/modules/outputs.nix | 61 ++++----- nix/snow/flake/modules/packages.nix | 2 +- nix/snow/flake/nodes/default.nix | 4 +- nix/snow/flake/nodes/groups.nix | 73 ----------- nix/snow/flake/nodes/node.nix | 62 +++++---- nix/snow/flake/nodes/nodes.nix | 14 +- nix/snow/flake/outputs/checks.nix | 4 +- nix/snow/flake/outputs/default.nix | 7 + nix/snow/flake/outputs/deploy.nix | 37 +----- .../flake/outputs/nixosConfigurations.nix | 123 +++++++++--------- nix/snow/lib/default.nix | 18 ++- nix/snow/lib/nixpkgs.nix | 7 +- nix/snow/lib/nodes.nix | 87 +++++++++++++ nix/snow/lib/util.nix | 3 + 26 files changed, 331 insertions(+), 326 deletions(-) delete mode 100644 nix/snow/flake/module.nix delete mode 100644 nix/snow/flake/nodes/groups.nix create mode 100644 nix/snow/flake/outputs/default.nix create mode 100644 nix/snow/lib/nodes.nix create mode 100644 nix/snow/lib/util.nix diff --git a/flake.lock b/flake.lock index a8c1976..6f3fefe 100644 --- a/flake.lock +++ b/flake.lock @@ -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": { @@ -212,11 +212,11 @@ "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" }, diff --git a/nix/default.nix b/nix/default.nix index 6c488a1..6364a63 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -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; + }; + }) diff --git a/nix/nixos/default.nix b/nix/nixos/default.nix index a716c2f..a91df1a 100644 --- a/nix/nixos/default.nix +++ b/nix/nixos/default.nix @@ -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 ]); } diff --git a/nix/nixos/home.nix b/nix/nixos/home.nix index 82117d8..cf24f74 100644 --- a/nix/nixos/home.nix +++ b/nix/nixos/home.nix @@ -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 diff --git a/nix/snow/default.nix b/nix/snow/default.nix index 5f95f46..89e1772 100644 --- a/nix/snow/default.nix +++ b/nix/snow/default.nix @@ -11,12 +11,17 @@ # 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. -{mix, ...} @ args: -mix.newMixture args (mixture: { - includes = { - public = [ - ./flake - ./lib - ]; - }; +{ + nt, + mix, + ... +} @ args: +mix.newMixture (removeAttrs args ["this"]) (mixture: { + submods.public = [ + ./lib + ]; + + includes.public = [ + ./flake + ]; }) diff --git a/nix/snow/flake/default.nix b/nix/snow/flake/default.nix index 9c5d1f5..828f59b 100644 --- a/nix/snow/flake/default.nix +++ b/nix/snow/flake/default.nix @@ -1,4 +1,5 @@ { + self, this, inputs, systems, @@ -16,14 +17,20 @@ 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; + # inherit (this) snow; + snow = this; inherit systems root; inputs = flakeInputs; + + _snowFlake = { + inherit self inputs; + }; }; warnIfReserved = let @@ -50,7 +57,10 @@ in { flakeInputs // reservedSpecialArgs; modules = [ - ./module.nix + ./nodes + ./modules + ./outputs + (this.lib.findImport /${root}/snow) ]; }; in diff --git a/nix/snow/flake/module.nix b/nix/snow/flake/module.nix deleted file mode 100644 index 1aacd0b..0000000 --- a/nix/snow/flake/module.nix +++ /dev/null @@ -1,24 +0,0 @@ -# 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. -{ - root, - snow, - ... -}: { - imports = [ - ./nodes - ./modules - (snow.findImport /${root}/snow) - ]; -} diff --git a/nix/snow/flake/modules/apps.nix b/nix/snow/flake/modules/apps.nix index 75cc4be..cbe12f0 100644 --- a/nix/snow/flake/modules/apps.nix +++ b/nix/snow/flake/modules/apps.nix @@ -10,7 +10,7 @@ ; inherit - (snow) + (snow.lib) mkPerSystemFlakeOutput ; diff --git a/nix/snow/flake/modules/checks.nix b/nix/snow/flake/modules/checks.nix index a8a7280..d10d6d5 100644 --- a/nix/snow/flake/modules/checks.nix +++ b/nix/snow/flake/modules/checks.nix @@ -9,7 +9,7 @@ types ; inherit - (snow) + (snow.lib) mkPerSystemFlakeOutput ; in diff --git a/nix/snow/flake/modules/devShells.nix b/nix/snow/flake/modules/devShells.nix index 7116e6b..04ace01 100644 --- a/nix/snow/flake/modules/devShells.nix +++ b/nix/snow/flake/modules/devShells.nix @@ -10,7 +10,7 @@ literalExpression ; inherit - (snow) + (snow.lib) mkPerSystemFlakeOutput ; in diff --git a/nix/snow/flake/modules/formatter.nix b/nix/snow/flake/modules/formatter.nix index 44e07c2..5cce36b 100644 --- a/nix/snow/flake/modules/formatter.nix +++ b/nix/snow/flake/modules/formatter.nix @@ -9,7 +9,7 @@ types ; inherit - (snow) + (snow.lib) mkPerSystemFlakeOutput ; in diff --git a/nix/snow/flake/modules/legacyPackages.nix b/nix/snow/flake/modules/legacyPackages.nix index f167c93..9adc91d 100644 --- a/nix/snow/flake/modules/legacyPackages.nix +++ b/nix/snow/flake/modules/legacyPackages.nix @@ -9,7 +9,7 @@ types ; inherit - (snow) + (snow.lib) mkPerSystemFlakeOutput ; in diff --git a/nix/snow/flake/modules/outputs.nix b/nix/snow/flake/modules/outputs.nix index 551186a..bf7d9f5 100644 --- a/nix/snow/flake/modules/outputs.nix +++ b/nix/snow/flake/modules/outputs.nix @@ -8,38 +8,39 @@ mkOption types ; - - 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. - ''; - }; in { options = { - inherit outputs; + 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 = {inherit (config) flake;}; + config = { + # ensure a minimal version is set + outputs = {}; + }; } diff --git a/nix/snow/flake/modules/packages.nix b/nix/snow/flake/modules/packages.nix index 517c758..ef970bc 100644 --- a/nix/snow/flake/modules/packages.nix +++ b/nix/snow/flake/modules/packages.nix @@ -10,7 +10,7 @@ ; inherit - (snow) + (snow.lib) mkPerSystemFlakeOutput ; in diff --git a/nix/snow/flake/nodes/default.nix b/nix/snow/flake/nodes/default.nix index d7b6a82..07ad153 100644 --- a/nix/snow/flake/nodes/default.nix +++ b/nix/snow/flake/nodes/default.nix @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. { - _snow, + _snowFlake, lib, specialArgs, ... @@ -39,7 +39,7 @@ config = { nodes = { - base = _snow.inputs.nixpkgs; + base = _snowFlake.inputs.nixpkgs; }; }; } diff --git a/nix/snow/flake/nodes/groups.nix b/nix/snow/flake/nodes/groups.nix deleted file mode 100644 index b22cac0..0000000 --- a/nix/snow/flake/nodes/groups.nix +++ /dev/null @@ -1,73 +0,0 @@ -# # 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 - inherit - (builtins) - concatLists - elem - filter - isAttrs - mapAttrs - pathExists - typeOf - ; - - rootGroupName = "all"; -in { - parseGroupsDecl = groups: 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`. - 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; -} diff --git a/nix/snow/flake/nodes/node.nix b/nix/snow/flake/nodes/node.nix index a368d24..11c2b98 100644 --- a/nix/snow/flake/nodes/node.nix +++ b/nix/snow/flake/nodes/node.nix @@ -14,8 +14,9 @@ { lib, systems, - config, nodesConfig, + groups, + groupLibs, ... }: { options = let @@ -25,6 +26,11 @@ types ; + inherit + (groupLibs) + resolveGroupsInheritance + ; + flakeRef = types.either types.str types.path; in { enabled = lib.mkOption { @@ -113,8 +119,8 @@ A function from the `groups` hierarchy to a list of groups this node inherits from. ''; - apply = groupsFn: - groupsFn nodesConfig.groups; + # apply = groupsFn: + # groupsFn nodesConfig.groups |> resolveGroupsInheritance; }; deploy = { @@ -266,32 +272,32 @@ }; }; - config = let - throwGotNull = name: - throw '' - [snow] `nodes..${name}` must be set for all nodes! (got: ) - ''; - givenSystem = - (config.system != null) - || throwGotNull "system"; + # config = let + # throwGotNull = name: + # throw '' + # [snow] `nodes..${name}` must be set for all nodes! (got: ) + # ''; + # givenSystem = + # (config.system != null) + # || throwGotNull "system"; - givenBase = - (config.base != null) - || throwGotNull "base"; + # givenBase = + # (config.base != null) + # || throwGotNull "base"; - givenHomeManager = - (config.homeManager != null) - || throwGotNull "homeManager"; + # 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; - }; + # 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; + # }; } diff --git a/nix/snow/flake/nodes/nodes.nix b/nix/snow/flake/nodes/nodes.nix index 58a9e1a..d5e5a59 100644 --- a/nix/snow/flake/nodes/nodes.nix +++ b/nix/snow/flake/nodes/nodes.nix @@ -12,7 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. { - _snow, + _snowFlake, + snow, + root, lib, config, specialArgs, @@ -26,7 +28,10 @@ flakeRef = types.either types.str types.path; - groupLibs = import ./groups.nix {inherit (_snow.inputs) nt;}; + groupLibs = import ./groups.nix { + inherit snow root; + inherit (_snowFlake.inputs) nt; + }; in { options = { base = lib.mkOption { @@ -94,8 +99,6 @@ in { description = '' Hierarchical groups that nodes can be a member of. ''; - - apply = groupLibs.parseGroupsDecl; }; nodes = mkOption { @@ -103,7 +106,8 @@ in { specialArgs = specialArgs // { - nodeConfig = config; + nodesConfig = config; + inherit groupLibs; }; modules = [./node.nix]; }); diff --git a/nix/snow/flake/outputs/checks.nix b/nix/snow/flake/outputs/checks.nix index a25ba32..de6a9c0 100644 --- a/nix/snow/flake/outputs/checks.nix +++ b/nix/snow/flake/outputs/checks.nix @@ -1,10 +1,10 @@ { config, - _snow, + _snowFlake, ... }: { outputs.checks = - _snow.inputs.deploy-rs.lib + _snowFlake.inputs.deploy-rs.lib |> builtins.mapAttrs (system: deployLib: deployLib.deployChecks config.outputs.deploy); } diff --git a/nix/snow/flake/outputs/default.nix b/nix/snow/flake/outputs/default.nix new file mode 100644 index 0000000..2c0a9ca --- /dev/null +++ b/nix/snow/flake/outputs/default.nix @@ -0,0 +1,7 @@ +{...}: { + imports = [ + ./checks.nix + ./deploy.nix + ./nixosConfigurations.nix + ]; +} diff --git a/nix/snow/flake/outputs/deploy.nix b/nix/snow/flake/outputs/deploy.nix index c8d39a9..59bbb49 100644 --- a/nix/snow/flake/outputs/deploy.nix +++ b/nix/snow/flake/outputs/deploy.nix @@ -1,37 +1,10 @@ { - _snow, + _snowFlake, + snow, config, ... -}: let - inherit - (builtins) - mapAttrs - ; - - mapNodes = nodes: f: - nodes.nodes - |> mapAttrs (name: node: let - # use per-node base or default to nodes' base - base = - if node.base != null - then node.base - else if nodes.base != null - then nodes.base - else - abort '' - 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 - f rec { - inherit name node base; - inherit (base) lib; - - groups = node.groups (parseGroupsDecl nodes.groups); - groupModules = root: getGroupModules root groups; - }); -in { - outputs.deploy.nodes = mapNodes config.nodes ({ +}: { + outputs.deploy.nodes = snow.lib.mapNodes config.nodes ({ name, node, ... @@ -49,7 +22,7 @@ in { confirmTimeout ; - nixosFor = system: _snow.inputs.deploy-rs.lib.${system}.activate.nixos; + nixosFor = system: _snowFlake.inputs.deploy-rs.lib.${system}.activate.nixos; in { hostname = if ssh.host != null diff --git a/nix/snow/flake/outputs/nixosConfigurations.nix b/nix/snow/flake/outputs/nixosConfigurations.nix index 2ca88b6..977fa22 100644 --- a/nix/snow/flake/outputs/nixosConfigurations.nix +++ b/nix/snow/flake/outputs/nixosConfigurations.nix @@ -1,14 +1,5 @@ -# { -# _module = { ... }; -# _type = "configuration"; -# class = null; -# config = { ... }; -# extendModules = «lambda extendModules @ /nix/store/9hfp0agnm43kz72l5lpfn9var5p0x2fa-source/lib/modules.nix:340:9»; -# graph = [ ... ]; -# options = { ... }; -# type = { ... }; -# } { + _snowFlake, snow, config, systems, @@ -27,59 +18,67 @@ nodes ; in { - outputs.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; + 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; - userArgs = nodes.args // node.args; - snowArgs = { - inherit systems snow root base nodes node; - inherit (node) system; - hostname = name; + 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; - _snow = { - inherit inputs userArgs snowArgs homeManager; - specialArgs = userArgs // snowArgs; + 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... attrNames + |> all (argName: + ! snowArgs ? argName + || abort '' + `specialArgs` are like super important to Snow my love... = 0) || abort '' The nixpkgs dependency of snow was overridden but is too old. The minimum supported version of nixpkgs-lib is ${minVersion}, diff --git a/nix/snow/lib/nodes.nix b/nix/snow/lib/nodes.nix new file mode 100644 index 0000000..6f799cf --- /dev/null +++ b/nix/snow/lib/nodes.nix @@ -0,0 +1,87 @@ +{ + this, + nt, + ... +}: let + inherit + (builtins) + concatLists + elem + filter + isAttrs + mapAttrs + pathExists + typeOf + ; + + inherit (nt.prim) uniq; + + rootGroupName = "all"; +in { + mapNodes = nodes: f: + nodes.nodes + |> mapAttrs (name: node: let + # use per-node base or default to nodes' base + base = + if node.base != null + then node.base + else if nodes.base != null + then nodes.base + else + abort '' + 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 + f rec { + inherit name node base; + inherit (base) lib; + + 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; +} diff --git a/nix/snow/lib/util.nix b/nix/snow/lib/util.nix new file mode 100644 index 0000000..6bfcd17 --- /dev/null +++ b/nix/snow/lib/util.nix @@ -0,0 +1,3 @@ +{nt, ...}: { + inherit (nt) findImport; +} From 482cbf67cd7c85555aef84eda576dc472e8c2c4e Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Mar 2026 22:45:46 +1000 Subject: [PATCH 17/19] switch modules/outputs names --- nix/snow/flake/modules/checks.nix | 32 ++---- nix/snow/flake/modules/default.nix | 10 +- .../flake/{outputs => modules}/deploy.nix | 0 .../flake/modules/nixosConfigurations.nix | 105 +++++++++++++----- nix/snow/flake/{modules => outputs}/README.md | 0 nix/snow/flake/{modules => outputs}/apps.nix | 0 nix/snow/flake/outputs/checks.nix | 32 ++++-- nix/snow/flake/outputs/default.nix | 10 +- .../flake/{modules => outputs}/devShells.nix | 0 .../flake/{modules => outputs}/formatter.nix | 0 .../{modules => outputs}/legacyPackages.nix | 0 .../flake/outputs/nixosConfigurations.nix | 105 +++++------------- .../{modules => outputs}/nixosModules.nix | 0 .../flake/{modules => outputs}/outputs.nix | 0 .../flake/{modules => outputs}/overlays.nix | 0 .../flake/{modules => outputs}/packages.nix | 0 16 files changed, 147 insertions(+), 147 deletions(-) rename nix/snow/flake/{outputs => modules}/deploy.nix (100%) rename nix/snow/flake/{modules => outputs}/README.md (100%) rename nix/snow/flake/{modules => outputs}/apps.nix (100%) rename nix/snow/flake/{modules => outputs}/devShells.nix (100%) rename nix/snow/flake/{modules => outputs}/formatter.nix (100%) rename nix/snow/flake/{modules => outputs}/legacyPackages.nix (100%) rename nix/snow/flake/{modules => outputs}/nixosModules.nix (100%) rename nix/snow/flake/{modules => outputs}/outputs.nix (100%) rename nix/snow/flake/{modules => outputs}/overlays.nix (100%) rename nix/snow/flake/{modules => outputs}/packages.nix (100%) diff --git a/nix/snow/flake/modules/checks.nix b/nix/snow/flake/modules/checks.nix index d10d6d5..de6a9c0 100644 --- a/nix/snow/flake/modules/checks.nix +++ b/nix/snow/flake/modules/checks.nix @@ -1,26 +1,10 @@ { - lib, - snow, + config, + _snowFlake, ... -}: 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; - } +}: { + outputs.checks = + _snowFlake.inputs.deploy-rs.lib + |> builtins.mapAttrs (system: deployLib: + deployLib.deployChecks config.outputs.deploy); +} diff --git a/nix/snow/flake/modules/default.nix b/nix/snow/flake/modules/default.nix index e6914a0..2c0a9ca 100644 --- a/nix/snow/flake/modules/default.nix +++ b/nix/snow/flake/modules/default.nix @@ -1,15 +1,7 @@ {...}: { imports = [ - ./outputs.nix - - ./apps.nix ./checks.nix - ./devShells.nix - ./formatter.nix - ./legacyPackages.nix + ./deploy.nix ./nixosConfigurations.nix - ./nixosModules.nix - ./overlays.nix - ./packages.nix ]; } diff --git a/nix/snow/flake/outputs/deploy.nix b/nix/snow/flake/modules/deploy.nix similarity index 100% rename from nix/snow/flake/outputs/deploy.nix rename to nix/snow/flake/modules/deploy.nix diff --git a/nix/snow/flake/modules/nixosConfigurations.nix b/nix/snow/flake/modules/nixosConfigurations.nix index 7db8077..977fa22 100644 --- a/nix/snow/flake/modules/nixosConfigurations.nix +++ b/nix/snow/flake/modules/nixosConfigurations.nix @@ -1,35 +1,84 @@ -{lib, ...}: let +{ + _snowFlake, + snow, + config, + systems, + root, + ... +}: let inherit - (lib) - mkOption - types - literalExpression + (builtins) + all + attrNames + warn + ; + + inherit + (config) + nodes ; in { - options = { - outputs.nixosConfigurations = mkOption { - type = types.lazyAttrsOf types.raw; - default = {}; - description = '' - Instantiated NixOS configurations. Used by `nixos-rebuild`. + 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; - `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 - ]; + 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... builtins.mapAttrs (system: deployLib: - deployLib.deployChecks config.outputs.deploy); -} +}: 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; + } diff --git a/nix/snow/flake/outputs/default.nix b/nix/snow/flake/outputs/default.nix index 2c0a9ca..e6914a0 100644 --- a/nix/snow/flake/outputs/default.nix +++ b/nix/snow/flake/outputs/default.nix @@ -1,7 +1,15 @@ {...}: { imports = [ + ./outputs.nix + + ./apps.nix ./checks.nix - ./deploy.nix + ./devShells.nix + ./formatter.nix + ./legacyPackages.nix ./nixosConfigurations.nix + ./nixosModules.nix + ./overlays.nix + ./packages.nix ]; } diff --git a/nix/snow/flake/modules/devShells.nix b/nix/snow/flake/outputs/devShells.nix similarity index 100% rename from nix/snow/flake/modules/devShells.nix rename to nix/snow/flake/outputs/devShells.nix diff --git a/nix/snow/flake/modules/formatter.nix b/nix/snow/flake/outputs/formatter.nix similarity index 100% rename from nix/snow/flake/modules/formatter.nix rename to nix/snow/flake/outputs/formatter.nix diff --git a/nix/snow/flake/modules/legacyPackages.nix b/nix/snow/flake/outputs/legacyPackages.nix similarity index 100% rename from nix/snow/flake/modules/legacyPackages.nix rename to nix/snow/flake/outputs/legacyPackages.nix diff --git a/nix/snow/flake/outputs/nixosConfigurations.nix b/nix/snow/flake/outputs/nixosConfigurations.nix index 977fa22..7db8077 100644 --- a/nix/snow/flake/outputs/nixosConfigurations.nix +++ b/nix/snow/flake/outputs/nixosConfigurations.nix @@ -1,84 +1,35 @@ -{ - _snowFlake, - snow, - config, - systems, - root, - ... -}: let +{lib, ...}: let inherit - (builtins) - all - attrNames - warn - ; - - inherit - (config) - nodes + (lib) + mkOption + types + literalExpression ; 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; + options = { + outputs.nixosConfigurations = mkOption { + type = types.lazyAttrsOf types.raw; + default = {}; + description = '' + Instantiated NixOS configurations. Used by `nixos-rebuild`. - 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; + `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 + ]; }; - }; - specialArgs = assert (userArgs - |> attrNames - |> all (argName: - ! snowArgs ? argName - || abort '' - `specialArgs` are like super important to Snow my love... Date: Tue, 17 Mar 2026 22:47:13 +1000 Subject: [PATCH 18/19] move modules/nixosConfigurations to nodes/ --- nix/snow/flake/modules/default.nix | 1 - nix/snow/flake/nodes/default.nix | 4 ++++ nix/snow/flake/{modules => nodes}/nixosConfigurations.nix | 0 3 files changed, 4 insertions(+), 1 deletion(-) rename nix/snow/flake/{modules => nodes}/nixosConfigurations.nix (100%) diff --git a/nix/snow/flake/modules/default.nix b/nix/snow/flake/modules/default.nix index 2c0a9ca..438b213 100644 --- a/nix/snow/flake/modules/default.nix +++ b/nix/snow/flake/modules/default.nix @@ -2,6 +2,5 @@ imports = [ ./checks.nix ./deploy.nix - ./nixosConfigurations.nix ]; } diff --git a/nix/snow/flake/nodes/default.nix b/nix/snow/flake/nodes/default.nix index 07ad153..dabae4d 100644 --- a/nix/snow/flake/nodes/default.nix +++ b/nix/snow/flake/nodes/default.nix @@ -17,6 +17,10 @@ specialArgs, ... }: { + imports = [ + ./nixosConfigurations.nix + ]; + options.nodes = let inherit (lib) diff --git a/nix/snow/flake/modules/nixosConfigurations.nix b/nix/snow/flake/nodes/nixosConfigurations.nix similarity index 100% rename from nix/snow/flake/modules/nixosConfigurations.nix rename to nix/snow/flake/nodes/nixosConfigurations.nix From 8270e4e0f42b129c61ac0836c5a18959d08189ad Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Mar 2026 22:49:45 +1000 Subject: [PATCH 19/19] merge checks.nix into deploy.nix --- nix/snow/flake/modules/checks.nix | 10 --- nix/snow/flake/modules/default.nix | 1 - nix/snow/flake/modules/deploy.nix | 107 +++++++++++++++-------------- 3 files changed, 57 insertions(+), 61 deletions(-) delete mode 100644 nix/snow/flake/modules/checks.nix diff --git a/nix/snow/flake/modules/checks.nix b/nix/snow/flake/modules/checks.nix deleted file mode 100644 index de6a9c0..0000000 --- a/nix/snow/flake/modules/checks.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ - config, - _snowFlake, - ... -}: { - outputs.checks = - _snowFlake.inputs.deploy-rs.lib - |> builtins.mapAttrs (system: deployLib: - deployLib.deployChecks config.outputs.deploy); -} diff --git a/nix/snow/flake/modules/default.nix b/nix/snow/flake/modules/default.nix index 438b213..cf35a62 100644 --- a/nix/snow/flake/modules/default.nix +++ b/nix/snow/flake/modules/default.nix @@ -1,6 +1,5 @@ {...}: { imports = [ - ./checks.nix ./deploy.nix ]; } diff --git a/nix/snow/flake/modules/deploy.nix b/nix/snow/flake/modules/deploy.nix index 59bbb49..fa4923e 100644 --- a/nix/snow/flake/modules/deploy.nix +++ b/nix/snow/flake/modules/deploy.nix @@ -4,60 +4,67 @@ config, ... }: { - outputs.deploy.nodes = snow.lib.mapNodes config.nodes ({ - name, - node, - ... - }: let - inherit - (node.deploy) - ssh - user - interactiveSudo - remoteBuild - rollback - autoRollback - magicRollback - activationTimeout - confirmTimeout - ; + outputs = { + checks = + _snowFlake.inputs.deploy-rs.lib + |> builtins.mapAttrs (system: deployLib: + deployLib.deployChecks config.outputs.deploy); - nixosFor = system: _snowFlake.inputs.deploy-rs.lib.${system}.activate.nixos; - in { - hostname = - if ssh.host != null - then ssh.host - else ""; + deploy.nodes = snow.lib.mapNodes config.nodes ({ + name, + node, + ... + }: let + inherit + (node.deploy) + ssh + user + interactiveSudo + remoteBuild + rollback + autoRollback + magicRollback + activationTimeout + confirmTimeout + ; - profilesOrder = ["default"]; # profiles priority - profiles.default = { - path = nixosFor node.system config.outputs.nixosConfigurations.${name}; + nixosFor = system: _snowFlake.inputs.deploy-rs.lib.${system}.activate.nixos; + in { + hostname = + if ssh.host != null + then ssh.host + else ""; - user = user; - sudo = "sudo -u"; - interactiveSudo = interactiveSudo; + profilesOrder = ["default"]; # profiles priority + profiles.default = { + path = nixosFor node.system config.outputs.nixosConfigurations.${name}; - fastConnection = false; + user = user; + sudo = "sudo -u"; + interactiveSudo = interactiveSudo; - autoRollback = autoRollback -> rollback; - magicRollback = magicRollback -> rollback; - activationTimeout = activationTimeout; - confirmTimeout = confirmTimeout; + fastConnection = false; - 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"] - ); - }; - }); + 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"] + ); + }; + }); + }; }