modules/homebrew: add onActivation.cleanup "check" mode
Closes #1032 Add `"check"` to the `onActivation.cleanup` enum. When set, nix-darwin runs `brew bundle cleanup` during system checks to detect Homebrew packages that are installed but not present in the generated Brewfile. If extra packages are found, activation fails with a list of them and remediation steps. Unlike `"uninstall"` and `"zap"`, the `"check"` mode never removes packages -- it only reports. This runs during both `darwin-rebuild check` and `darwin-rebuild switch`, matching the behavior of all other system checks.
This commit is contained in:
parent
ca6f8609c3
commit
c68f5d1387
4 changed files with 66 additions and 9 deletions
|
|
@ -76,29 +76,36 @@ let
|
|||
onActivationOptions = { config, ... }: {
|
||||
options = {
|
||||
cleanup = mkOption {
|
||||
type = types.enum [ "none" "uninstall" "zap" ];
|
||||
type = types.enum [ "none" "check" "uninstall" "zap" ];
|
||||
default = "none";
|
||||
example = "uninstall";
|
||||
description = ''
|
||||
This option manages what happens to formulae installed by Homebrew, that aren't present in
|
||||
This option manages what happens to packages installed by Homebrew that aren't present in
|
||||
the Brewfile generated by this module, during {command}`nix-darwin` system
|
||||
activation.
|
||||
|
||||
When set to `"none"` (the default), formulae not present in the generated
|
||||
When set to `"none"` (the default), packages not present in the generated
|
||||
Brewfile are left installed.
|
||||
|
||||
When set to `"check"`, {command}`nix-darwin` verifies during system activation that no
|
||||
Homebrew packages (taps, formulae, casks, etc.) are installed that aren't present in the
|
||||
generated Brewfile. If extra packages are found, activation fails with a list of them.
|
||||
Note that when this check fails during {command}`darwin-rebuild switch`, the entire
|
||||
system activation is aborted and no other configuration changes will be applied until
|
||||
the issue is resolved.
|
||||
|
||||
When set to `"uninstall"`, {command}`nix-darwin` invokes
|
||||
{command}`brew bundle [install]` with the {command}`--cleanup` flag. This
|
||||
uninstalls all formulae not listed in generated Brewfile, i.e.,
|
||||
{command}`brew uninstall` is run for those formulae.
|
||||
uninstalls all packages not listed in the generated Brewfile, i.e.,
|
||||
{command}`brew uninstall` is run for those packages.
|
||||
|
||||
When set to `"zap"`, {command}`nix-darwin` invokes
|
||||
{command}`brew bundle [install]` with the {command}`--cleanup --zap`
|
||||
flags. This uninstalls all formulae not listed in the generated Brewfile, and if the
|
||||
formula is a cask, removes all files associated with that cask. In other words,
|
||||
{command}`brew uninstall --zap` is run for all those formulae.
|
||||
flags. This uninstalls all packages not listed in the generated Brewfile, and if the
|
||||
package is a cask, removes all files associated with that cask. In other words,
|
||||
{command}`brew uninstall --zap` is run for all those packages.
|
||||
|
||||
If you plan on exclusively using {command}`nix-darwin` to manage formulae
|
||||
If you plan on exclusively using {command}`nix-darwin` to manage packages
|
||||
installed by Homebrew, you probably want to set this option to
|
||||
`"uninstall"` or `"zap"`.
|
||||
'';
|
||||
|
|
@ -879,6 +886,33 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
system.checks.text = mkIf (cfg.enable && cfg.onActivation.cleanup == "check") ''
|
||||
if [ -f "${cfg.prefix}/bin/brew" ]; then
|
||||
homebrewCleanupExitCode=0
|
||||
homebrewCleanupResult=$(PATH="${cfg.prefix}/bin:${lib.makeBinPath [ pkgs.mas ]}:$PATH" \
|
||||
sudo \
|
||||
--preserve-env=PATH \
|
||||
--user=${escapeShellArg cfg.user} \
|
||||
--set-home \
|
||||
env HOMEBREW_NO_AUTO_UPDATE=1 \
|
||||
brew bundle cleanup --file='${brewfileFile}' 2>&1) || homebrewCleanupExitCode=$?
|
||||
if [ "$homebrewCleanupExitCode" -eq 1 ]; then
|
||||
printf >&2 '\e[1;31merror: found Homebrew packages not listed in the Brewfile, aborting activation\e[0m\n'
|
||||
printf >&2 '%s\n' "$homebrewCleanupResult"
|
||||
printf >&2 '\n'
|
||||
printf >&2 'To fix this, either:\n'
|
||||
printf >&2 ' - Add the listed packages to your nix-darwin Homebrew configuration\n'
|
||||
printf >&2 ' - Remove them by running: brew bundle cleanup --force\n'
|
||||
printf >&2 ' - Set homebrew.onActivation.cleanup to "uninstall" or "zap"\n'
|
||||
exit 2
|
||||
elif [ "$homebrewCleanupExitCode" -ne 0 ]; then
|
||||
printf >&2 '\e[1;31merror: brew bundle cleanup failed, aborting activation\e[0m\n'
|
||||
printf >&2 '%s\n' "$homebrewCleanupResult"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
'';
|
||||
|
||||
system.activationScripts.homebrew.text = mkIf cfg.enable ''
|
||||
# Homebrew Bundle
|
||||
echo >&2 "Homebrew bundle..."
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ in {
|
|||
tests.environment-path = makeTest ./tests/environment-path.nix;
|
||||
tests.environment-terminfo = makeTest ./tests/environment-terminfo.nix;
|
||||
tests.homebrew = makeTest ./tests/homebrew.nix;
|
||||
tests.homebrew-cleanup-check = makeTest ./tests/homebrew-cleanup-check.nix;
|
||||
tests.homebrew-shell-integration = makeTest ./tests/homebrew-shell-integration.nix;
|
||||
tests.launchd-daemons = makeTest ./tests/launchd-daemons.nix;
|
||||
tests.launchd-setenv = makeTest ./tests/launchd-setenv.nix;
|
||||
|
|
|
|||
19
tests/homebrew-cleanup-check.nix
Normal file
19
tests/homebrew-cleanup-check.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
homebrew.enable = true;
|
||||
homebrew.user = "test-homebrew-user";
|
||||
homebrew.onActivation.cleanup = "check";
|
||||
|
||||
test = ''
|
||||
echo "checking that cleanup check is present in system checks" >&2
|
||||
grep 'brew bundle cleanup --file=' ${config.out}/activate
|
||||
|
||||
echo "checking that brew bundle command does not have --cleanup flag" >&2
|
||||
if echo "${config.homebrew.onActivation.brewBundleCmd}" | grep -F -- '--cleanup' > /dev/null; then
|
||||
echo "Expected no --cleanup flag in brewBundleCmd"
|
||||
echo "Actual: ${config.homebrew.onActivation.brewBundleCmd}"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
}
|
||||
|
|
@ -128,5 +128,8 @@ in
|
|||
|
||||
echo "checking that shell integration is absent by default" >&2
|
||||
(! grep 'brew shellenv' ${config.out}/etc/zshrc)
|
||||
|
||||
echo "checking that cleanup check is absent by default" >&2
|
||||
(! grep 'brew bundle cleanup --file=' ${config.out}/activate)
|
||||
'';
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue