wip(#1970): gh wrapper + git credential helper + gated env/gitconfig for githubAccount
This commit is contained in:
parent
303037689e
commit
5fb4b9f4b0
1 changed files with 74 additions and 21 deletions
|
|
@ -17,6 +17,27 @@ let
|
|||
# from `userName` to keep them coupled.
|
||||
userName = config.hyperhive.user.name;
|
||||
homeDir = "/home/${userName}";
|
||||
# GitHub account (hyperhive.githubAccount): a `gh` wrapper + a git
|
||||
# credential helper, both sourcing the PAT from HIVE_GITHUB_TOKEN_FILE at
|
||||
# invocation time so a dashboard-pasted token takes effect with no rebuild.
|
||||
# The scripts are static (they read env at runtime) — the account option
|
||||
# only gates whether they're installed + the env is set, so the token
|
||||
# value never enters the nix store.
|
||||
ghWrapper = pkgs.writeShellScriptBin "gh" ''
|
||||
if [ -n "''${HIVE_GITHUB_TOKEN_FILE:-}" ] && [ -r "''${HIVE_GITHUB_TOKEN_FILE}" ]; then
|
||||
GH_TOKEN="$(cat "''${HIVE_GITHUB_TOKEN_FILE}")"
|
||||
export GH_TOKEN
|
||||
fi
|
||||
exec ${pkgs.gh}/bin/gh "$@"
|
||||
'';
|
||||
gitCredHelper = pkgs.writeShellScriptBin "git-credential-hive-github" ''
|
||||
# git credential-helper protocol: only the `get` action needs an answer.
|
||||
[ "''${1:-}" = "get" ] || exit 0
|
||||
if [ -n "''${HIVE_GITHUB_TOKEN_FILE:-}" ] && [ -r "''${HIVE_GITHUB_TOKEN_FILE}" ]; then
|
||||
printf 'username=%s\n' "''${HIVE_GITHUB_USER:-x-access-token}"
|
||||
printf 'password=%s\n' "$(cat "''${HIVE_GITHUB_TOKEN_FILE}")"
|
||||
fi
|
||||
'';
|
||||
# Hive-wide OpenTelemetry config (host-driven; baked in per-agent by
|
||||
# meta.rs `otel_config`).
|
||||
otelCfg = config.hyperhive.otel;
|
||||
|
|
@ -1558,6 +1579,15 @@ in
|
|||
# regardless of which profile files are sourced.
|
||||
NIX_REMOTE = "daemon";
|
||||
}
|
||||
// lib.optionalAttrs (config.hyperhive.githubAccount != null) {
|
||||
# GitHub account: metadata + token-file PATH only, never the secret.
|
||||
# The `gh` wrapper + git credential helper read the PAT from the file
|
||||
# at invocation time (see hyperhive.githubAccount).
|
||||
HIVE_GITHUB_USER = config.hyperhive.githubAccount.username;
|
||||
HIVE_GITHUB_HOST = config.hyperhive.githubAccount.host;
|
||||
HIVE_GITHUB_TOKEN_FILE = config.hyperhive.githubAccount.tokenFile;
|
||||
GH_HOST = config.hyperhive.githubAccount.host;
|
||||
}
|
||||
// lib.optionalAttrs (!config.hyperhive.autoCompact) {
|
||||
# Zero watermark disables proactive compaction; the reactive path
|
||||
# (compact-on-overflow) still fires when the session is truly full.
|
||||
|
|
@ -1652,27 +1682,50 @@ in
|
|||
# we have to allow it inside the container's config as well.
|
||||
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ "claude-code" ];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
hyperhive
|
||||
claude-code
|
||||
bashInteractive
|
||||
coreutils-full
|
||||
# procps for pkill — used by the web UI's /api/cancel to SIGINT the
|
||||
# in-flight claude turn.
|
||||
procps
|
||||
# tea: gitea/forgejo CLI client. Configured at boot by the
|
||||
# tea-login oneshot below if /state/forge-token is present, so
|
||||
# claude can `tea repos create`, `tea pulls create`, etc.
|
||||
tea
|
||||
# jq: JSON processing in shell — useful for parsing API responses,
|
||||
# forge REST calls, sqlite output, etc.
|
||||
jq
|
||||
# curl: HTTP client for forge REST API and other web requests.
|
||||
curl
|
||||
# hive-forge <verb>: CLI wrapping common Forgejo REST API operations
|
||||
# (view, pr, issue, comment, assign, close, labels, branches, etc.)
|
||||
(pkgs.callPackage ../packages/hive-forge-tools.nix { })
|
||||
];
|
||||
environment.systemPackages =
|
||||
with pkgs;
|
||||
[
|
||||
hyperhive
|
||||
claude-code
|
||||
bashInteractive
|
||||
coreutils-full
|
||||
# procps for pkill — used by the web UI's /api/cancel to SIGINT the
|
||||
# in-flight claude turn.
|
||||
procps
|
||||
# tea: gitea/forgejo CLI client. Configured at boot by the
|
||||
# tea-login oneshot below if /state/forge-token is present, so
|
||||
# claude can `tea repos create`, `tea pulls create`, etc.
|
||||
tea
|
||||
# jq: JSON processing in shell — useful for parsing API responses,
|
||||
# forge REST calls, sqlite output, etc.
|
||||
jq
|
||||
# curl: HTTP client for forge REST API and other web requests.
|
||||
curl
|
||||
# hive-forge <verb>: CLI wrapping common Forgejo REST API operations
|
||||
# (view, pr, issue, comment, assign, close, labels, branches, etc.)
|
||||
(pkgs.callPackage ../packages/hive-forge-tools.nix { })
|
||||
]
|
||||
++ lib.optionals (config.hyperhive.githubAccount != null) [
|
||||
# gh wrapper + git credential helper for hyperhive.githubAccount.
|
||||
# (No bare pkgs.gh here — the wrapper *is* `gh` and hardcodes the real
|
||||
# binary path, so it can't be shadowed.)
|
||||
ghWrapper
|
||||
gitCredHelper
|
||||
];
|
||||
|
||||
# Wire the GitHub credential helper for `git push` over HTTPS to the
|
||||
# configured host. Host-scoped (github.com or a GHE host), so it never
|
||||
# touches the forge (localhost:3000) or any other remote. Gated on the
|
||||
# account; the helper reads the PAT from HIVE_GITHUB_TOKEN_FILE at
|
||||
# invocation (see hyperhive.githubAccount). System /etc/gitconfig merges
|
||||
# under the agent's ~/.gitconfig (safe.directory), so this is additive.
|
||||
environment.etc = lib.optionalAttrs (config.hyperhive.githubAccount != null) {
|
||||
"gitconfig".text = ''
|
||||
[credential "https://${config.hyperhive.githubAccount.host}"]
|
||||
helper = hive-github
|
||||
username = ${config.hyperhive.githubAccount.username}
|
||||
'';
|
||||
};
|
||||
|
||||
# One-shot: tea config.yml from the seeded forge token. Shape
|
||||
# contract (always exit 0, no set -e, skip-silently, re-runnable):
|
||||
|
|
|
|||
Loading…
Reference in a new issue