From 540f5feb78db9c0d9c6de611dc69db35d2c8a654 Mon Sep 17 00:00:00 2001 From: UGA Innovation Factory Date: Tue, 27 Jan 2026 15:05:52 -0500 Subject: [PATCH] fix: Lazily fetch external modules only if needed --- fleet/default.nix | 47 +++++++++++++++++++++++++++++++++++++----- fleet/fleet-option.nix | 32 ++++++++++++++++++++++++---- fleet/user-config.nix | 10 ++++++++- inventory.nix | 6 +++--- sw/default.nix | 7 ------- users.nix | 6 ++++-- 6 files changed, 86 insertions(+), 22 deletions(-) diff --git a/fleet/default.nix b/fleet/default.nix index 7fe2f3d..3bb9d31 100644 --- a/fleet/default.nix +++ b/fleet/default.nix @@ -36,8 +36,20 @@ let externalModulePath = if externalModuleThunk != null then let - # Force evaluation of the thunk (fetchGit, fetchTarball, etc.) - fetchedPath = externalModuleThunk; + # Force evaluation of the thunk + fetchedPath = + if + builtins.isAttrs externalModuleThunk + && externalModuleThunk ? _type + && externalModuleThunk._type == "lazy-fetchGit" + then + # New format: lazy fetchGit - only execute when needed + (builtins.fetchGit { + inherit (externalModuleThunk) url rev submodules; + }).outPath + else + # Legacy: pre-fetched derivation or path + externalModuleThunk; # Extract outPath from fetchGit/fetchTarball results extractedPath = if builtins.isAttrs fetchedPath && fetchedPath ? outPath then fetchedPath.outPath else fetchedPath; @@ -61,10 +73,19 @@ let name: user: if (user ? external && user.external != null) then let + # Resolve external path (lazy fetchGit if needed) externalPath = - if builtins.isAttrs user.external && user.external ? outPath then + if builtins.isAttrs user.external && user.external ? url && user.external ? rev then + # New format: lazy fetchGit + (builtins.fetchGit { + inherit (user.external) url rev; + submodules = user.external.submodules or false; + }).outPath + else if builtins.isAttrs user.external && user.external ? outPath then + # Legacy: pre-fetched user.external.outPath else + # Direct path user.external; nixosModulePath = externalPath + "/nixos.nix"; in @@ -205,8 +226,24 @@ let # Check if deviceConfig has an 'external' field for lazy evaluation hasExternalField = builtins.isAttrs deviceConfig && deviceConfig ? external; - # Extract external module thunk if present (don't evaluate yet!) - externalModuleThunk = if hasExternalField then deviceConfig.external else null; + # Extract external module spec (don't evaluate fetchGit yet!) + externalModuleThunk = + if hasExternalField then + let + ext = deviceConfig.external; + in + # New format: { url, rev, submodules? } - create lazy fetchGit thunk + if builtins.isAttrs ext && ext ? url && ext ? rev then + { + _type = "lazy-fetchGit"; + inherit (ext) url rev; + submodules = ext.submodules or false; + } + # Legacy: pre-fetched or path + else + ext + else + null; # Remove 'external' from config to avoid conflicts cleanDeviceConfig = diff --git a/fleet/fleet-option.nix b/fleet/fleet-option.nix index cd32642..a435cab 100644 --- a/fleet/fleet-option.nix +++ b/fleet/fleet-option.nix @@ -125,21 +125,45 @@ let type = lib.types.nullOr ( lib.types.oneOf [ lib.types.path - lib.types.package - lib.types.attrs + (lib.types.submodule { + options = { + url = lib.mkOption { + type = lib.types.str; + description = "Git repository URL to fetch user configuration from."; + example = "https://github.com/username/dotfiles"; + }; + rev = lib.mkOption { + type = lib.types.str; + description = "Git commit hash, tag, or branch to fetch."; + example = "abc123def456..."; + }; + submodules = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to fetch Git submodules."; + }; + }; + }) ] ); default = null; description = '' External user configuration module from Git or local path. + Can be either: + - A local path: /path/to/config + - A Git repository: { url = "..."; rev = "..."; submodules? = false; } + + The Git repository is only fetched when the user is actually enabled. + Should contain user.nix (user options + home-manager config) and optionally nixos.nix (system-level config). ''; example = lib.literalExpression '' - builtins.fetchGit { + { url = "https://github.com/username/dotfiles"; - rev = "abc123..."; + rev = "abc123def456789abcdef0123456789abcdef012"; + submodules = false; }''; }; opensshKeys = lib.mkOption { diff --git a/fleet/user-config.nix b/fleet/user-config.nix index 821fd7b..07edd75 100644 --- a/fleet/user-config.nix +++ b/fleet/user-config.nix @@ -13,13 +13,21 @@ # Options are defined in fleet-option.nix for early availability. let - # Helper: Resolve external module path from fetchGit/fetchTarball/path + # Helper: Resolve external module path (with lazy Git fetching) resolveExternalPath = external: if external == null then null + # New format: { url, rev, submodules? } - only fetch when needed + else if builtins.isAttrs external && external ? url && external ? rev then + (builtins.fetchGit { + inherit (external) url rev; + submodules = external.submodules or false; + }).outPath + # Legacy: pre-fetched derivation/package else if builtins.isAttrs external && external ? outPath then external.outPath + # Direct path else external; diff --git a/inventory.nix b/inventory.nix index 3ae8054..764d073 100644 --- a/inventory.nix +++ b/inventory.nix @@ -45,7 +45,7 @@ # External modules (instead of config): # Device values can be a config attrset with an optional 'external' field: # devices."hostname" = { -# external = builtins.fetchGit { ... }; # Lazy: only fetched when building this host +# external = { url = "..."; rev = "..."; submodules? = false; }; # Lazy: only fetched when building this host # # ... additional config options # }; # The external module will be imported and evaluated only when this specific host is built. @@ -65,7 +65,7 @@ # devices."alice".athenix.forUser = "alice123"; # Sets up for user alice123 # }; # "external" = { -# devices."remote".external = builtins.fetchGit { # External module via Git (lazy) +# devices."remote".external = { url = "..."; rev = "..."; }; # External module via Git (lazy) # url = "https://github.com/example/config"; # rev = "e1ccd7cc3e709afe4f50b0627e1c4bde49165014"; # }; @@ -127,7 +127,7 @@ }; }; }; - "usda-dash".external = builtins.fetchGit { + "usda-dash".external = { url = "https://git.factory.uga.edu/MODEL/usda-dash-config.git"; rev = "dab32f5884895cead0fae28cb7d88d17951d0c12"; submodules = true; diff --git a/sw/default.nix b/sw/default.nix index 9695bc0..5c46ead 100644 --- a/sw/default.nix +++ b/sw/default.nix @@ -37,9 +37,6 @@ in ]; options.athenix.sw = { - # Software submodule for the Athenix system suite. sw.enable enables - # base packages and common configuration. Each sw..enable enables - # additional packages and services for that system type. enable = mkOption { type = lib.types.bool; default = false; @@ -57,8 +54,6 @@ in }; type = mkOption { - # DEPRECATED: Backwards compatibility for external modules - # Use athenix.sw..enable instead type = lib.types.nullOr (lib.types.either lib.types.str (lib.types.listOf lib.types.str)); default = null; description = "DEPRECATED: Use athenix.sw..enable instead. Legacy type selection."; @@ -66,7 +61,6 @@ in }; extraPackages = mkOption { - # Additional packages to install beyond the defaults type = lib.types.listOf lib.types.package; default = [ ]; description = '' @@ -77,7 +71,6 @@ in }; excludePackages = mkOption { - # Packages to exclude from the default package list type = lib.types.listOf lib.types.package; default = [ ]; description = '' diff --git a/users.nix b/users.nix index de1c030..78594e2 100644 --- a/users.nix +++ b/users.nix @@ -13,8 +13,9 @@ # # External User Configuration: # Users can specify external configuration modules via the 'external' attribute: - # external = builtins.fetchGit { url = "..."; rev = "..."; }; + # external = { url = "..."; rev = "..."; submodules? = false; }; # external = /path/to/local/config; + # external = builtins.fetchGit { ... }; # legacy, still supported # # External repositories should contain: # - user.nix (required): Defines athenix.users. options AND home-manager config @@ -47,9 +48,10 @@ enable = true; # Default user, enabled everywhere }; hdh20267 = { - external = builtins.fetchGit { + external = { url = "https://git.factory.uga.edu/hdh20267/hdh20267-nix"; rev = "dbdf65c7bd59e646719f724a3acd2330e0c922ec"; + # submodules = false; # optional, defaults to false }; }; sv22900 = {