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.

fix: applyDeep skips static subs that don't consume parametric ctx (#426)

PR #419 introduced applyDeep to propagate parametric context into
bare-result sub-includes. But it called takeFn unconditionally on every
sub, including full static aspects whose default functor (withOwn
parametric.atLeast) discards owned class configs in a non-static branch.
Result: `den.aspects.role._.sub.nixos.x = true` was silently dropped
when role was a parametric parent that included its sub-aspect.

Gate the inner re-application on canTake.upTo: a static aspect's default
functor has empty functionArgs, so upTo is false and the sub is left
alone for the static resolve pass. User-provided provider fns (e.g. `{
host, ... }: { nixos = ...; }`) have host in functionArgs, so upTo fires
and their config is materialized. This preserves the #419 fix while
restoring pre-#419 behavior for static sub-aspects.

Fixes #423.

authored by

Jason Bowman and committed by
GitHub
8d2fe019 92ffac19

+46 -8
+8 -8
nix/lib/parametric.nix
··· 1 1 { lib, den, ... }: 2 2 let 3 - inherit (den.lib) take; 3 + inherit (den.lib) take canTake; 4 4 inherit (den.lib.statics) owned statics isCtxStatic; 5 5 6 6 # Preserve aspect identity through functor evaluation. ··· 40 40 else if isBareResult then 41 41 r 42 42 // { 43 - includes = map ( 44 - sub: 45 - let 46 - sr = takeFn sub ctx; 47 - in 48 - if sr != { } then sr else sub 49 - ) r.includes; 43 + # Only recurse into subs whose functor actually consumes this ctx. 44 + # A static aspect's default functor takes a bare `ctx` (functionArgs 45 + # = {}), so canTake.upTo is false and we leave it alone — its owned 46 + # class configs must be picked up later by the static resolve pass. 47 + # A user-provided provider fn (e.g. { host, ... }: { nixos = ...; }) 48 + # has host in functionArgs; canTake.upTo fires and we materialize it. 49 + includes = map (sub: if canTake.upTo ctx sub then take.upTo sub ctx else sub) r.includes; 50 50 } 51 51 else 52 52 r;
+38
templates/ci/modules/features/deadbugs/issue-423-static-sub-aspect-parametric-parent.nix
··· 1 + # Static sub-aspect (attrset with owned class config) included from a 2 + # parametric parent aspect. Regression from the applyDeep fix in #419: 3 + # re-applying takeFn to the sub invoked its default functor in a non-static 4 + # context, which dropped owned class configs. 5 + # https://github.com/vic/den/pull/423 6 + { denTest, ... }: 7 + { 8 + flake.tests.deadbugs-issue-423 = { 9 + test-static-sub-aspect-from-parametric-parent = denTest ( 10 + { den, igloo, ... }: 11 + { 12 + den.hosts.x86_64-linux.igloo.users.tux = { }; 13 + 14 + # Split across modules so the parametric parent and the static sub 15 + # don't clash on the same `den.aspects.role` attribute definition. 16 + imports = [ 17 + { 18 + den.aspects.role = 19 + { host, ... }: 20 + { 21 + includes = [ den.aspects.role._.sub ]; 22 + }; 23 + } 24 + { 25 + den.aspects.role._.sub.nixos.networking.networkmanager.enable = true; 26 + } 27 + { 28 + den.aspects.igloo.includes = [ den.aspects.role ]; 29 + } 30 + ]; 31 + 32 + expr = igloo.networking.networkmanager.enable; 33 + expected = true; 34 + } 35 + ); 36 + 37 + }; 38 + }