Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions nix/lib/aspects/fx/edges/materialize-unified.nix
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ let
scopeContexts
scopeParent
scopeIsolated
scopeEntityKind
;
# Stable scope name for the trace-edge construction (ordering only).
name = den.lib.aspects.fx.edges.edge.scopeName {
Expand Down Expand Up @@ -176,6 +177,7 @@ let
rootScopeId
scopeContexts
scopeParent
scopeEntityKind
spawnNode
buildForwardAspect
;
Expand Down
13 changes: 10 additions & 3 deletions nix/lib/aspects/fx/edges/route.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ let
synthesize
rootTarget
;
inherit (import ./spawn-context.nix { inherit lib; }) mkSourceScopeBindings;
inherit (import ../scope-walk.nix { inherit lib; }) subtreeScopes;

# ===== materialization mechanics (ported from route/wrap.nix) ==========
Expand Down Expand Up @@ -579,15 +580,18 @@ let
# edges here would double-count the same delivery. Only the drain-fold spawn
# (resolve.nix mkDrained) surfaces edges into unifiedEdges.
resolveSourceFallback =
spec: spawnNode: scopeParent:
spec: spawnNode: scopeParent: scopeContexts: scopeEntityKind:
if !(spec ? sourceAspect) || spawnNode == null || !(spec ? sourceScopeId) then
[ ]
else
(spawnNode {
from = scopeParent.${spec.sourceScopeId} or spec.sourceScopeId;
class = spec.fromClass;
aspect = den.lib.aspects.normalizeRoot spec.sourceAspect;
bindings = { };
bindings = mkSourceScopeBindings {
inherit scopeContexts scopeEntityKind;
sourceScopeId = spec.sourceScopeId;
};
}).imports;

# Append synthesized modules to a class bucket at a scope (flat + perScope).
Expand Down Expand Up @@ -615,6 +619,7 @@ let
rootScopeId,
scopeContexts,
scopeParent,
scopeEntityKind,
spawnNode,
buildForwardAspect,
}:
Expand All @@ -625,7 +630,7 @@ let
if collectedSource != [ ] then
collectedSource
else
resolveSourceFallback spec spawnNode scopeParent;
resolveSourceFallback spec spawnNode scopeParent scopeContexts scopeEntityKind;
sourceModule = spec.mapModule { imports = sourceModules; };
newMods = collectClassMods spec.intoClass (buildForwardAspect spec sourceModule);
in
Expand Down Expand Up @@ -706,6 +711,7 @@ let
scopeParent ? { },
scopeIsolated ? { },
scopeContexts ? { },
scopeEntityKind,
spawnNode ? null,
rootScopeId ? null,
buildForwardAspect ? null,
Expand All @@ -723,6 +729,7 @@ let
rootScopeId
scopeContexts
scopeParent
scopeEntityKind
spawnNode
buildForwardAspect
;
Expand Down
17 changes: 17 additions & 0 deletions nix/lib/aspects/fx/edges/spawn-context.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{ ... }:
{
# Fallback rewalk starts from the parent scope for fleet visibility, so restore
# the source scope's own entity binding (for example, `user`) explicitly.
mkSourceScopeBindings =
{
scopeContexts,
scopeEntityKind,
sourceScopeId,
}:
let
sourceCtx = scopeContexts.${sourceScopeId} or { };
ownKind = scopeEntityKind.${sourceScopeId} or null;
ownRecord = if ownKind == null then null else sourceCtx.${ownKind} or null;
in
if ownRecord == null then { } else { ${ownKind} = ownRecord; };
Comment thread
drupol marked this conversation as resolved.
}
4 changes: 3 additions & 1 deletion nix/lib/aspects/fx/resolve.nix
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,14 @@ let
# complex-route forward SOURCE with full fleet visibility (replaces the old
# isolated fxResolve fallback).
applyRoutes =
spawnNode: ctx: scopeContexts: rootScopeId: scopeParent: scopeIsolated: scopedRoutes: acc:
spawnNode: ctx: scopeContexts: rootScopeId: scopeParent: scopeIsolated: scopeEntityKind: scopedRoutes: acc:
routeEdges.applyRoutes {
inherit
scopedRoutes
scopeContexts
scopeParent
scopeIsolated
scopeEntityKind
rootScopeId
spawnNode
;
Expand Down Expand Up @@ -983,6 +984,7 @@ let
oraclePhase2 = applyProvidesEdges ctx scopedProvides phase1;
oraclePhase3 =
applyRoutes spawnNode ctx augmentedScopeContexts result.state.rootScopeId scopeParent scopeIsolated
scopeEntityKind
scopedRoutes
oraclePhase2;
in
Expand Down
90 changes: 90 additions & 0 deletions templates/ci/modules/deadbugs/hm-platform-forward.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Regression for discussion #620:
# `docs/src/content/docs/guides/custom-classes.mdx`,
# "Example: Platform specific `hm` classes".
#
# The documented `hmPlatforms` forward failed for a host user with
# "spawnNode spawn root equals its parent scope".
{ denTest, ... }:
{
flake.tests.deadbugs.hm-platform-forward = {

# Docs example: forward `hmLinux`, guard out `hmDarwin`.
test-doc-example-forwards-linux-only = denTest (
{
den,
lib,
tuxHm,
...
}:
let
hmPlatforms =
{ class, aspect-chain }:
den.batteries.forward {
each = [
"Linux"
"Darwin"
"Aarch64"
"64bit"
];
fromClass = platform: "hm${platform}";
intoClass = _: "homeManager";
intoPath = _: [ ];
fromAspect = _: lib.head aspect-chain;
guard = { pkgs, ... }: platform: lib.mkIf pkgs.stdenv."is${platform}";
adaptArgs =
{ config, ... }:
{
osConfig = config;
};
};
in
{
den.hosts.x86_64-linux.igloo.users.tux = { };
den.aspects.tux = {
includes = [ hmPlatforms ];

hmLinux.home.sessionVariables.HM_PLATFORM = "linux";

hmDarwin.home.sessionVariables.HM_PLATFORM_DARWIN = "darwin";
};

expr = {
linux = tuxHm.home.sessionVariables.HM_PLATFORM or null;
darwin = tuxHm.home.sessionVariables.HM_PLATFORM_DARWIN or null;
};
expected = {
linux = "linux";
darwin = null;
};
}
);

# Unknown source class: forwarding an undeclared, unused class into an
# evaluated class should be inert, not crash during fallback rewalk.
test-unknown-source-class-to-home-manager-is-inert = denTest (
{
den,
lib,
igloo,
...
}:
let
forwardUnknownSource =
{ aspect-chain, ... }:
den.batteries.forward {
each = [ true ];
fromClass = _: "unusedSource";
intoClass = _: "homeManager";
fromAspect = _: lib.head aspect-chain;
};
in
{
den.hosts.x86_64-linux.igloo.users.tux = { };
den.aspects.tux.includes = [ forwardUnknownSource ];

expr = igloo.home-manager.users.tux.home.stateVersion;
expected = "25.11";
}
);
};
}
Loading