Skip to content

Add support for reading issue field values - #14130

Draft
iulia-b wants to merge 2 commits into
cli:trunkfrom
iulia-b:issue-fields/read-field-values
Draft

Add support for reading issue field values#14130
iulia-b wants to merge 2 commits into
cli:trunkfrom
iulia-b:issue-fields/read-field-values

Conversation

@iulia-b

@iulia-b iulia-b commented Aug 11, 2026

Copy link
Copy Markdown

Related to https://github.com/github/issues/issues/21241
Design: https://github.com/github/gh-cli-and-desktop/issues/273

Description

Issue fields are not currently available when reading issues through gh, and there is no command for discovering the issue fields defined for a repository.

This adds read-only issue-field support for text, number, date, single-select, and multi-select values. gh issue view renders field values in terminal output, while gh issue view --json issueFields and gh issue list --json issueFields return normalized JSON. It also adds gh issue field list, including table output and --json id,name,dataType,options, with pagination over repository field definitions.

Default issue views use feature detection before requesting issue fields so older GHES instances continue to work. Issue fields remain issue-only and are filtered from pull request field lists and GraphQL queries.

How did you test this change?

image image image

Key points

This PR is intentionally read-only. Setting and clearing field values will be handled separately. Repository field definitions are fully paginated; values attached to an individual issue currently use the API's first 100 values. Explicit field discovery and --json issueFields requests surface API errors on unsupported hosts, while the default terminal view is compatibility-gated because it is not opt-in.

Notes for reviewers

Start with api/query_builder.go and api/queries_issue.go for the GraphQL and normalized value model, then pkg/cmd/issue/view/view.go and pkg/cmd/issue/field/list/list.go for the user-facing behavior. The tracking issue and design proposal linked above describe the broader create/edit work that is deliberately outside this PR.

Authorship and follow-up

Who wrote this:

  • A human wrote it.
  • An agent wrote it under close human direction.
  • An agent wrote it independently, and no human has guided the implementation beyond the initial prompt.

Who answers review comments:

  • @iulia-b will read and reply directly. Name the account.
  • An agent will draft replies and @username will read them before they are posted.
  • Nobody has explicitly committed to replying.

Copilot AI balanced review requested due to automatic review settings August 11, 2026 11:46
@github-actions github-actions Bot added external pull request originating outside of the CLI core team needs-triage needs to be reviewed labels Aug 11, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds read-only custom issue-field support across API queries, issue commands, JSON export, and terminal rendering.

Changes:

  • Queries and normalizes issue field definitions and values.
  • Adds gh issue field list.
  • Adds feature detection and test coverage for view/list behavior.
Show a summary per file
File Description
api/export_pr.go Exports normalized issue fields.
api/export_pr_test.go Tests field-value export.
api/issue_fields.go Fetches paginated field definitions.
api/issue_fields_test.go Tests definition pagination.
api/queries_issue.go Defines issue-field models.
api/query_builder.go Builds field-value queries.
api/query_builder_test.go Tests query generation.
internal/featuredetection/feature_detection.go Detects API support.
internal/featuredetection/feature_detection_test.go Tests detection.
pkg/cmd/issue/field/field.go Adds the field command group.
pkg/cmd/issue/field/list/list.go Implements field listing.
pkg/cmd/issue/field/list/list_test.go Tests list output.
pkg/cmd/issue/issue.go Registers the command.
pkg/cmd/issue/list/http_test.go Tests issue-list queries.
pkg/cmd/issue/view/view.go Renders field values.
pkg/cmd/issue/view/view_test.go Tests view and JSON output.

Review details

Tip

Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 16/16 changed files
  • Comments generated: 6
  • Review effort level: Balanced

