home-manager-auto-upgrade: add switch flags and pre-switch commands

Add a flags option for passing extra arguments to home-manager
switch and a preSwitchCommands option for running commands before the
switch.

Preserve the legacy flake update behavior behind a deprecation warning,
clean up the shell script, and cover the flake path in tests.
This commit is contained in:
Takumi 2026-04-22 18:40:12 -05:00 committed by Austin Horstman
parent 9c7dcc55bd
commit 8f259af671
2 changed files with 112 additions and 30 deletions

View file

@ -6,39 +6,79 @@
}:
let
cfg = config.services.home-manager.autoUpgrade;
homeManagerPackage = config.programs.home-manager.package;
hmExtraArgs = lib.escapeShellArgs cfg.flags;
legacyPreSwitchCommands = lib.warn ''
services.home-manager.autoUpgrade:
Implicit `nix flake update` before `home-manager switch` is deprecated.
Please set `services.home-manager.autoUpgrade.preSwitchCommands`
explicitly.
'' [ "nix flake update" ];
# null = legacy behavior
# [] = run nothing
preSwitchCommands =
if cfg.useFlake && cfg.preSwitchCommands == null then
legacyPreSwitchCommands
else if cfg.preSwitchCommands == null then
[ ]
else
cfg.preSwitchCommands;
hasPreSwitchCommands = preSwitchCommands != [ ];
preSwitchScript = lib.optionalString hasPreSwitchCommands (
lib.concatStringsSep "\n" (
[
''echo "Running pre-switch commands"''
"set -o xtrace"
]
++ preSwitchCommands
)
);
autoUpgradeApp = pkgs.writeShellApplication {
name = "home-manager-auto-upgrade";
text =
if cfg.useFlake then
''
set -e
if [[ ! -f "$FLAKE_DIR/flake.nix" ]]; then
echo "No flake.nix found in $FLAKE_DIR." >&2
exit 1
fi
echo "Changing to flake directory $FLAKE_DIR"
cd "$FLAKE_DIR"
echo "Update flake inputs"
nix flake update
echo "Upgrade Home Manager"
home-manager switch --flake .
''
else
''
echo "Update Nix's channels"
nix-channel --update
echo "Upgrade Home Manager"
home-manager switch
'';
runtimeInputs = with pkgs; [
homeManagerPackage
nix
];
text =
if cfg.useFlake then
''
set -euo pipefail
if [[ ! -f "$FLAKE_DIR/flake.nix" ]]; then
echo "No flake.nix found in $FLAKE_DIR." >&2
exit 1
fi
echo "Changing to flake directory $FLAKE_DIR"
cd "$FLAKE_DIR"
${preSwitchScript}
echo "Upgrade Home Manager"
home-manager switch --flake . ${hmExtraArgs}
''
else
''
set -euo pipefail
echo "Update Nix channels"
nix-channel --update
${preSwitchScript}
echo "Upgrade Home Manager"
home-manager switch ${hmExtraArgs}
'';
};
in
{
@ -48,7 +88,8 @@ in
services.home-manager.autoUpgrade = {
enable = lib.mkEnableOption ''
the Home Manager upgrade service that periodically updates your Nix
channels before running `home-manager switch`'';
configuration before running `home-manager switch`
'';
frequency = lib.mkOption {
type = lib.types.str;
@ -57,15 +98,16 @@ in
The interval at which the Home Manager auto upgrade is run.
This value is passed to the systemd timer configuration
as the `OnCalendar` option.
The format is described in
{manpage}`systemd.time(7)`.
The format is described in systemd.time(7).
'';
};
useFlake = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to use 'nix flake update' instead of 'nix-channel --update'.";
description = ''
Whether to use flake-based Home Manager configuration.
'';
};
flakeDir = lib.mkOption {
@ -73,7 +115,39 @@ in
default = "${config.xdg.configHome}/home-manager";
defaultText = lib.literalExpression ''"''${config.xdg.configHome}/home-manager"'';
example = "/home/user/dotfiles";
description = "The directory of the flake to update.";
description = ''
Directory containing flake.nix.
'';
};
flags = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [
"--impure"
"-b"
"hmbak"
];
description = ''
Extra arguments passed to `home-manager switch`.
'';
};
preSwitchCommands = lib.mkOption {
type = lib.types.nullOr (lib.types.listOf lib.types.str);
default = null;
example = lib.literalExpression ''
[
"''${pkgs.gitMinimal}/bin/git pull"
"nix flake update"
]
'';
description = ''
Shell commands executed before `home-manager switch`.
- null: use legacy behavior (deprecated)
- []: run no pre-switch commands
'';
};
};
};
@ -97,10 +171,17 @@ in
};
services.home-manager-auto-upgrade = {
Unit.Description = "Home Manager upgrade";
Unit = {
Description = "Home Manager upgrade";
X-SwitchMethod = "keep-old";
};
Service = {
ExecStart = "${autoUpgradeApp}/bin/home-manager-auto-upgrade";
Environment = lib.mkIf cfg.useFlake [ "FLAKE_DIR=${cfg.flakeDir}" ];
Environment = lib.mkIf cfg.useFlake [
"FLAKE_DIR=${cfg.flakeDir}"
];
};
};
};

View file

@ -4,6 +4,7 @@
frequency = "daily";
useFlake = true;
flakeDir = "/tmp/my-flake";
preSwitchCommands = [ "nix flake update" ];
};
nmt.script = ''