diff --git a/home/base/core/git.nix b/home/base/core/git.nix index a0062d59..fb337e46 100644 --- a/home/base/core/git.nix +++ b/home/base/core/git.nix @@ -1,100 +1,109 @@ { + config, lib, pkgs, myvars, ... }: { - # `programs.git` will generate the config file: ~/.config/git/config - # to make git use this config file, `~/.gitconfig` should not exist! - # - # https://git-scm.com/docs/git-config#Documentation/git-config.txt---global - home.activation.backupExistingGitconfig = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - if [[ -e ~/.gitconfig ]]; then - run mv $VERBOSE_ARG ~/.gitconfig ~/.gitconfig.bak - fi - ''; + options.modules.git.githubSsh.enable = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Rewrite https://github.com/ryan4yin remotes to SSH with the owner's key."; + }; - # GitHub CLI tool - # https://cli.github.com/manual/ - home.packages = [ pkgs.gh ]; + config = { + # `programs.git` will generate the config file: ~/.config/git/config + # to make git use this config file, `~/.gitconfig` should not exist! + # + # https://git-scm.com/docs/git-config#Documentation/git-config.txt---global + home.activation.backupExistingGitconfig = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + if [[ -e ~/.gitconfig ]]; then + run mv $VERBOSE_ARG ~/.gitconfig ~/.gitconfig.bak + fi + ''; - programs.git = { - enable = true; - lfs.enable = true; + # GitHub CLI tool + # https://cli.github.com/manual/ + home.packages = [ pkgs.gh ]; - signing.format = "openpgp"; + programs.git = { + enable = true; + lfs.enable = true; - includes = [ - { - # use different email & name for work: - # - # [user] - # email = "xxx@xxx.com" - # name = "Ryan Yin" - path = "~/work/.gitconfig"; - condition = "gitdir:~/work/"; - } - ]; + signing.format = "openpgp"; - settings = { - user.email = myvars.useremail; - user.name = myvars.userfullname; + includes = [ + { + # use different email & name for work: + # + # [user] + # email = "xxx@xxx.com" + # name = "Ryan Yin" + path = "~/work/.gitconfig"; + condition = "gitdir:~/work/"; + } + ]; - init.defaultBranch = "main"; - trim.bases = "develop,master,main"; # for git-trim - push.autoSetupRemote = true; - pull.rebase = true; - log.date = "iso"; # use iso format for date + settings = { + user.email = myvars.useremail; + user.name = myvars.userfullname; - # replace https with ssh - url = { - "ssh://git@github.com/ryan4yin" = { - insteadOf = "https://github.com/ryan4yin"; + init.defaultBranch = "main"; + trim.bases = "develop,master,main"; # for git-trim + push.autoSetupRemote = true; + pull.rebase = true; + log.date = "iso"; # use iso format for date + + # replace https with ssh + url = lib.mkIf config.modules.git.githubSsh.enable { + "ssh://git@github.com/ryan4yin" = { + insteadOf = "https://github.com/ryan4yin"; + }; + }; + + alias = { + # common aliases + br = "branch"; + co = "checkout"; + st = "status"; + ls = "log --pretty=format:\"%C(yellow)%h%Cred%d\\\\ %Creset%s%Cblue\\\\ [%cn]\" --decorate"; + ll = "log --pretty=format:\"%C(yellow)%h%Cred%d\\\\ %Creset%s%Cblue\\\\ [%cn]\" --decorate --numstat"; + cm = "commit -m"; # commit via `git cm ` + ca = "commit -am"; # commit all changes via `git ca ` + dc = "diff --cached"; + + amend = "commit --amend -m"; # amend commit message via `git amend ` + unstage = "reset HEAD --"; # unstage file via `git unstage ` + merged = "branch --merged"; # list merged(into HEAD) branches via `git merged` + unmerged = "branch --no-merged"; # list unmerged(into HEAD) branches via `git unmerged` + nonexist = "remote prune origin --dry-run"; # list non-exist(remote) branches via `git nonexist` + + # delete merged branches except master & dev & staging + # `!` indicates it's a shell script, not a git subcommand + delmerged = ''! git branch --merged | egrep -v "(^\*|main|master|dev|staging)" | xargs git branch -d''; + # delete non-exist(remote) branches + delnonexist = "remote prune origin"; + + # aliases for submodule + update = "submodule update --init --recursive"; + foreach = "submodule foreach"; }; }; + }; - alias = { - # common aliases - br = "branch"; - co = "checkout"; - st = "status"; - ls = "log --pretty=format:\"%C(yellow)%h%Cred%d\\\\ %Creset%s%Cblue\\\\ [%cn]\" --decorate"; - ll = "log --pretty=format:\"%C(yellow)%h%Cred%d\\\\ %Creset%s%Cblue\\\\ [%cn]\" --decorate --numstat"; - cm = "commit -m"; # commit via `git cm ` - ca = "commit -am"; # commit all changes via `git ca ` - dc = "diff --cached"; - - amend = "commit --amend -m"; # amend commit message via `git amend ` - unstage = "reset HEAD --"; # unstage file via `git unstage ` - merged = "branch --merged"; # list merged(into HEAD) branches via `git merged` - unmerged = "branch --no-merged"; # list unmerged(into HEAD) branches via `git unmerged` - nonexist = "remote prune origin --dry-run"; # list non-exist(remote) branches via `git nonexist` - - # delete merged branches except master & dev & staging - # `!` indicates it's a shell script, not a git subcommand - delmerged = ''! git branch --merged | egrep -v "(^\*|main|master|dev|staging)" | xargs git branch -d''; - # delete non-exist(remote) branches - delnonexist = "remote prune origin"; - - # aliases for submodule - update = "submodule update --init --recursive"; - foreach = "submodule foreach"; + # A syntax-highlighting pager for git, diff, grep, and blame output + programs.delta = { + enable = true; + enableGitIntegration = true; + options = { + diff-so-fancy = true; + line-numbers = true; + true-color = "always"; }; }; - }; - # A syntax-highlighting pager for git, diff, grep, and blame output - programs.delta = { - enable = true; - enableGitIntegration = true; - options = { - diff-so-fancy = true; - line-numbers = true; - true-color = "always"; - }; + # Git terminal UI (written in go). + programs.lazygit.enable = true; }; - - # Git terminal UI (written in go). - programs.lazygit.enable = true; } diff --git a/home/linux/tui.nix b/home/linux/tui.nix index 4fed2e58..a2016cc7 100644 --- a/home/linux/tui.nix +++ b/home/linux/tui.nix @@ -13,4 +13,8 @@ # ~/.secrets is synced to the desktops only. modules.shell.secrets.enable = false; + + # Agent hosts use their own GitHub account, logged in with `gh`, over HTTPS. + modules.git.githubSsh.enable = false; + programs.gh.enable = true; } diff --git a/hosts/README.md b/hosts/README.md index 677546b0..946902de 100644 --- a/hosts/README.md +++ b/hosts/README.md @@ -25,7 +25,8 @@ directory. - **desktop**: Niri session and GUI apps on top of the full TUI stack. - **agent**: headless, with the full TUI stack from Home Manager (shell, editors, dev toolchains, cloud CLIs, AI agents with their rules and skills), and nix-ld, rootless Podman and linger from - the system. Computer use (Xvfb + i3, VNC) is part of the profile but off by default. + the system. Computer use (Xvfb + i3, VNC) is part of the profile but off by default. Git reaches + GitHub over HTTPS with the host's own `gh` login, not the owner's SSH key. - **server**: system services only, no Home Manager. The `agent` hosts differ only in: diff --git a/outputs/x86_64-linux/tests/agent-profile/expected.nix b/outputs/x86_64-linux/tests/agent-profile/expected.nix index e74d4abf..98ec030b 100644 --- a/outputs/x86_64-linux/tests/agent-profile/expected.nix +++ b/outputs/x86_64-linux/tests/agent-profile/expected.nix @@ -5,6 +5,8 @@ let qwenInstalled = true; devToolsFromHome = true; nushellSecrets = false; + githubSshRewrite = false; + ghCredentialHelper = true; nixLd = true; rootlessPodman = true; docker = false; diff --git a/outputs/x86_64-linux/tests/agent-profile/expr.nix b/outputs/x86_64-linux/tests/agent-profile/expr.nix index e671fb26..787902e9 100644 --- a/outputs/x86_64-linux/tests/agent-profile/expr.nix +++ b/outputs/x86_64-linux/tests/agent-profile/expr.nix @@ -27,6 +27,11 @@ lib.genAttrs hosts ( devToolsFromHome = hasPackage "kubectl" home.home.packages; # ~/.secrets is synced to the desktops only; sourcing it would break nushell. nushellSecrets = home.modules.shell.secrets.enable; + # GitHub goes through the host's own `gh` login over HTTPS, not the owner's SSH key. + githubSshRewrite = home.programs.git.settings ? url; + ghCredentialHelper = lib.any (lib.hasSuffix "/bin/gh auth git-credential") ( + home.programs.git.settings.credential."https://github.com".helper or [ ] + ); # system module: modules/nixos/agent.nix nixLd = system.programs.nix-ld.enable;