Files
diple/auth.go
2026-07-27 14:04:08 +02:00

67 lines
1.9 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"net/url"
"os"
"os/exec"
"strings"
"time"
)
type commandRunner func(context.Context, string, ...string) ([]byte, error)
func resolveToken(endpoint string) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
return resolveTokenWith(ctx, endpoint, os.Getenv, runCommand)
}
func resolveTokenWith(ctx context.Context, endpoint string, getenv func(string) string, run commandRunner) (string, error) {
if token := firstNonEmpty(
getenv("GH_TOKEN"),
getenv("GITHUB_TOKEN"),
getenv("GH_ENTERPRISE_TOKEN"),
getenv("GITHUB_ENTERPRISE_TOKEN"),
); token != "" {
return token, nil
}
host, err := githubHost(endpoint)
if err != nil {
return "", err
}
output, err := run(ctx, "gh", "auth", "token", "--hostname", host)
if err != nil {
if errors.Is(err, exec.ErrNotFound) {
return "", errors.New("no environment token found and gh is not installed; install gh and run `gh auth login`, or set GH_TOKEN")
}
if ctx.Err() != nil {
return "", fmt.Errorf("read authentication from gh: %w", ctx.Err())
}
return "", fmt.Errorf("no usable authentication for %s; run `gh auth login --hostname %s`, or set GH_TOKEN: %w", host, host, err)
}
token := strings.TrimSpace(string(output))
if token == "" {
return "", fmt.Errorf("gh returned an empty token for %s; run `gh auth login --hostname %s`", host, host)
}
return token, nil
}
func githubHost(endpoint string) (string, error) {
parsed, err := url.Parse(endpoint)
if err != nil || parsed.Scheme == "" || parsed.Hostname() == "" {
return "", fmt.Errorf("invalid GitHub GraphQL endpoint %q", endpoint)
}
if parsed.Hostname() == "api.github.com" {
return "github.com", nil
}
return parsed.Hostname(), nil
}
func runCommand(ctx context.Context, name string, args ...string) ([]byte, error) {
return exec.CommandContext(ctx, name, args...).Output()
}