53 lines
1.5 KiB
Go
53 lines
1.5 KiB
Go
package github
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// TokenSource yields a GitHub bearer token on demand. It is intentionally
|
|
// tiny so tests can inject a static token and production can layer env-var or
|
|
// gh-CLI fallbacks behind the same surface. The Tracker calls Token once at
|
|
// construction (fail-fast) and again per request (so rotated tokens are
|
|
// picked up without restart).
|
|
type TokenSource interface {
|
|
Token(ctx context.Context) (string, error)
|
|
}
|
|
|
|
// ErrNoToken is returned when no token source could yield a non-empty token.
|
|
var ErrNoToken = errors.New("github tracker: no token configured")
|
|
|
|
// StaticTokenSource is a literal token, typically used in tests.
|
|
type StaticTokenSource string
|
|
|
|
func (s StaticTokenSource) Token(context.Context) (string, error) {
|
|
t := strings.TrimSpace(string(s))
|
|
if t == "" {
|
|
return "", ErrNoToken
|
|
}
|
|
return t, nil
|
|
}
|
|
|
|
// EnvTokenSource reads the first non-empty value from the listed env vars,
|
|
// falling back to GITHUB_TOKEN. The order matters: a project-configured
|
|
// token (e.g. AO_GITHUB_TOKEN) should be preferred over the global default,
|
|
// matching the pattern PR #28 uses on the SCM side so both adapters honor
|
|
// the same precedence.
|
|
type EnvTokenSource struct {
|
|
EnvVars []string
|
|
}
|
|
|
|
func (s EnvTokenSource) Token(context.Context) (string, error) {
|
|
for _, name := range s.EnvVars {
|
|
if v := strings.TrimSpace(os.Getenv(name)); v != "" {
|
|
return v, nil
|
|
}
|
|
}
|
|
if v := strings.TrimSpace(os.Getenv("GITHUB_TOKEN")); v != "" {
|
|
return v, nil
|
|
}
|
|
return "", ErrNoToken
|
|
}
|