fix: gh CLI setup on remote VMs — pass local token through (#1444)

Fixes GitHub CLI authentication on remote VMs by passing local token through to remote installation script. Uses printf '%q' for safe shell escaping to prevent command injection.
This commit is contained in:
A 2026-02-18 10:22:33 -08:00 committed by GitHub
parent 56fda1435a
commit ae4aa90bb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 40 additions and 8 deletions

View file

@ -500,7 +500,7 @@ describe("ensure_gh_auth", () => {
ensure_gh_auth 2>&1
`);
expect(result.exitCode).not.toBe(0);
expect(result.stdout + result.stderr).toContain("Failed to authenticate");
expect(result.stdout + result.stderr).toContain("authentication failed");
});
it("should fail when post-login auth status check fails", () => {

View file

@ -1233,6 +1233,13 @@ prompt_github_auth() {
choice=$(safe_read "Set up GitHub CLI (gh) on this machine? (y/N): ") || return 0
if [[ "${choice}" =~ ^[Yy]$ ]]; then
SPAWN_GITHUB_AUTH_REQUESTED=1
# Capture local GitHub token for passthrough to remote VM
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
SPAWN_GITHUB_TOKEN="${GITHUB_TOKEN}"
elif command -v gh &>/dev/null && gh auth status &>/dev/null 2>&1; then
SPAWN_GITHUB_TOKEN="$(gh auth token 2>/dev/null)" || true
fi
fi
}
@ -1248,11 +1255,19 @@ offer_github_auth() {
return 0
fi
# Build the remote command with optional token export
local gh_cmd="curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/shared/github-auth.sh | bash"
if [[ -n "${SPAWN_GITHUB_TOKEN:-}" ]]; then
local escaped_token
escaped_token=$(printf '%q' "${SPAWN_GITHUB_TOKEN}")
gh_cmd="export GITHUB_TOKEN=${escaped_token}; ${gh_cmd}"
fi
# If prompt_github_auth was already called, use its stored answer
if [[ "${SPAWN_GITHUB_AUTH_PROMPTED:-}" == "1" ]]; then
if [[ "${SPAWN_GITHUB_AUTH_REQUESTED:-}" == "1" ]]; then
log_step "Installing and authenticating GitHub CLI..."
${run_callback} "curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/shared/github-auth.sh | bash"
${run_callback} "${gh_cmd}"
fi
return 0
fi
@ -1265,8 +1280,22 @@ offer_github_auth() {
return 0
fi
# Attempt token capture in fallback path too
if [[ -z "${SPAWN_GITHUB_TOKEN:-}" ]]; then
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
SPAWN_GITHUB_TOKEN="${GITHUB_TOKEN}"
elif command -v gh &>/dev/null && gh auth status &>/dev/null 2>&1; then
SPAWN_GITHUB_TOKEN="$(gh auth token 2>/dev/null)" || true
fi
if [[ -n "${SPAWN_GITHUB_TOKEN:-}" ]]; then
local escaped_token
escaped_token=$(printf '%q' "${SPAWN_GITHUB_TOKEN}")
gh_cmd="export GITHUB_TOKEN=${escaped_token}; ${gh_cmd}"
fi
fi
log_step "Installing and authenticating GitHub CLI..."
${run_callback} "curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/shared/github-auth.sh | bash"
${run_callback} "${gh_cmd}"
}
# ============================================================

View file

@ -222,10 +222,12 @@ ensure_gh_auth() {
return 1
}
else
# Interactive: browser-based OAuth flow
log_step "Initiating GitHub CLI authentication..."
gh auth login || {
log_error "Failed to authenticate with GitHub CLI"
# Device code flow — works on headless/remote servers
# Shows a URL + code; user opens URL in local browser and enters the code
log_step "Authenticating via device code flow..."
log_info "A URL and code will appear below. Open the URL in your browser and enter the code."
gh auth login --web -p https -h github.com || {
log_error "GitHub authentication failed"
log_error "Run manually: gh auth login"
return 1
}
@ -254,7 +256,8 @@ ensure_github_auth() {
# ============================================================
# If executed directly (not sourced), run ensure_github_auth
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
# When piped via curl|bash, BASH_SOURCE[0] is empty and $0 is "bash"
if [[ "${BASH_SOURCE[0]}" == "${0}" ]] || [[ -z "${BASH_SOURCE[0]:-}" ]]; then
set -eo pipefail
ensure_github_auth
fi