Skip to content

feat(tracker): zero-config GitHub auth via gh auth token fallback#44

Open
harshitsinghbhandari wants to merge 2 commits into
mainfrom
feat/tracker-github-auto-auth
Open

feat(tracker): zero-config GitHub auth via gh auth token fallback#44
harshitsinghbhandari wants to merge 2 commits into
mainfrom
feat/tracker-github-auto-auth

Conversation

@harshitsinghbhandari
Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #36. Closes the local-dev token-friction gap by adding a gh auth token fallback to EnvTokenSource — if the user has already run gh auth login, the adapter just works with no env var setup.

Lookup order (zero-config on a stock dev machine)

  1. Configured env vars (project-specific, e.g. AO_GITHUB_TOKEN)
  2. GITHUB_TOKEN
  3. gh auth token (new)
  4. else ErrNoToken

gh-CLI failures (binary missing, not authenticated, exec error) are intentionally swallowed and reported as ErrNoToken so callers see one uniform "configure a token" signal regardless of why no token was found.

Implementation notes

  • The gh shell-out is injectable via a new GH func(ctx) (string, error) field on EnvTokenSource. Production code leaves it nil and the default gh auth token exec is used; tests inject a fake to avoid shelling out.
  • New() now bounds the construction-time token probe with a 5s context deadline so a hung gh fallback (broken PATH, etc.) cannot stall daemon startup.
  • Doc.go gets a short "Zero-config auth" section explaining the chain.

Tests

5 new table-driven cases in TestEnvTokenSource:

  • configured env var wins (GH not called)
  • GITHUB_TOKEN used when configured env empty (GH not called)
  • gh fallback used when env empty
  • gh fallback error swallowed → ErrNoToken (NOT propagated)
  • gh fallback empty stdout falls through → ErrNoToken

go test -race ./internal/adapters/tracker/github/55 pass, full backend suite 305 pass, go vet + gofmt clean.

Related

🤖 Generated with Claude Code

harshitsinghbhandari and others added 2 commits May 31, 2026 00:07
The merged adapter required an env var (AO_GITHUB_TOKEN or GITHUB_TOKEN)
even when the user already had `gh auth login` set up. That's friction
for the common local-dev case.

EnvTokenSource now falls through to `gh auth token` after the configured
env vars and GITHUB_TOKEN. If gh isn't installed or isn't logged in, the
exec error is swallowed and ErrNoToken is returned — callers see one
uniform "configure a token" signal regardless of why no token was found.

The gh shell-out is injectable via a new GH func field for testing; the
default real-exec is used when nil. The New() construction-time probe is
also bounded by a 5s deadline so a hung gh fallback (broken PATH, etc.)
cannot stall daemon startup.

Adds 5 table-driven tests covering: configured env wins, GITHUB_TOKEN
fallback, gh fallback path, gh error swallowed to ErrNoToken, and gh
empty stdout falls through. go test -race + go vet + gofmt clean. Full
backend suite green (305 pass).

Same pattern is being added to the GitLab adapter (aa-28 in flight). No
equivalent CLI for Linear (aa-29) — that one stays env-var only.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Five fixes from the second review pass on PR #44.

1. Wrap gh runtime errors under ErrNoToken instead of swallowing them.
   gh's stderr ("not logged in to any GitHub hosts. Try `gh auth login`")
   now flows into the surfaced error message so daemon operators can see
   WHY zero-config auth fell through, not just THAT it did.
   errors.Is(err, ErrNoToken) still holds.

2. Exclude exec.ErrNotFound from the wrap — "user doesn't have gh
   installed" is uninteresting noise; bare ErrNoToken is the right shape.

3. Capture gh's stderr via cmd.Stderr = & builder before .Output() so the
   ExitError carries the human-readable cause that we then wrap into the
   ErrNoToken result.

4. Name the 5s probe deadline as bootTokenProbeTimeout — magic numbers
   get a story.

5. Add TestNewBoundsTokenProbe pinning the deadline. Stub TokenSource
   blocks until ctx is cancelled; New() must return within 4-8s. CI-safe
   margin. Cheap insurance for the one defensive property in this PR.

Also: tightened the env-restore comment in TestEnvTokenSource to explain
why both t.Setenv and manual save/restore are present (subtests call
os.Unsetenv which t.Setenv can't restore).

Tests: 57 in package with -race, 307 full suite green. vet + gofmt clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant