Modular, context-aware and aspect-oriented dendritic Nix configurations. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ den.oeiuwq.com
configurations den dendritic nix aspect oriented
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(ci): Make denTest re-usable between CI and bogus templates (#424)

Updates documentation for bogus template on how to contribute.
Adds AI Policy aside.
Adds CI helper for `trace`.

authored by

Victor Borja and committed by
GitHub
4310c691 5a4b828a

+244 -312
+45 -18
docs/src/content/docs/tutorials/bogus.mdx
··· 10 10 [`templates/bogus`](https://github.com/vic/den/tree/main/templates/bogus) 11 11 </Aside> 12 12 13 - The bogus template helps you create minimal bug reproductions. Use it when reporting issues or contributing fixes. 13 + This template helps you create minimal Den reproductions. 14 + 15 + Use it for: 16 + 17 + - Showcasing focused demos of how you are trying to use Den. 18 + - Reducing a problem to its minimum outside of your infra. 19 + - Sharing code that exposes an unknown bug. 20 + - Contributing bug fixes to Den core. 21 + 22 + All PRs modifying this template are run by Den CI on the following 23 + Den versions: `PR_HEAD`, `main`, `latest`. 24 + 25 + Feel free to send any PR even if you don't know if it is an 26 + actual bug or if you don't know the solution. 27 + 28 + Just having an small, focused example can help Den maintainers a lot. 29 + We can together determine if there's something we need to fix in Den. 30 + 31 + If you wish to contribute a fix, you are more than welcome, 32 + just mention you'd like to work on this at the PR. 33 + 34 + <Aside title="AI Policy"> 35 + We accept AI assisted contributions as long as they are clear and focused and don't introduce unrelated accidental complexity. 36 + 37 + **All PR changes must be the absolute minimum required for showing/fixing bugs** 38 + </Aside> 14 39 15 40 ## Initialize 16 41 ··· 43 68 den.hosts.x86_64-linux.igloo.users.tux = { }; 44 69 45 70 # set up the scenario 46 - den.aspects.igloo.nixos.something = true; 71 + den.aspects.igloo.nixos.environment.sessionVariables.FOO = ["foo" "bar"]; 47 72 48 73 # what you get 49 - expr = igloo.something; 74 + expr = igloo.environment.sessionVariables.FOO; 50 75 # what you expect 51 - expected = true; 76 + expected = "foo:bar"; 52 77 } 53 78 ); 54 79 }; ··· 71 96 | `tuxHm` | `igloo.home-manager.users.tux` | 72 97 | `pinguHm` | `igloo.home-manager.users.pingu` | 73 98 | `funnyNames` | Resolves an aspect for class `"funny"` and collects `.names` | 74 - | `show` | `builtins.trace` helper for debugging | 99 + | `trace` | traces included aspect names | 100 + 101 + If you want to see some examples, take a look at other bogus reports that are now part of Den repository at: 102 + 103 + ```console 104 + ls den/templates/ci/modules/features/deadbugs/*.nix 105 + ``` 75 106 76 107 ## Run Tests 77 108 78 109 ```console 110 + # From the bogus root 79 111 nix flake check 80 112 ``` 81 113 82 - ## Testing Against Different Den Versions 83 114 84 - Edit `.github/workflows/test.yml` to test against multiple Den versions: 85 - 86 - ```yaml 87 - strategy: 88 - matrix: 89 - rev: ["main", "v1.0.0", "abc1234"] 115 + ```console 116 + # From the Den root 117 + just bogus 90 118 ``` 91 119 92 - This helps identify regressions — include `"main"` and any release tag or commit. 93 - 94 120 ## Contributing a Fix 95 121 96 - If you're submitting a fix to Den, test against your local checkout: 122 + Edit Den `/nix` or `/modules` code and run: 97 123 98 124 ```console 99 - cd <den-working-copy> 100 - nix flake check --override-input den . ./templates/bogus 125 + just bogus 101 126 ``` 127 + 128 + When your changes to Den have fixed the bug, be sure to 129 + move `bug.nix` into the `templates/ci/modules/feautres/deadbugs/` directory, following naming conventions for both the file and test-suite name. 102 130 103 131 ## What It Provides 104 132 ··· 111 139 112 140 ## Next Steps 113 141 114 - - Share your reproduction repo on [GitHub Discussions](https://github.com/vic/den/discussions) 115 142 - Read [Debug Configurations](/guides/debug/) for debugging techniques 116 143 - See the [CI Tests template](/tutorials/ci/) for Den's own comprehensive test suite
+1
nix/default.nix
··· 5 5 6 6 flakeModules.default = ./flakeModule.nix; 7 7 flakeModules.dendritic = ./dendritic.nix; 8 + flakeModules.denTest = ./denTest.nix; 8 9 9 10 templates = { 10 11 default.path = ../templates/default;
+114
nix/denTest.nix
··· 1 + # Test helpers for evaluating Den on isolation 2 + # 3 + # Exports _module.args.denTest 4 + { 5 + inputs, 6 + lib, 7 + config, 8 + ... 9 + }: 10 + let 11 + # isolated test, prevent polution between tests. 12 + denTest = module: { 13 + inherit ((evalDen module).config) expr expected; 14 + }; 15 + 16 + # emulate fake-parts only for self and nixpkgs. 17 + withSystem = 18 + system: 19 + let 20 + pkgs = inputs.nixpkgs.legacyPackages.${system}; 21 + inputs'.nixpkgs.packages = pkgs; 22 + inputs'.nixpkgs.legacyPackages = pkgs; 23 + self'.packages = pkgs; 24 + self'.legacyPackages = pkgs; 25 + in 26 + cb: cb { inherit inputs' self'; }; 27 + 28 + evalDen = 29 + module: 30 + lib.evalModules { 31 + specialArgs = { 32 + inherit inputs; 33 + inherit withSystem; 34 + }; 35 + modules = [ 36 + module 37 + testModule 38 + helpersModule 39 + config.denTest 40 + ]; 41 + }; 42 + 43 + testModule = { 44 + imports = [ inputs.den.flakeModule ]; 45 + options.expr = lib.mkOption { }; 46 + options.expected = lib.mkOption { }; 47 + config = { 48 + den.schema.user.classes = lib.mkDefault [ "homeManager" ]; 49 + den.default.nixos.system.stateVersion = lib.mkDefault "25.11"; 50 + den.default.homeManager.home.stateVersion = lib.mkDefault "25.11"; 51 + }; 52 + }; 53 + 54 + helpersModule = 55 + { config, den, ... }: 56 + let 57 + 58 + iceberg = config.flake.nixosConfigurations.iceberg.config; 59 + apple = config.flake.darwinConfigurations.apple.config; 60 + igloo = config.flake.nixosConfigurations.igloo.config; 61 + tuxHm = igloo.home-manager.users.tux; 62 + pinguHm = igloo.home-manager.users.pingu; 63 + 64 + sort = lib.sort (a: b: a < b); 65 + show = items: builtins.trace (lib.concatStringsSep " / " (lib.flatten [ items ])); 66 + 67 + trace = with den.lib.aspects; { 68 + __functor = _: resolve.withAdapter adapters.trace; 69 + over = outer: resolve.withAdapter (outer adapters.trace); 70 + }; 71 + 72 + funnyNames = 73 + aspect: 74 + let 75 + resolve = config.den.lib.aspects.resolve; 76 + mod = resolve "funny" aspect; 77 + namesMod = { 78 + options.names = lib.mkOption { 79 + type = lib.types.listOf lib.types.str; 80 + default = [ ]; 81 + }; 82 + }; 83 + res = lib.evalModules { 84 + modules = [ 85 + mod 86 + namesMod 87 + ]; 88 + }; 89 + in 90 + sort res.config.names; 91 + 92 + in 93 + { 94 + _module.args = { 95 + inherit 96 + show 97 + funnyNames 98 + apple 99 + igloo 100 + iceberg 101 + tuxHm 102 + pinguHm 103 + trace 104 + ; 105 + }; 106 + }; 107 + in 108 + { 109 + config._module.args = { inherit denTest; }; 110 + options.denTest = lib.mkOption { 111 + default = { }; 112 + type = lib.types.deferredModule; 113 + }; 114 + }
+13 -6
nix/lib/aspects/adapters.nix
··· 160 160 161 161 # Traces aspect.name as nested lists per includes. Composed with filterIncludes 162 162 # so tombstones and substitutions are visible. 163 - trace = filterIncludes ( 164 - { aspect, recurse, ... }: 165 - { 166 - trace = [ aspect.name ] ++ builtins.map (i: (recurse i).trace or [ ]) (aspect.includes or [ ]); 167 - } 168 - ); 163 + # 164 + # trace.on takes a function to extract any value from aspect. 165 + trace = { 166 + __functor = _: trace.on (a: a.name or "<anon>"); 167 + on = 168 + f: 169 + filterIncludes ( 170 + { aspect, recurse, ... }: 171 + { 172 + trace = [ (f aspect) ] ++ builtins.map (i: (recurse i).trace or [ ]) (aspect.includes or [ ]); 173 + } 174 + ); 175 + }; 169 176 170 177 in 171 178 {
+7 -33
templates/bogus/README.md
··· 1 - # Bug Reproduction den 2 - 3 - READ: https://den.oeiuwq.com/tutorials/ci/ 4 - 5 - Use this small template to reproduce bugs in den. 6 - 7 - Edit the `rev` list being tested at [`test.yml`](.github/workflows/test.yml), include `"main"` and any other release tag or commit sha you might want to test. This is useful for showing regressions. 8 - 9 - Create a **minimal** bug reproduction at [`modules/bug.nix`](modules/bug.nix) 10 - 11 - Each `denTest` is isolated from others so you can create as many 12 - as you want with same hosts and users. 13 - 14 - Then run tests: 15 - 16 - ```shell 17 - nix flake check 18 - ``` 19 - 20 - Running a single test with `nixpkgs#nix-unit` on PATH: 21 - 22 - ```shell 23 - # append any attrName to run just particular tests 24 - nix-unit --flake .#.tests.systems.x86_64-linux.system-agnostic 25 - ``` 1 + # READ: https://den.oeiuwq.com/tutorials/bogus/ 26 2 27 - Please share a link to your reproduction repo, showing the CI step and the error at CI build. 28 - 29 - ## Fixing Den 3 + Use this template for: 30 4 31 - If you are contributing a bug-fix PR, you can use the following command to 32 - use your local den checkout. 5 + - Showcasing focused demos of how you are trying to use Den. 6 + - Reducing a problem to its minimum outside of your infra. 7 + - Sharing code that exposes an unknown bug. 8 + - Contributing bug fixes to Den core. 33 9 34 - ```shell 35 - nix-unit --override-input den <den-working-copy> --flake <your-bogus-repo>#.tests.systems.x86_64-linux.system-agnostic 36 - ``` 10 + ALL pull-requests are welcome, even those not having solutions.
+3 -97
templates/bogus/modules/test-base.nix
··· 1 1 # DO NOT EDIT. 2 - { 3 - inputs, 4 - lib, 5 - withSystem, 6 - ... 7 - }: 8 - let 9 - # isolated test, prevent polution between tests. 10 - denTest = module: { 11 - inherit ((evalDen module).config) expr expected; 12 - }; 13 - 14 - evalDen = 15 - module: 16 - lib.evalModules { 17 - specialArgs = { 18 - inherit inputs; 19 - inherit withSystem; 20 - }; 21 - modules = [ 22 - module 23 - testModule 24 - helpersModule 25 - denModule 26 - ]; 27 - }; 28 - 29 - denModule = { 30 - imports = [ 31 - inputs.den.flakeModule 32 - inputs.den.flakeOutputs.nixosConfigurations 33 - ]; 34 - den.ctx.host.nixos = { 35 - system.stateVersion = lib.mkDefault "26.05"; 36 - boot.loader.grub.enable = lib.mkForce false; 37 - fileSystems."/".device = lib.mkForce "/dev/fake"; 38 - }; 39 - den.ctx.user.homeManager.home.stateVersion = lib.mkDefault "26.05"; 40 - den.schema.user.classes = lib.mkDefault [ "homeManager" ]; 41 - }; 42 - 43 - testModule = { 44 - options.expr = lib.mkOption { }; 45 - options.expected = lib.mkOption { }; 46 - }; 47 - 48 - helpersModule = 49 - { config, ... }: 50 - let 51 - iceberg = config.flake.nixosConfigurations.iceberg.config; 52 - igloo = config.flake.nixosConfigurations.igloo.config; 53 - tuxHm = igloo.home-manager.users.tux; 54 - pinguHm = igloo.home-manager.users.pingu; 55 - 56 - sort = lib.sort (a: b: a < b); 57 - show = items: builtins.trace (lib.concatStringsSep " / " (lib.flatten [ items ])); 58 - 59 - funnyNames = 60 - aspect: 61 - let 62 - mod = config.den.lib.aspects.resolve "funny" [ ] aspect; 63 - namesMod = { 64 - options.names = lib.mkOption { 65 - type = lib.types.listOf lib.types.str; 66 - default = [ ]; 67 - }; 68 - }; 69 - res = lib.evalModules { 70 - modules = [ 71 - mod 72 - namesMod 73 - ]; 74 - }; 75 - in 76 - sort res.config.names; 77 - 78 - in 79 - { 80 - _module.args = { 81 - inherit 82 - show 83 - funnyNames 84 - igloo 85 - iceberg 86 - tuxHm 87 - pinguHm 88 - ; 89 - }; 90 - }; 91 - 92 - in 2 + { inputs, lib, ... }: 93 3 { 94 - _module.args = { inherit denTest evalDen; }; 95 - 96 4 imports = [ 97 - inputs.den.flakeModule 5 + inputs.den.flakeModules.denTest 98 6 inputs.nix-unit.modules.flake.default 99 7 ]; 100 - 8 + denTest.imports = [ inputs.den.flakeOutputs.flake ]; 101 9 systems = lib.systems.flakeExposed; 102 - flake.packages.x86_64-linux.hello = inputs.nixpkgs.legacyPackages.x86_64-linux.hello; 103 - 104 10 perSystem.nix-unit = { 105 11 allowNetwork = lib.mkDefault true; 106 12 inputs = lib.mkDefault inputs;
+17 -22
templates/ci/modules/features/adapter-propagation.nix
··· 8 8 { den, ... }: 9 9 { 10 10 den.aspects.foo.includes = [ den.aspects.bar ]; 11 - den.aspects.foo.meta.adapter = 12 - inherited: den.lib.aspects.adapters.filter (a: (a.name or null) != "bar") inherited; 11 + den.aspects.foo.meta.adapter = den.lib.aspects.adapters.filter (a: (a.name or null) != "bar"); 13 12 den.aspects.bar.nixos = { }; 14 13 15 14 expr = (den.lib.aspects.resolve "nixos" den.aspects.foo) ? imports; ··· 18 17 ); 19 18 20 19 test-tags-includes-with-adapter = denTest ( 21 - { den, ... }: 20 + { den, trace, ... }: 22 21 { 23 22 den.aspects.parent.includes = [ den.aspects.child ]; 24 - den.aspects.parent.meta.adapter = 25 - inherited: den.lib.aspects.adapters.filter (a: (a.name or null) != "baz") inherited; 23 + den.aspects.parent.meta.adapter = den.lib.aspects.adapters.filter (a: (a.name or null) != "baz"); 26 24 den.aspects.child.includes = [ den.aspects.baz ]; 27 25 den.aspects.baz.nixos = { }; 28 26 29 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.parent; 27 + expr = trace "nixos" den.aspects.parent; 30 28 # baz tombstone visible in trace 31 29 expected.trace = [ 32 30 "parent" ··· 39 37 ); 40 38 41 39 test-child-inherits-parent-adapter = denTest ( 42 - { den, ... }: 40 + { den, trace, ... }: 43 41 { 44 42 den.aspects.parent.includes = [ den.aspects.child ]; 45 - den.aspects.parent.meta.adapter = 46 - inherited: den.lib.aspects.adapters.filter (a: (a.name or null) != "excluded") inherited; 43 + den.aspects.parent.meta.adapter = den.lib.aspects.adapters.filter ( 44 + a: (a.name or null) != "excluded" 45 + ); 47 46 den.aspects.child.includes = [ 48 47 den.aspects.kept 49 48 den.aspects.excluded ··· 51 50 den.aspects.kept.nixos = { }; 52 51 den.aspects.excluded.nixos = { }; 53 52 54 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.parent; 53 + expr = trace "nixos" den.aspects.parent; 55 54 expected.trace = [ 56 55 "parent" 57 56 [ ··· 64 63 ); 65 64 66 65 test-deep-chain-a-excludes-c-through-b = denTest ( 67 - { den, ... }: 66 + { den, trace, ... }: 68 67 { 69 68 den.aspects.a.includes = [ den.aspects.b ]; 70 - den.aspects.a.meta.adapter = 71 - inherited: den.lib.aspects.adapters.filter (a: (a.name or null) != "c") inherited; 69 + den.aspects.a.meta.adapter = den.lib.aspects.adapters.filter (a: (a.name or null) != "c"); 72 70 den.aspects.b.includes = [ 73 71 den.aspects.c 74 72 den.aspects.d ··· 76 74 den.aspects.c.nixos = { }; 77 75 den.aspects.d.nixos = { }; 78 76 79 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.a; 77 + expr = trace "nixos" den.aspects.a; 80 78 expected.trace = [ 81 79 "a" 82 80 [ ··· 89 87 ); 90 88 91 89 test-diamond-a-excludes-d-through-both-paths = denTest ( 92 - { den, ... }: 90 + { den, trace, ... }: 93 91 { 94 92 den.aspects.a.includes = [ 95 93 den.aspects.b 96 94 den.aspects.c 97 95 ]; 98 - den.aspects.a.meta.adapter = 99 - inherited: den.lib.aspects.adapters.filter (a: (a.name or null) != "d") inherited; 96 + den.aspects.a.meta.adapter = den.lib.aspects.adapters.filter (a: (a.name or null) != "d"); 100 97 den.aspects.b.includes = [ den.aspects.d ]; 101 98 den.aspects.c.includes = [ den.aspects.d ]; 102 99 den.aspects.d.nixos = { }; 103 100 104 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.a; 101 + expr = trace "nixos" den.aspects.a; 105 102 expected.trace = [ 106 103 "a" 107 104 [ ··· 123 120 { 124 121 den.hosts.x86_64-linux.igloo = { }; 125 122 126 - den.ctx.host.meta.adapter = 127 - inherited: den.lib.aspects.adapters.filter (a: a.name != "foo") inherited; 123 + den.ctx.host.meta.adapter = den.lib.aspects.adapters.filter (a: a.name != "foo"); 128 124 129 125 expr = (den.ctx.host { host = den.hosts.x86_64-linux.igloo; }).meta.adapter != null; 130 126 expected = true; ··· 150 146 { 151 147 den.hosts.x86_64-linux.igloo.users.tux = { }; 152 148 153 - den.ctx.host.meta.adapter = 154 - inherited: den.lib.aspects.adapters.filter (a: (a.name or null) != "blocked") inherited; 149 + den.ctx.host.meta.adapter = den.lib.aspects.adapters.filter (a: (a.name or null) != "blocked"); 155 150 156 151 den.aspects.igloo.includes = [ den.aspects.parent ]; 157 152 den.aspects.parent.includes = [
+10 -13
templates/ci/modules/features/aspect-adapter.nix
··· 3 3 flake.tests.aspect-adapter = { 4 4 5 5 test-meta-adapter-filters-subtree = denTest ( 6 - { den, ... }: 6 + { den, trace, ... }: 7 7 { 8 8 den.aspects.foo.includes = [ 9 9 den.aspects.bar 10 10 den.aspects.baz 11 11 ]; 12 - den.aspects.foo.meta.adapter = 13 - inherited: den.lib.aspects.adapters.filter (a: a.name != "baz") inherited; 12 + den.aspects.foo.meta.adapter = den.lib.aspects.adapters.filter (a: a.name != "baz"); 14 13 den.aspects.bar.nixos = { }; 15 14 den.aspects.baz.nixos = { }; 16 15 17 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.foo; 16 + expr = trace "nixos" den.aspects.foo; 18 17 # baz tombstone visible in trace 19 18 expected.trace = [ 20 19 "foo" ··· 25 24 ); 26 25 27 26 test-meta-adapter-only-affects-subtree = denTest ( 28 - { den, ... }: 27 + { den, trace, ... }: 29 28 { 30 29 den.aspects.root.includes = [ 31 30 den.aspects.foo 32 31 den.aspects.baz 33 32 ]; 34 33 den.aspects.foo.includes = [ den.aspects.bar ]; 35 - den.aspects.foo.meta.adapter = 36 - inherited: den.lib.aspects.adapters.filter (a: a.name != "baz") inherited; 34 + den.aspects.foo.meta.adapter = den.lib.aspects.adapters.filter (a: a.name != "baz"); 37 35 den.aspects.bar.nixos = { }; 38 36 den.aspects.baz.nixos = { }; 39 37 40 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.root; 38 + expr = trace "nixos" den.aspects.root; 41 39 # foo's adapter only affects its subtree; root's baz is unaffected 42 40 expected.trace = [ 43 41 "root" ··· 51 49 ); 52 50 53 51 test-meta-adapter-composes-with-caller = denTest ( 54 - { den, ... }: 52 + { den, trace, ... }: 55 53 { 56 54 den.aspects.foo.includes = [ 57 55 den.aspects.bar 58 56 den.aspects.baz 59 57 ]; 60 - den.aspects.foo.meta.adapter = 61 - inherited: den.lib.aspects.adapters.filter (a: a.name != "bar") inherited; 58 + den.aspects.foo.meta.adapter = den.lib.aspects.adapters.filter (a: a.name != "bar"); 62 59 den.aspects.bar.nixos = { }; 63 60 den.aspects.baz.nixos = { }; 64 61 65 62 expr = 66 63 let 67 64 inherit (den.lib.aspects) resolve adapters; 68 - outerTrace = adapters.filter (a: a.name != "baz") adapters.trace; 65 + outer = trace.over (adapters.filter (a: a.name != "baz")); 69 66 in 70 - resolve.withAdapter outerTrace "nixos" den.aspects.foo; 67 + outer "nixos" den.aspects.foo; 71 68 # bar tombstoned by meta.adapter, baz killed by outer filter (no tombstone 72 69 # since the outer filter is not wrapped in filterIncludes) 73 70 expected.trace = [
+14 -14
templates/ci/modules/features/aspect-path.nix
··· 28 28 29 29 # excludeAspect: excluded include becomes a tombstone (visible in trace) 30 30 test-excludeAspect-tombstone-in-trace = denTest ( 31 - { den, ... }: 31 + { den, trace, ... }: 32 32 { 33 33 den.aspects.foo.includes = [ 34 34 den.aspects.bar ··· 39 39 den.aspects.bar.nixos = { }; 40 40 den.aspects.baz.nixos = { }; 41 41 42 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.foo; 42 + expr = trace "nixos" den.aspects.foo; 43 43 # baz appears as tombstone (~baz, no children) 44 44 expected.trace = [ 45 45 "foo" ··· 71 71 72 72 # excludeAspect: propagates through subtree 73 73 test-excludeAspect-propagates-to-subtree = denTest ( 74 - { den, ... }: 74 + { den, trace, ... }: 75 75 { 76 76 den.aspects.root.includes = [ den.aspects.role ]; 77 77 den.aspects.root.meta.adapter = ··· 83 83 den.aspects.bar.nixos = { }; 84 84 den.aspects.baz.nixos = { }; 85 85 86 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.root; 86 + expr = trace "nixos" den.aspects.root; 87 87 # baz tombstone appears in role's subtree 88 88 expected.trace = [ 89 89 "root" ··· 98 98 99 99 # excludeAspect: by provider path 100 100 test-excludeAspect-by-provider = denTest ( 101 - { den, ... }: 101 + { den, trace, ... }: 102 102 { 103 103 den.aspects.monitoring = { 104 104 nixos = { }; ··· 113 113 den.aspects.server.meta.adapter = 114 114 inherited: den.lib.aspects.adapters.excludeAspect den.aspects.monitoring._.node-exporter inherited; 115 115 116 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.server; 116 + expr = trace "nixos" den.aspects.server; 117 117 # node-exporter tombstone visible, alerting kept 118 118 expected.trace = [ 119 119 "server" ··· 126 126 127 127 # excludeAspect: excluding a parent also excludes its providers 128 128 test-excludeAspect-cascades-to-providers = denTest ( 129 - { den, ... }: 129 + { den, trace, ... }: 130 130 { 131 131 den.aspects.monitoring = { 132 132 nixos = { }; ··· 141 141 den.aspects.server.meta.adapter = 142 142 inherited: den.lib.aspects.adapters.excludeAspect den.aspects.monitoring inherited; 143 143 144 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.server; 144 + expr = trace "nixos" den.aspects.server; 145 145 # monitoring and all its providers excluded 146 146 expected.trace = [ 147 147 "server" ··· 154 154 155 155 # substituteAspect: replaced include becomes tombstone + replacement 156 156 test-substituteAspect-replaces = denTest ( 157 - { den, ... }: 157 + { den, trace, ... }: 158 158 { 159 159 den.aspects.foo.includes = [ 160 160 den.aspects.bar ··· 166 166 den.aspects.baz.nixos = { }; 167 167 den.aspects.qux.nixos = { }; 168 168 169 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.foo; 169 + expr = trace "nixos" den.aspects.foo; 170 170 # bar tombstone + qux replacement, baz unchanged 171 171 expected.trace = [ 172 172 "foo" ··· 196 196 197 197 # substituteAspect: propagates through subtree 198 198 test-substituteAspect-propagates = denTest ( 199 - { den, ... }: 199 + { den, trace, ... }: 200 200 { 201 201 den.aspects.root.includes = [ den.aspects.role ]; 202 202 den.aspects.root.meta.adapter = ··· 209 209 den.aspects.baz.nixos = { }; 210 210 den.aspects.qux.nixos = { }; 211 211 212 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.root; 212 + expr = trace "nixos" den.aspects.root; 213 213 # baz tombstone + qux in role's subtree 214 214 expected.trace = [ 215 215 "root" ··· 225 225 226 226 # perHost parametric aspects should appear in trace by name 227 227 test-perHost-visible-in-trace = denTest ( 228 - { den, ... }: 228 + { den, trace, ... }: 229 229 { 230 230 den.aspects.role.includes = with den.aspects; [ 231 231 leaf ··· 239 239 } 240 240 ); 241 241 242 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.role; 242 + expr = trace "nixos" den.aspects.role; 243 243 expected.trace = [ 244 244 "role" 245 245 [ "leaf" ]
+15 -6
templates/ci/modules/features/resolve-adapters.nix
··· 3 3 flake.tests.resolve-adapters = { 4 4 5 5 test-basic-trace-includes = denTest ( 6 - { den, lib, ... }: 6 + { 7 + den, 8 + lib, 9 + trace, 10 + ... 11 + }: 7 12 { 8 13 9 14 den.aspects.foo.includes = [ den.aspects.bar ]; 10 15 den.aspects.bar.includes = [ den.aspects.baz ]; 11 16 den.aspects.baz.nixos = { }; 12 17 13 - expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.foo; 18 + expr = trace "nixos" den.aspects.foo; 14 19 expected.trace = [ 15 20 "foo" 16 21 [ ··· 22 27 ); 23 28 24 29 test-filter-compose-with-trace-includes = denTest ( 25 - { den, lib, ... }: 30 + { 31 + den, 32 + lib, 33 + trace, 34 + ... 35 + }: 26 36 { 27 37 28 38 den.aspects.foo.includes = [ den.aspects.bar ]; ··· 31 41 32 42 expr = 33 43 let 34 - inherit (den.lib.aspects) resolve adapters; 35 - composed = adapters.filter (aspect: aspect.name != "bar") adapters.trace; 44 + outer = den.lib.aspects.adapters.filter (aspect: aspect.name != "bar"); 36 45 in 37 - resolve.withAdapter composed "nixos" den.aspects.foo; 46 + trace.over outer "nixos" den.aspects.foo; 38 47 expected.trace = [ 39 48 "foo" 40 49 [ ]
+5 -103
templates/ci/modules/test-support/eval-den.nix
··· 1 - { 2 - inputs, 3 - lib, 4 - ... 5 - }: 6 - let 7 - # isolated test, prevent polution between tests. 8 - denTest = module: { 9 - inherit ((evalDen module).config) expr expected; 10 - }; 11 - 12 - # emulate fake-parts only for self and nixpkgs. 13 - withSystem = 14 - system: 15 - let 16 - pkgs = inputs.nixpkgs.legacyPackages.${system}; 17 - inputs'.nixpkgs.packages = pkgs; 18 - inputs'.nixpkgs.legacyPackages = pkgs; 19 - self'.packages = pkgs; 20 - self'.legacyPackages = pkgs; 21 - in 22 - cb: cb { inherit inputs' self'; }; 23 - 24 - evalDen = 25 - module: 26 - lib.evalModules { 27 - specialArgs = { 28 - inherit inputs; 29 - inherit withSystem; 30 - }; 31 - modules = [ 32 - module 33 - testModule 34 - helpersModule 35 - ]; 36 - }; 37 - 38 - testModule = { 39 - imports = [ inputs.den.flakeModule ]; 40 - options.expr = lib.mkOption { }; 41 - options.expected = lib.mkOption { }; 42 - config = { 43 - den.schema.user.classes = lib.mkDefault [ "homeManager" ]; 44 - den.default.nixos.system.stateVersion = lib.mkDefault "25.11"; 45 - den.default.homeManager.home.stateVersion = lib.mkDefault "25.11"; 46 - }; 47 - }; 48 - 49 - helpersModule = 50 - { config, ... }: 51 - let 52 - 53 - iceberg = config.flake.nixosConfigurations.iceberg.config; 54 - apple = config.flake.darwinConfigurations.apple.config; 55 - igloo = config.flake.nixosConfigurations.igloo.config; 56 - tuxHm = igloo.home-manager.users.tux; 57 - pinguHm = igloo.home-manager.users.pingu; 58 - 59 - sort = lib.sort (a: b: a < b); 60 - show = items: builtins.trace (lib.concatStringsSep " / " (lib.flatten [ items ])); 61 - 62 - funnyNames = 63 - aspect: 64 - let 65 - resolve = config.den.lib.aspects.resolve; 66 - mod = resolve "funny" aspect; 67 - namesMod = { 68 - options.names = lib.mkOption { 69 - type = lib.types.listOf lib.types.str; 70 - default = [ ]; 71 - }; 72 - }; 73 - res = lib.evalModules { 74 - modules = [ 75 - mod 76 - namesMod 77 - ]; 78 - }; 79 - in 80 - sort res.config.names; 81 - 82 - in 83 - { 84 - _module.args = { 85 - inherit 86 - show 87 - funnyNames 88 - apple 89 - igloo 90 - iceberg 91 - tuxHm 92 - pinguHm 93 - ; 94 - }; 95 - }; 96 - 97 - in 1 + { inputs, ... }: 98 2 { 99 - config._module.args = { inherit denTest evalDen; }; 100 - config.flake.packages.x86_64-linux.hello = inputs.nixpkgs.legacyPackages.x86_64-linux.hello; 101 - 102 - options.flake = lib.mkOption { 103 - type = lib.types.lazyAttrsOf lib.types.anything; 104 - }; 3 + imports = [ 4 + inputs.den.flakeModules.denTest 5 + inputs.den.flakeOutputs.flake 6 + ]; 105 7 }