Skip to content

[go-fan] Go Module Review: github.com/cli/go-gh/v2 #67153

Description

@github-actions

Module Overview

github.com/cli/go-gh/v2 is GitHub's official Go module for talking to the GitHub REST/GraphQL APIs and gh config/auth the same way the gh CLI does. gh-aw uses it as the sole GitHub API client library across the CLI, workflow compiler, and parser.

Current Usage in gh-aw

  • Files: 14 non-test files import pkg/api (13) or pkg/repository (1)
  • Key APIs used: api.ClientOptions, api.NewRESTClient / api.DefaultRESTClient / api.NewGraphQLClient, (*RESTClient).DoWithContext (dominant pattern), api.HTTPError for typed status checks, repository.Current()
  • Central wrapper: pkg/githubapi/options.go builds shared ClientOptions; most call sites construct their own RESTClient from there.

Version pinned (v2.16.1) is already the latest release — no upgrade needed.

Research Findings

Recent releases (newest first):

  • v2.16.1 (2026-09-15): fixed HTTP cache entries written without in-place mutation; pkg/repository now honors the resolved remote.
  • v2.16.0: trusts the canonical host alongside the API host (relevant to GHES setups).
  • v2.15.0: added per-host APIHost override and a configurable CheckRedirect policy on ClientOptions.
  • v2.13.0: DoWithContext now handles HTTP 205 correctly; bumped to Go 1.25.
  • v2.12.1: security fix GHSA-g9f5-x53j-h563 (arbitrary local file execution via attacker-controlled GHES browse URLs) — already covered since gh-aw pins v2.16.1.

Best practice from the source (pkg/api/rest_client.go): Get/Post/Patch/Put/Delete are thin wrappers that always call Do → DoWithContext(context.Background(), ...). They silently drop caller cancellation/deadlines. DoWithContext/RequestWithContext are the recommended entry points whenever a context is available.

Improvement Opportunities

🏃 Quick Wins

Three call sites still use the context-less REST helpers instead of DoWithContext:

  • pkg/cli/secret_set_command.go:234 — client.Get(path, &key)
  • pkg/cli/bootstrap_profile_actions_repo.go:210 — client.Post(...)
  • pkg/cli/bootstrap_profile_actions_repo.go:218 — client.Get(...)

These are the only go-gh call sites in the codebase that don't propagate a context.Context, so they can't be cancelled on process interrupt/timeout — inconsistent with every other go-gh call site, and with this repo's own httpnoctx custom linter, which flags exactly this anti-pattern for raw http.Client. Fixing this means threading a ctx through setRepoSecret/getRepoPublicKey and the bootstrap label helpers — a small, contained refactor rather than a one-liner.

✨ Feature Opportunities

  • ClientOptions.CheckRedirect (added in v2.15.0) is unused anywhere in gh-aw. Worth keeping in mind for remote_resolve_sha.go / remote_download_file.go, which deal with GHES/public-GitHub fallbacks where redirect-sensitive semantics (e.g. a DELETE silently becoming a GET after a 301) could matter — not an active bug today, just a lever available if redirect edge cases are ever reported.
  • ClientOptions.EnableCache/CacheTTL is only applied in repository_features_validation.go. update_check.go / update_cooldown.go hit the GitHub releases API on every invocation; a short-lived cache (mirroring repositoryFeaturesCacheTTL) could shave redundant calls in CI runs that invoke gh aw multiple times — marginal benefit since these are typically single-shot per process.

📐 Best Practice Alignment

The overwhelming majority of call sites already do the right thing:

  • Context-bound DoWithContext everywhere except the 3 sites above.
  • Typed *api.HTTPError status checks (bootstrap_profile_actions_repo.go, remote_resolve_sha.go) instead of string-matching errors.
  • A deliberate two-layer caching strategy in repository_features_validation.go: go-gh's disk-backed EnableCache/CacheTTL (persists across separate CLI invocations in the same CI workflow) layered under an in-process sync.Map/sync.Once cache — this is a well above-average use of a go-gh feature most consumers skip entirely.

🔧 General Improvements

None found beyond the quick win above — the module is used narrowly (REST client + one repository.Current() call) and idiomatically. No custom HTTP-client code was found duplicating go-gh functionality.

Recommendations

  1. Thread context.Context through the secret-set and bootstrap-label helper chains so the 3 remaining client.Get/client.Post call sites can switch to DoWithContext.
  2. No version bump or other action needed — v2.16.1 is current and the security advisory is already covered.

Next Steps

  • Optional follow-up PR for the context-propagation refactor above (low urgency, consistency-only — these are short-lived, low-frequency calls during gh aw secret set / repo bootstrap).

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

Generated by 🐹 Go Fan · claude · agent · 319.6 AIC · ⊞ 6.4K · ◷

  • expires on Oct 10, 2026, 12:10 AM UTC-08:00

Activity

  1. github-actions commented on Oct 10, 2026

    @github-actions
    ContributorAuthor

    This issue was automatically closed because it expired on 2026-10-10T08:10:47.910Z.

    Closed by Workflow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions