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 testsKey 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.goand 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
Featuresstruct infeature_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. |
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.