From 0e29e08c207867c2d7439c7cfff6b40d7c83e2e0 Mon Sep 17 00:00:00 2001 From: Jelle Spreeuwenberg Date: Sun, 26 Apr 2026 19:11:20 +0200 Subject: [PATCH] refactor: simplify source control --- modules/data.nix | 5 -- modules/features/git.nix | 53 ++++++++++++- modules/features/source-control.nix | 108 -------------------------- modules/features/workstation-base.nix | 2 +- modules/lib/schema.nix | 31 +------- 5 files changed, 55 insertions(+), 144 deletions(-) delete mode 100644 modules/features/source-control.nix diff --git a/modules/data.nix b/modules/data.nix index 0bc5b55..997a452 100644 --- a/modules/data.nix +++ b/modules/data.nix @@ -3,27 +3,22 @@ account = { name = "kiri"; realName = "Jelle Spreeuwenberg"; - sourceControl.projectScope = "work"; emails = { personal = { address = "mail@jelles.net"; primary = true; - scope = "personal"; type = "mxrouting"; }; old = { address = "mail@jellespreeuwenberg.nl"; - scope = null; type = "mxrouting"; }; uni = { address = "j.spreeuwenberg@student.tue.nl"; - scope = null; type = "office365"; }; work = { address = "jelle.spreeuwenberg@yookr.org"; - scope = "work"; type = "office365"; }; }; diff --git a/modules/features/git.nix b/modules/features/git.nix index 7d05514..a79200a 100644 --- a/modules/features/git.nix +++ b/modules/features/git.nix @@ -1,4 +1,4 @@ -{ config, ... }: +{ config, lib, ... }: let account = config.repo.account; in @@ -6,9 +6,44 @@ in flake.modules.homeManager.git = { config, + osConfig, ... }: + let + machine = osConfig.meta.machine; + allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers"; + + mkScope = + scope: + let + email = account.emails.${scope}.address; + key = machine.sourceControl.${scope}; + hasSigningKey = key != null && key.publicKey != null; + in + { + allowedSigners = lib.optional hasSigningKey "${email} ${key.publicKey}"; + git = { + user = { + name = account.realName; + inherit email; + } + // lib.optionalAttrs hasSigningKey { + signingKey = "${key.privateKeyPath}.pub"; + }; + } + // lib.optionalAttrs hasSigningKey { + gpg.ssh.allowedSignersFile = allowedSignersFile; + }; + }; + + personal = mkScope "personal"; + work = mkScope "work"; + in { + xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" ( + personal.allowedSigners ++ work.allowedSigners ++ [ "" ] + ); + programs.git = { enable = true; signing.format = "ssh"; @@ -20,9 +55,23 @@ in init.defaultBranch = "main"; user = { name = account.realName; - email = account.primaryEmail.address; + email = account.emails.personal.address; }; }; + includes = [ + { + condition = "gitdir:${account.nixosConfigurationPath}/"; + contents = personal.git; + } + { + condition = "gitdir:${config.xdg.userDirs.projects}/"; + contents = personal.git; + } + { + condition = "gitdir:${config.home.homeDirectory}/work/"; + contents = work.git; + } + ]; }; }; } diff --git a/modules/features/source-control.nix b/modules/features/source-control.nix deleted file mode 100644 index 44e3bfb..0000000 --- a/modules/features/source-control.nix +++ /dev/null @@ -1,108 +0,0 @@ -{ config, lib, ... }: -let - account = config.repo.account; - homeModules = config.flake.modules.homeManager; -in -{ - flake.modules.homeManager.source-control = - { - config, - lib, - osConfig, - ... - }: - let - machine = osConfig.meta.machine; - sourceControl = account.sourceControl; - - scopeConfig = scope: machine.sourceControl.${scope} or null; - - emailForScope = - scope: - let - scopedEmails = lib.filter (email: email.scope == scope) (builtins.attrValues account.emails); - in - if builtins.length scopedEmails == 1 then (builtins.head scopedEmails).address else null; - - scopeHasSigningKey = - scope: - let - keyConfig = scopeConfig scope; - in - keyConfig != null && keyConfig.publicKey != null; - - privateKeyPathForScope = - scope: - let - keyConfig = scopeConfig scope; - in - if keyConfig == null || keyConfig.privateKeyPath == null then - "~/.ssh/id_${scope}" - else - keyConfig.privateKeyPath; - - publicKeyForScope = - scope: - let - keyConfig = scopeConfig scope; - in - if keyConfig == null then null else keyConfig.publicKey; - - scopesInUse = lib.unique [ - "personal" - sourceControl.projectScope - ]; - - missingEmailScopes = builtins.filter (scope: emailForScope scope == null) scopesInUse; - - allowedSignersLines = map (scope: "${emailForScope scope} ${publicKeyForScope scope}") ( - builtins.filter (scope: emailForScope scope != null && scopeHasSigningKey scope) scopesInUse - ); - - gitConfigForScope = - scope: - lib.recursiveUpdate - { - user = { - name = account.realName; - email = emailForScope scope; - }; - } - ( - lib.optionalAttrs (scopeHasSigningKey scope) { - gpg.ssh.allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers"; - user.signingKey = "${privateKeyPathForScope scope}.pub"; - } - ); - - gitRoots = [ - { - root = account.nixosConfigurationPath; - scope = "personal"; - } - { - root = config.xdg.userDirs.projects; - scope = sourceControl.projectScope; - } - ]; - in - { - imports = [ homeModules.git ]; - - assertions = [ - { - assertion = missingEmailScopes == [ ]; - message = "Missing source-control email scope for `${account.name}`: ${lib.concatStringsSep ", " missingEmailScopes}."; - } - ]; - - xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" ( - allowedSignersLines ++ [ "" ] - ); - - programs.git.includes = map (gitRoot: { - condition = "gitdir:${gitRoot.root}/"; - contents = gitConfigForScope gitRoot.scope; - }) gitRoots; - }; -} diff --git a/modules/features/workstation-base.nix b/modules/features/workstation-base.nix index f77ed35..3f72127 100644 --- a/modules/features/workstation-base.nix +++ b/modules/features/workstation-base.nix @@ -54,7 +54,7 @@ in homeModules.qbittorrent-client homeModules.shell homeModules.sops - homeModules.source-control + homeModules.git homeModules.ssh-client homeModules.syncthing homeModules.terminal diff --git a/modules/lib/schema.nix b/modules/lib/schema.nix index 82c6d0e..2c6e688 100644 --- a/modules/lib/schema.nix +++ b/modules/lib/schema.nix @@ -1,10 +1,5 @@ { lib, ... }: let - sourceControlScopeType = lib.types.enum [ - "personal" - "work" - ]; - emailProviderType = lib.types.enum [ "mxrouting" "office365" @@ -26,21 +21,6 @@ let type = lib.mkOption { type = emailProviderType; }; - - scope = lib.mkOption { - type = lib.types.nullOr sourceControlScopeType; - default = null; - }; - }; - } - ); - - sourceControlAccountType = lib.types.submodule ( - { ... }: - { - options.projectScope = lib.mkOption { - type = sourceControlScopeType; - default = "personal"; }; } ); @@ -72,11 +52,6 @@ let default = { }; }; - sourceControl = lib.mkOption { - type = sourceControlAccountType; - default = { }; - }; - primaryEmail = lib.mkOption { type = lib.types.nullOr emailType; description = "Derived primary email entry for this user."; @@ -133,7 +108,7 @@ let ); sourceControlMachineKeyType = lib.types.submodule ( - { ... }: + { name, ... }: { options = { publicKey = lib.mkOption { @@ -142,8 +117,8 @@ let }; privateKeyPath = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; + type = lib.types.str; + default = "~/.ssh/id_${name}"; }; }; }