diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1f248798..bcc4f4c9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -84,7 +84,7 @@ jobs: # max-parallel: 2 strategy: matrix: - template: [bogus, minimal, microvm, nvf-standalone] + template: [bogus, minimal, microvm, nvf-standalone, flake-parts-modules] os: [ubuntu-latest] name: Check template ${{matrix.template}} ${{matrix.os}} runs-on: ${{matrix.os}} diff --git a/nix/default.nix b/nix/default.nix index f8448f27..145a432a 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -19,6 +19,8 @@ let microvm.description = "MicroVM example"; nvf-standalone.path = ../templates/nvf-standalone; nvf-standalone.description = "Standalone NVF"; + flake-parts-modules.path = ../templates/flake-parts-modules; + flake-parts-modules.description = "flake-parts classes"; ci.path = ../templates/ci; ci.description = "Feature Tests"; bogus.path = ../templates/bogus; diff --git a/nix/lib/forward.nix b/nix/lib/forward.nix index e681f0f2..e6ffe387 100644 --- a/nix/lib/forward.nix +++ b/nix/lib/forward.nix @@ -33,7 +33,7 @@ let }; freeformMod = { - config._module.freeformType = lib.types.lazyAttrsOf lib.types.anything; + config._module.freeformType = lib.types.lazyAttrsOf lib.types.unspecified; }; adapterMods = [ diff --git a/templates/flake-parts-modules/README.md b/templates/flake-parts-modules/README.md new file mode 100644 index 00000000..0c364658 --- /dev/null +++ b/templates/flake-parts-modules/README.md @@ -0,0 +1,7 @@ +# Example Den custom classes for flake-parts modules and perSystem outputs. + +This example showcases Den forward classes for third-party flake-parts modules. + +This README is generated by `nix run .#write-files`. + +See den.nix, custom-classes.nix and perSystem-forward.nix diff --git a/templates/flake-parts-modules/flake.lock b/templates/flake-parts-modules/flake.lock new file mode 100644 index 00000000..ee08026a --- /dev/null +++ b/templates/flake-parts-modules/flake.lock @@ -0,0 +1,206 @@ +{ + "nodes": { + "den": { + "locked": { + "lastModified": 1774981725, + "narHash": "sha256-eaNpxQLoNpALVyiolZQEIoi6eH529jcXeQ7LfuwtHIY=", + "owner": "vic", + "repo": "den", + "rev": "66677bf5f235c5f5fe742e3839f6c184d66065df", + "type": "github" + }, + "original": { + "owner": "vic", + "repo": "den", + "type": "github" + } + }, + "devshell": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1768818222, + "narHash": "sha256-460jc0+CZfyaO8+w8JNtlClB2n4ui1RbHfPTLkpwhU8=", + "owner": "numtide", + "repo": "devshell", + "rev": "255a2b1725a20d060f566e4755dbf571bbbb5f76", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "files": { + "locked": { + "lastModified": 1762767848, + "narHash": "sha256-trF2WXzH57uSkA1zeI8FTz8tU6vPYrklkTjh/7DZy/M=", + "owner": "mightyiam", + "repo": "files", + "rev": "2d9d4937e94006ad8f165dfab9dff87cfab7eb2b", + "type": "github" + }, + "original": { + "owner": "mightyiam", + "repo": "files", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "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" + } + }, + "import-tree": { + "locked": { + "lastModified": 1773693634, + "narHash": "sha256-BtZ2dtkBdSUnFPPFc+n0kcMbgaTxzFNPv2iaO326Ffg=", + "owner": "vic", + "repo": "import-tree", + "rev": "c41e7d58045f9057880b0d85e1152d6a4430dbf1", + "type": "github" + }, + "original": { + "owner": "vic", + "repo": "import-tree", + "type": "github" + } + }, + "nix-topology": { + "inputs": { + "flake-parts": [ + "flake-parts" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1774824790, + "narHash": "sha256-3R2aoykbutdJ7YQaZiU7uO8w4O8b6RjztTPNo8isLTI=", + "owner": "oddlama", + "repo": "nix-topology", + "rev": "5765ce41be8a4fb5471a57671c2b740a350c5da0", + "type": "github" + }, + "original": { + "owner": "oddlama", + "repo": "nix-topology", + "type": "github" + } + }, + "nix-unit": { + "inputs": { + "flake-parts": [ + "flake-parts" + ], + "nix-github-actions": [], + "nixpkgs": [ + "nixpkgs" + ], + "treefmt-nix": [ + "treefmt-nix" + ] + }, + "locked": { + "lastModified": 1762774186, + "narHash": "sha256-hRADkHjNt41+JUHw2EiSkMaL4owL83g5ZppjYUdF/Dc=", + "owner": "nix-community", + "repo": "nix-unit", + "rev": "1c9ab50554eed0b768f9e5b6f646d63c9673f0f7", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-unit", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1774855581, + "narHash": "sha256-YkreHeMgTCYvJ5fESV0YyqQK49bHGe2B51tH6claUh4=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "15c6719d8c604779cf59e03c245ea61d3d7ab69b", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pkgs-by-name-for-flake-parts": { + "locked": { + "lastModified": 1769286518, + "narHash": "sha256-F7VlUICvYp2wJKyQqM6d46BNEZCzMQ6dMH9zbmjuybc=", + "owner": "drupol", + "repo": "pkgs-by-name-for-flake-parts", + "rev": "7ba1cd4a9a72c9c6c272018a63f090f2c912a171", + "type": "github" + }, + "original": { + "owner": "drupol", + "repo": "pkgs-by-name-for-flake-parts", + "type": "github" + } + }, + "root": { + "inputs": { + "den": "den", + "devshell": "devshell", + "files": "files", + "flake-parts": "flake-parts", + "import-tree": "import-tree", + "nix-topology": "nix-topology", + "nix-unit": "nix-unit", + "nixpkgs": "nixpkgs", + "pkgs-by-name-for-flake-parts": "pkgs-by-name-for-flake-parts", + "treefmt-nix": "treefmt-nix" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1773297127, + "narHash": "sha256-6E/yhXP7Oy/NbXtf1ktzmU8SdVqJQ09HC/48ebEGBpk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "71b125cd05fbfd78cab3e070b73544abe24c5016", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/templates/flake-parts-modules/flake.nix b/templates/flake-parts-modules/flake.nix new file mode 100644 index 00000000..b1b363f6 --- /dev/null +++ b/templates/flake-parts-modules/flake.nix @@ -0,0 +1,38 @@ +{ + description = "Using flake-parts modules from Den"; + + outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./modules); + + inputs = { + den.url = "github:vic/den"; + import-tree.url = "github:vic/import-tree"; + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-parts.url = "github:hercules-ci/flake-parts"; + flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; + + pkgs-by-name-for-flake-parts.url = "github:drupol/pkgs-by-name-for-flake-parts"; + + files.url = "github:mightyiam/files"; + + devshell.url = "github:numtide/devshell"; + devshell.inputs.nixpkgs.follows = "nixpkgs"; + + treefmt-nix.url = "github:numtide/treefmt-nix"; + treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; + + nix-unit.url = "github:nix-community/nix-unit"; + nix-unit.inputs = { + nixpkgs.follows = "nixpkgs"; + flake-parts.follows = "flake-parts"; + nix-github-actions.follows = ""; + treefmt-nix.follows = "treefmt-nix"; + }; + + nix-topology.url = "github:oddlama/nix-topology"; + nix-topology.inputs = { + nixpkgs.follows = "nixpkgs"; + flake-parts.follows = "flake-parts"; + }; + + }; +} diff --git a/templates/flake-parts-modules/modules/custom-classes.nix b/templates/flake-parts-modules/modules/custom-classes.nix new file mode 100644 index 00000000..76655a57 --- /dev/null +++ b/templates/flake-parts-modules/modules/custom-classes.nix @@ -0,0 +1,94 @@ +{ + den, + lib, + inputs, + config, + ... +}: +{ + systems = builtins.attrNames den.hosts; + + # Some third-party flake-parts modules for demo purposes. + # Read their documentation at https://flake.parts for usage. + imports = [ + inputs.devshell.flakeModule + inputs.files.flakeModules.default + inputs.nix-topology.flakeModule + inputs.nix-unit.modules.flake.default + inputs.pkgs-by-name-for-flake-parts.flakeModule + inputs.treefmt-nix.flakeModule + ]; + + # some globals + perSystem = { + pkgsDirectory = ../packages; + nix-unit = { + allowNetwork = true; + inputs = inputs; + }; + }; + + # den.ctx.flake-parts transformations define which + # custom classes exist and where to read them. + den.ctx.flake-parts.into = _: { + + # Read flake-parts classes from hosts and their includes + host = map (host: { inherit host; }) ( + builtins.concatMap builtins.attrValues (builtins.attrValues den.hosts) + ); + + # Our custom flake-parts perSystem classes. + # These are partial params for `den._.forward`. + # See ./perSystem-forward.nix + flake-parts-system = [ + + # A class for flake-parts' perSystem.packages + # NOTE: this is different from Den's flake-packages class. + { + fromClass = _: "packages"; + intoPath = _: [ "packages" ]; + } + + { + fromClass = _: "files"; + intoPath = _: [ + "files" + ]; + adapterModule = { }; + } + + # a default `devshell` class + { + fromClass = _: "devshell"; + intoPath = _: [ + "devshells" + "default" + ]; + } + + { + fromClass = _: "treefmt"; + intoPath = _: [ "treefmt" ]; + } + + { + fromClass = _: "tests"; + intoPath = _: [ + "nix-unit" + "tests" + ]; + # test helpers + adaptArgs = + { pkgs, ... }: + let + igloo = config.flake.nixosConfigurations.igloo.config; + tux = igloo.users.users.tux; + in + { + inherit pkgs igloo tux; + }; + } + ]; + }; + +} diff --git a/templates/flake-parts-modules/modules/den.nix b/templates/flake-parts-modules/modules/den.nix new file mode 100644 index 00000000..8a10ba3c --- /dev/null +++ b/templates/flake-parts-modules/modules/den.nix @@ -0,0 +1,98 @@ +{ + den, + lib, + inputs, + config, + ... +}: +{ + imports = [ inputs.den.flakeModule ]; + + den.hosts.x86_64-linux.igloo.users.tux = { }; + + den.aspects.igloo = { + # User TODO: Remove for real host + nixos.fileSystems."/".device = "/dev/no-boot"; + nixos.boot.loader.grub.enable = false; + }; + + den.aspects.tux = { + includes = [ den._.define-user ]; + user.description = "Bird"; + + tests = + { tux, ... }: + { + test-tux-is-bird = { + expr = tux.description; + expected = "Bird"; + }; + }; + }; + + # Read flake-parts classes from foo aspect and its includes + den.ctx.flake-parts.includes = [ den.aspects.foo ]; + + den.aspects.foo = { + includes = [ den.aspects.bar ]; + + treefmt.settings.on-unmatched = "warn"; + + devshell.commands = [ { package = "cowsay"; } ]; + + packages = + { pkgs, ... }: + { + topology = config.flake.topology.${pkgs.stdenv.targetPlatform.system}.config.output; + }; + }; + + den.aspects.bar = { + treefmt.programs.nixfmt.enable = true; + + tests.test-math-works = { + expr = 22 * 2; + expected = 44; + }; + + packages = + { config, ... }: + { + write-files = config.files.writer.drv; + }; + + files = + { pkgs, ... }: + { + files = [ + { + path_ = "README.md"; + drv = pkgs.writeText "README.md" '' + # Example Den custom classes for flake-parts modules and perSystem outputs. + + This example showcases Den forward classes for third-party flake-parts modules. + + This README is generated by `nix run .#write-files`. + + See den.nix, custom-classes.nix and perSystem-forward.nix + ''; + } + ]; + }; + + devshell = + { pkgs, self', ... }: + { + commands = [ + { + package = self'.packages.write-files; + } + ]; + packages = [ + pkgs.hello + ]; + }; + + }; + +} diff --git a/templates/flake-parts-modules/modules/perSystem-forward.nix b/templates/flake-parts-modules/modules/perSystem-forward.nix new file mode 100644 index 00000000..bfb0cbef --- /dev/null +++ b/templates/flake-parts-modules/modules/perSystem-forward.nix @@ -0,0 +1,24 @@ +{ den, lib, ... }: +let + + perSystemFwd = + forwardArgs: + { class, aspect-chain }: + den._.forward ( + { + each = lib.optional (class == "flake-parts") forwardArgs; + intoClass = _: "flake-parts"; + fromAspect = _: lib.head aspect-chain; + adaptArgs = { config, ... }: config.allModuleArgs; + } + // forwardArgs + ); + + ctx.flake-parts = { }; + ctx.flake-parts-system.provides.flake-parts-system = perSystemFwd; + perSystemModule = den.lib.aspects.resolve "flake-parts" (den.ctx.flake-parts { }); +in +{ + den.ctx = ctx; + perSystem.imports = [ perSystemModule ]; +} diff --git a/templates/flake-parts-modules/packages/hola.nix b/templates/flake-parts-modules/packages/hola.nix new file mode 100644 index 00000000..ac18240a --- /dev/null +++ b/templates/flake-parts-modules/packages/hola.nix @@ -0,0 +1 @@ +{ hello }: hello