Comment thread api/issue_fields.go
IssueFields issueFieldDefinitionConnection
}
}
if err := client.GraphQL(repo.RepoHost(), query, variables, &result); err != nil {
Comment thread api/query_builder.go
Comment thread api/issue_fields.go Outdated
Comment thread api/queries_issue.go Outdated
Comment thread pkg/cmd/issue/view/view.go
Comment thread pkg/cmd/issue/field/list/list.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (3)

api/issue_fields.go:27

  • 🛑 Requirement: Enable the Issue Fields GraphQL preview for field discovery

This repository-field query also uses the public-preview schema, but the shared API client currently sends only the merge_queue GraphQL feature (api/client.go:23,59). Without GraphQL-Features: issue_fields, gh issue field list will fail against the live API even though the mocked response succeeds. Add the preview feature to the shared GraphQL header and assert it in the request test.

	query RepositoryIssueFields($owner: String!, $name: String!, $endCursor: String) {
		repository(owner: $owner, name: $name) {
			issueFields(first: 100, after: $endCursor) {

internal/featuredetection/feature_detection.go:209

  • 🛑 Requirement: Keep issue feature detection to one API round trip

Every GHES call to IssueFeatures now launches a second introspection request, affecting unrelated existing flows such as issue create/edit and PR create. This violates the repository's “avoid extra round-trips” API rule and makes those commands fail if either request fails. Add the two aliased __type selections to the existing featureDetection struct and resolve all flags from one Query call instead.

	wg.Go(func() error {
		return gql.Query(d.host, "Issue_fields", &featureDetection, nil)
	})
	wg.Go(func() error {
		return gql.Query(d.host, "Issue_field_types", &issueFieldFeatureDetection, nil)

pkg/cmd/issue/view/view.go:140

  • 💭 Commentary: Avoid fetching values that the non-TTY renderer discards

This branch runs for both TTY and redirected output, but printRawIssuePreview never emits issue fields. As a result, scripted/default non-TTY views request up to 100 extra values and take on another API failure mode without any user-visible result. Gate this lookup on IsStdoutTTY() (or deliberately add a documented raw-output contract, which would be breaking).

			if issueFeatures.IssueFieldsSupported {
  • Files reviewed: 16/16 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread api/query_builder.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (2)

pkg/cmd/issue/view/view.go:136

  • 🛑 Requirement: Keep the cleanup marker directly above the feature-gated branch

The repository feature-detection convention requires the cleanup TODO immediately above the if that tests the capability (AGENTS.md:161-172). This refactor leaves IssueRelationshipsCleanup above the detector call instead, so move it onto this branch.

			if issueFeatures.IssueRelationshipsSupported {

internal/featuredetection/feature_detection.go:208

  • 🛑 Requirement: Fold these type checks into the existing introspection request

Every IssueFeatures call on GHES now makes two HTTP requests, including commands such as issue/PR create and edit that already depend on this detector. This violates the repository's “Avoid extra round-trips” API rule (AGENTS.md:176-186). Add these two aliased __type selections to featureDetection and run one gql.Query instead; concurrency only hides latency and does not remove the extra server/cache load.

	var wg errgroup.Group
	wg.Go(func() error {
		return gql.Query(d.host, "Issue_fields", &featureDetection, nil)
	})
	wg.Go(func() error {
  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

scottlaird added a commit to scottlaird/roz that referenced this pull request Aug 12, 2026
The other half of #99. The library could answer the question; nothing could
supply it with a real change. Now roz codeowners --pr does the whole thing in
one command.

github.Change fetches three things: the paths a pull request touches, the
CODEOWNERS governing them, and who has already approved. The approvals matter
as much as the files -- the useful question is what is left, and having to look
that up separately and type it back in is most of the friction.

CODEOWNERS is read from the base ref, not the default branch, because a change
into a release branch is governed by that branch's rules. That is why it is two
round trips: the base ref is not known until the pull request has been read.
The three locations GitHub looks in are tried as three aliases in one query,
since a repository has at most one of them.

The file list is paginated to completion. A partial list could turn "no single
owner covers this" into "one does", and being wrong in that direction is worse
than being slow.

Deliberately not part of the batched poll, which is what #99 assumed and is
right for a different reason than it gives: the cost is not that it cannot be
batched, it is that the file list is large, changes only when someone pushes,
and is wanted when a person asks a question rather than every minute.

Verified against cli/cli#14130: sixteen files, rules read from
.github/CODEOWNERS@trunk, one team covering all of it.

Say plainly when no rule matches any file, rather than reporting that no
single owner covers everything. Found running this against elasticsearch,
whose CODEOWNERS covers eighty specific paths in a very large repository, so
most changes match nothing: the old wording read as a problem and sat beside a
contradictory "nothing outstanding".
@Hasim-hannover

Copy link
Copy Markdown

OK

rranjan14 added a commit to rranjan14/diffident that referenced this pull request Aug 18, 2026
Matches tuicr, which takes the pull request as a subcommand argument
rather than a flag -- it is the object you are acting on, not a modifier
on some other action.

`<target>` accepts the three forms people actually have in hand:

  diffident pr 123
  diffident pr cli/cli#13758
  diffident pr cli/cli#13758

The last two carry their own repo, which is the point: pasting a URL
should not also require saying which repository it came from. URLs still
parse with whatever GitHub appends as you click around -- /files,
#discussion_r123, ?w=1. A bare number uses the checkout you are in.

`--repo` still overrides, because a flag is a statement where a target's
repo is only an inference. `--repo`/`--pr` keep working unchanged.

473 tests, clippy clean. All three forms verified against real pull
requests: cli/cli#13758 by URL, cli/cli#14130 by slug, and #89 by bare
number in this checkout.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external pull request originating outside of the CLI core team needs-triage needs to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants