Skip to content

[go-fan] Go Module Review: go-ghΒ #50822

Description

@github-actions

🐹 Go Fan Report: cli/go-gh (v2)

Module Overview

github.com/cli/go-gh/v2 is GitHub's official Go module for building gh CLI extensions and tools that talk to GitHub. gh-aw uses it exclusively for its native pkg/api REST/GraphQL clients β€” it never shells out to the gh binary for API calls, which is the right call for a compiled Go tool (no external binary dependency, native context.Context cancellation).

Current Usage in gh-aw

  • Files: 11 non-test files (pkg/cli/*, pkg/workflow/repository_features_validation.go, pkg/parser/remote_*, pkg/githubapi/options.go)
  • Key APIs Used: api.NewRESTClient, api.DefaultRESTClient, api.DefaultGraphQLClient, api.ClientOptions{Host, AuthToken, Timeout}, client.DoWithContext(...)
  • A shared helper (pkg/githubapi.ClientOptions) centralizes client construction; call sites each build their own client and issue a single DoWithContext call wrapped in a caller-supplied context.WithTimeout.

Research Findings

  • Currently on v2.13.0, which is the latest released version (2025-11-04) β€” already up to date, no action needed there.
  • go-gh ships a built-in disk-backed HTTP response cache (api.ClientOptions{EnableCache, CacheDir, CacheTTL}, default TTL 24h) implemented transparently as an http.RoundTripper. It caches GETs and also GraphQL POSTs to /graphql//api/graphql.
  • go-gh also auto-honors GH_DEBUG=api for verbose request/response logging to stderr, with no extra wiring needed by the caller.

Recent Updates

No breaking changes between the currently-pinned v2.13.0 and prior v2.12.x releases that affect gh-aw's usage patterns.

Best Practices

  • Use DoWithContext with an explicit timeout context rather than the context-less Do β€” gh-aw already does this consistently. βœ…
  • Only skip go-gh's auto-auth-token resolution (empty AuthToken) when unauthenticated access is genuinely required β€” gh-aw does this correctly and intentionally in pkg/parser/remote_client.go's public-contents fallback, with a comment explaining why a hand-rolled http.Client is used instead of api.RESTClient there (avoiding go-gh's automatic fallback to the stored gh OAuth token when an enterprise SAML-enforced token can't reach a public cross-org repo). βœ…

Improvement Opportunities

πŸƒ Quick Wins

None required for correctness β€” usage already matches the current API surface and go-gh's own idioms.

✨ Feature Opportunities

  • Persist the repository-features cache across process invocations using go-gh's built-in disk cache. pkg/workflow/repository_features_validation.go hand-rolls an in-process sync.Map cache (repositoryFeaturesCache) for "does this repo have discussions/issues enabled" lookups. That cache only lives for a single process's lifetime, so every fresh gh-aw CLI invocation (e.g. repeated runs in the same CI workflow) re-queries the GitHub API for the same, rarely-changing repo settings. Passing EnableCache: true, CacheTTL: <a few minutes> when constructing the REST/GraphQL clients used here would let go-gh persist results to disk across invocations, cutting redundant API calls and rate-limit usage, while the existing sync.Map can stay as a same-process fast path on top.
  • Document GH_DEBUG=api for troubleshooting. Since none of gh-aw's client constructions set Log, go-gh already supports verbose HTTP logging via this env var for free β€” worth a mention in contributor/debugging docs instead of reaching for custom instrumentation when diagnosing API issues.

πŸ“ Best Practice Alignment

  • Minor inconsistency worth double-checking: some call sites use api.DefaultRESTClient()/api.DefaultGraphQLClient() (zero-value options β€” no client-level timeout at all), relying entirely on the caller's context.WithTimeout to bound request duration, while others pass an explicit Timeout via ClientOptions. All reviewed call sites do wrap these in a timeout context correctly, but since there's no client-level fallback timeout, any future call site added without one would hang indefinitely on a slow/unresponsive host.

πŸ”§ General Improvements

  • Worth a follow-up check on whether repository.Current() (go-gh's git-remote-aware, GH_REPO-respecting repo resolver) could replace any bespoke "parse repo from git remote" logic elsewhere in the codebase β€” not confirmed as present in this review's scope.

Recommendations

  1. Consider enabling go-gh's disk cache (EnableCache/CacheTTL) for the repository-features REST/GraphQL clients to persist lookups across CLI invocations, not just within one process.
  2. No dependency upgrade needed β€” v2.13.0 is current.
  3. No correctness issues found; usage is idiomatic and well-commented where it deliberately diverges from go-gh defaults.

Next Steps

  • Evaluate a short CacheTTL (e.g. 5–10 minutes) for the repository-features clients and measure API-call reduction in CI-heavy repos.
  • Add a short debugging note about GH_DEBUG=api to contributor docs.

Generated by Go Fan
Module summary saved to: scratchpad/mods/go-gh.md

Generated by 🐹 Go Fan Β· agent Β· 138.4 AIC Β· βŒ– 32.3 AIC Β· ⊞ 7.5K Β· β—·

  • expires on Aug 7, 2026, 12:59 AM UTC-08:00

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions