Open-Source Wikis

/

GitHub CLI

/

Systems

/

Feature detection

cli/cli

Feature detection

Active contributors: Mislav, William Martin, Sam Coe

Purpose

gh runs against github.com, GitHub Enterprise Cloud, and GitHub Enterprise Server. GHES versions trail the public API by months. To avoid hard-coding host checks, the CLI probes the GraphQL schema at runtime to ask "is feature X available?" and lets each command branch accordingly.

Directory layout

internal/featuredetection/
  feature_detection.go      # ~16 KB: detector implementation
  feature_detection_test.go # ~21 KB
  detector_mock.go          # moq mock for tests

Key abstractions

Symbol File Role
Detector interface feature_detection.go Returns capability flags by name.
IssueFeatures, PullRequestFeatures, RepositoryFeatures, OrganizationFeatures, ProjectsV2Features, ActorsFeatures feature_detection.go Per-domain capability bundles.
NewDetector feature_detection.go Builds a detector backed by an api.Client.
DetectorMock detector_mock.go Lets tests assert against requested capabilities without doing a real probe.

How it works

Each detection issues a small GraphQL introspection query asking whether a particular field, type, or argument exists in the connected schema. The result is cached per detector instance.

The pattern in command code is rigid:

features, err := opts.Detector.IssueFeatures()
if err != nil {
    return err
}

// TODO ApiActorsSupported
if features.ApiActorsSupported {
    // new query path
} else {
    // GHES fallback
}

The // TODO <cleanupIdentifier> comment is required by a custom forbidigo lint rule. It makes it a one-grep job to find every code path that needs to be deleted once a particular GHES version goes EOL. The // TODO does not need to point at a real ticket; it is a marker, not a debt.

Integration points

  • Detectors are typically created inside the run function with featuredetection.NewDetector(httpClient, hostname) and used immediately.
  • Tests substitute detector_mock.go and assert the expected subset of features was queried.
  • Cleanup IDs are listed in commit messages and PR descriptions when a code path is being retired.

Entry points for modification

  • New capability: add a field to the relevant Features struct in feature_detection.go, write the introspection query, add // TODO <cleanupIdentifier> to every consumer, update the mock.
  • Retiring a capability: grep for the cleanup identifier and remove the branches plus the field. Keep the cleanup grouped in a single PR per identifier.

Key source files

File Purpose
internal/featuredetection/feature_detection.go Detector + features.
internal/featuredetection/detector_mock.go Mock.
internal/featuredetection/feature_detection_test.go Tests.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Feature detection – GitHub CLI wiki | Factory