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.
|
# from `userName` to keep them coupled.
|
||||||
userName = config.hyperhive.user.name;
|
userName = config.hyperhive.user.name;
|
||||||
homeDir = "/home/${userName}";
|
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
|
# Hive-wide OpenTelemetry config (host-driven; baked in per-agent by
|
||||||
# meta.rs `otel_config`).
|
# meta.rs `otel_config`).
|
||||||
otelCfg = config.hyperhive.otel;
|
otelCfg = config.hyperhive.otel;
|
||||||
|
|
@ -1558,6 +1579,15 @@ in
|
||||||
# regardless of which profile files are sourced.
|
# regardless of which profile files are sourced.
|
||||||
NIX_REMOTE = "daemon";
|
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) {
|
// lib.optionalAttrs (!config.hyperhive.autoCompact) {
|
||||||
# Zero watermark disables proactive compaction; the reactive path
|
# Zero watermark disables proactive compaction; the reactive path
|
||||||
# (compact-on-overflow) still fires when the session is truly full.
|
# (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.
|
# we have to allow it inside the container's config as well.
|
||||||
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ "claude-code" ];
|
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ "claude-code" ];
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages =
|
||||||
hyperhive
|
with pkgs;
|
||||||
claude-code
|
[
|
||||||
bashInteractive
|
hyperhive
|
||||||
coreutils-full
|
claude-code
|
||||||
# procps for pkill — used by the web UI's /api/cancel to SIGINT the
|
bashInteractive
|
||||||
# in-flight claude turn.
|
coreutils-full
|
||||||
procps
|
# procps for pkill — used by the web UI's /api/cancel to SIGINT the
|
||||||
# tea: gitea/forgejo CLI client. Configured at boot by the
|
# in-flight claude turn.
|
||||||
# tea-login oneshot below if /state/forge-token is present, so
|
procps
|
||||||
# claude can `tea repos create`, `tea pulls create`, etc.
|
# tea: gitea/forgejo CLI client. Configured at boot by the
|
||||||
tea
|
# tea-login oneshot below if /state/forge-token is present, so
|
||||||
# jq: JSON processing in shell — useful for parsing API responses,
|
# claude can `tea repos create`, `tea pulls create`, etc.
|
||||||
# forge REST calls, sqlite output, etc.
|
tea
|
||||||
jq
|
# jq: JSON processing in shell — useful for parsing API responses,
|
||||||
# curl: HTTP client for forge REST API and other web requests.
|
# forge REST calls, sqlite output, etc.
|
||||||
curl
|
jq
|
||||||
# hive-forge <verb>: CLI wrapping common Forgejo REST API operations
|
# curl: HTTP client for forge REST API and other web requests.
|
||||||
# (view, pr, issue, comment, assign, close, labels, branches, etc.)
|
curl
|
||||||
(pkgs.callPackage ../packages/hive-forge-tools.nix { })
|
# 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
|
# One-shot: tea config.yml from the seeded forge token. Shape
|
||||||
# contract (always exit 0, no set -e, skip-silently, re-runnable):
|
# contract (always exit 0, no set -e, skip-silently, re-runnable):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue