Home-Manager: Run activation script after programs are set up (e.g. git)

In home.activation one can specify activation script that are run in a systemd service (by that user) at startup. There is infrastructure to order those, e.g. with lib.hm.dag.entryAfter:

{ pkgs, ... }: {
  imports = [ <home-manager/nixos> ];
  home-manager.users.myUser = { pkgs, lib, osConfig, ... }: {
    home.activation = {
      #                                                       👇👇👇        👇👇👇 doesn't seem to do anything...
      makeRepo = lib.hm.dag.entryAfter [ "writeBoundary" "installPackages" "git" ] ''
        export PATH="${
          lib.makeBinPath (with pkgs; [ git ])
        }:$PATH"
        git clone https://git-host.com/repo ~/repo
        cd ~/repo
        touch bla
        git add -A;git commit -m "cantcommit" # fails, git has no user set
      '';
    };
    programs.git = {
      enable = true;
      userEmail = "me@internet.com";
      userName = "me";
    };
  };
}

However in this case it fails as git has no user/email set. How do I tell home-manager to first set up git, then run the activation?

If it errors out, the ~/.config/git/config isn’t even created, so home-manager seems to run the activation before the setting up the programs. If I ignore the error in the activation with || true, the activation proceeds and the ~/.config/git/config is created.

I also don’t see anything programs.git-related in journalctl -eu home-manager-myUser.service, even with home-manager.verbose = true set. :person_shrugging:

Ahm… what user do these scripts run as, at all?

It’s home-manager, so they run as that user, here myUser.

This is probably a bad workaround but you could try telling git to set your email and username at the repo level, inside the script by referencing the config.programs.git.userEmail and userName? (You could also unset this at the end of the script).

Yeah thought about that as well. A bit inelegant though :upside_down_face:

I would guess this script is isolated to a good degree. I wouldn’t expect it to run in the environment of a login shell.

What @wyyllou suggests seems like the correct approach to me.

But there’s something fishy to me about trying to clone a repo in a home manager activation script. At the very least, it wouldn’t work offline, would it?

Yeah I have my reasons to do that. It’s also not a clone but executing a git command in a then extracted tarball of a repo. I wanted to keep complexity low for this example.

1 Like

Hi,

I’ve no issue with this activation script in home manager

  home.activation = {
    makePotato = lib.hm.dag.entryAfter ["writeBoundary"] ''
      git clone git@github.com:hansemschnokeloch/automatic-potato.git ~/potato
    '';
  };

authentication on github with ssh key, and git installed with environment.systemPackages = [ git ];

I guess one doesn’t need user.email and user.name set while cloning. That’s why I included the commit operation below.

I had a similar issue, I could commit but couldn’t push. From my understanding, the script is ran as root, so it doesn’t have your ssh key or git config, and clone the repository with root config.

I fixed it by specifying the ssh key

$DRY_RUN_CMD ${pkgs.git}/bin/git clone git@github.com:cbaconnier/nvim.git "$nvimConfigPath" \
 --config core.sshCommand="${pkgs.openssh}/bin/ssh -i ${config.home.homeDirectory}/.ssh/id_rsa"