fix(issue): avoid fetching unnecessary fields for discovery#12884
fix(issue): avoid fetching unnecessary fields for discovery#12884williammartin merged 7 commits intotrunkfrom
Conversation
Add a new IssueRepoInfo function that fetches only the fields needed for issue creation (id, name, owner, hasIssuesEnabled, viewerPermission), avoiding defaultBranchRef and other fields that require Contents:Read. Also add StubIssueRepoInfoResponse helper to httpmock for testing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add success, not-found, and edge case tests for both GitHubRepo and IssueRepoInfo, covering field population, parent repo handling, viewer permission checks, and issues-disabled scenarios. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… permission Switch issue create from GitHubRepo to IssueRepoInfo so that gh issue create works with fine-grained PATs that only have Issues:Write and Metadata:Read permissions. Fixes #12798 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update test mocks to match the renamed GraphQL query used by IssueRepoInfo, and switch to StubIssueRepoInfoResponse helper. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…sues Only the destination repo ID is needed for issue transfer. Switch from GitHubRepo to IssueRepoInfo to use minimal fields appropriate for issues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes #12798 where gh issue create fails with fine-grained PATs that have Issues:Write but not Contents:Read permissions. The root cause was that GitHubRepo fetches defaultBranchRef and merge-strategy fields via GraphQL, which require Contents:Read. The fix introduces a minimal IssueRepoInfo function that only fetches the fields actually needed for issue operations (id, name, owner, hasIssuesEnabled, viewerPermission).
Changes:
- Added new
IssueRepoInfoAPI function inapi/queries_repo.gowith a narrower GraphQL query (IssueRepositoryInfo) that avoids permission-sensitive fields. - Switched
issue createandissue transferfromapi.GitHubRepotoapi.IssueRepoInfo. - Updated all test stubs to match the new query name and added unit tests for the new function, plus a
StubIssueRepoInfoResponsetest helper.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| api/queries_repo.go | New IssueRepoInfo function with minimal GraphQL query |
| api/queries_repo_test.go | Tests for IssueRepoInfo (not found, success, issues disabled) and improved GitHubRepo tests |
| pkg/cmd/issue/create/create.go | Swap GitHubRepo → IssueRepoInfo |
| pkg/cmd/issue/create/create_test.go | Update mock query names and stub helpers |
| pkg/cmd/issue/transfer/transfer.go | Swap GitHubRepo → IssueRepoInfo |
| pkg/cmd/issue/transfer/transfer_test.go | Update mock query name |
| pkg/httpmock/legacy.go | New StubIssueRepoInfoResponse helper |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
williammartin
left a comment
There was a problem hiding this comment.
Passes all the issue acceptance tests (after I rebased on main):
➜ pr-12884 git:(babakks/use-min-discovery-fields-for-issue-create) GH_ACCEPTANCE_HOST=github.com GH_ACCEPTANCE_ORG=gh-acceptance-testing GH_ACCEPTANCE_TOKEN=$(gh auth token) go test -tags=acceptance -run ^TestIssues$ ./acceptance
ok github.com/cli/cli/v2/acceptance 24.048s
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [cli/cli](https://github.com/cli/cli) | minor | `v2.88.1` → `v2.89.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>cli/cli (cli/cli)</summary> ### [`v2.89.0`](https://github.com/cli/cli/releases/tag/v2.89.0): GitHub CLI 2.89.0 [Compare Source](cli/cli@v2.88.1...v2.89.0) ####`gh agent-task` now works on ghe.com tenancies `gh agent-task` commands previously failed with `401 Unauthorized` for users on ghe.com tenancy hosts because the Copilot API URL was hardcoded. The URL is now resolved dynamically per host, so `gh agent-task` works correctly regardless of your GitHub hosting environment. #### Experimental new prompter A new TUI-based prompter powered by [charmbracelet/huh](https://github.com/charmbracelet/huh) is available behind the `GH_EXPERIMENTAL_PROMPTER` environment variable. This is an early preview — try it out and share feedback! ``` export GH_EXPERIMENTAL_PROMPTER=1 ``` #### `gh issue create` and `gh issue transfer` no longer require extra token scopes `gh issue create` and `gh issue transfer` previously fetched repository fields they didn't need, which could require additional token scopes. These commands now fetch only the minimal fields necessary for issue operations. #### What's Changed ##### ✨ Features - `gh pr create`, `gh issue create`, `gh issue edit`: search-based assignee selection and login-based mutation on github.com by [@​BagToad](https://github.com/BagToad) in [#​13009](cli/cli#13009) - Add experimental huh-only prompter gated by `GH_EXPERIMENTAL_PROMPTER` by [@​BagToad](https://github.com/BagToad) in [#​12859](cli/cli#12859) ##### 🐛 Fixes - fix(agent-task): resolve Copilot API URL dynamically for ghe.com tenancies by [@​BagToad](https://github.com/BagToad) in [#​12956](cli/cli#12956) - fix(issue): avoid fetching unnecessary fields in `issue create` and `issue transfer` by [@​babakks](https://github.com/babakks) in [#​12884](cli/cli#12884) - fix: resolve data race in codespaces port forwarder by [@​Lslightly](https://github.com/Lslightly) in [#​13033](cli/cli#13033) ##### 📚 Docs & Chores - Record agentic invocations in User-Agent header by [@​williammartin](https://github.com/williammartin) in [#​13023](cli/cli#13023) - docs: clarify that `gh pr edit --add-reviewer` can re-request reviews by [@​joshjohanning](https://github.com/joshjohanning) in [#​13021](cli/cli#13021) - Add AGENTS.md by [@​williammartin](https://github.com/williammartin) in [#​13024](cli/cli#13024) - Fix typo: remove extra space in README.md link by [@​realMelTuc](https://github.com/realMelTuc) in [#​12725](cli/cli#12725) - Align triage.md with current triage process by [@​tidy-dev](https://github.com/tidy-dev) in [#​13030](cli/cli#13030) - Remove auto-labels from issue templates by [@​tidy-dev](https://github.com/tidy-dev) in [#​12972](cli/cli#12972) - Consolidate actor-mode signals into `ApiActorsSupported` by [@​BagToad](https://github.com/BagToad) in [#​13025](cli/cli#13025) - Fix acceptance test failures: git identity, headRepository JSON, obsolete traversal test by [@​BagToad](https://github.com/BagToad) in [#​13037](cli/cli#13037) #####
Dependencies - chore(deps): bump google.golang.org/grpc from 1.79.2 to 1.79.3 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​12963](cli/cli#12963) - chore(deps): bump github.com/google/go-containerregistry from 0.20.7 to 0.21.3 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​12962](cli/cli#12962) - chore(deps): bump github.com/zalando/go-keyring from 0.2.6 to 0.2.8 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13031](cli/cli#13031) - chore(deps): bump microsoft/setup-msbuild from 2.0.0 to 3.0.0 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13005](cli/cli#13005) - chore(deps): bump mislav/bump-homebrew-formula-action from 3.6 to 4.1 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13004](cli/cli#13004) - chore(deps): bump azure/login from 2.3.0 to 3.0.0 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​12951](cli/cli#12951) #### New Contributors - [@​joshjohanning](https://github.com/joshjohanning) made their first contribution in [#​13021](cli/cli#13021) - [@​realMelTuc](https://github.com/realMelTuc) made their first contribution in [#​12725](cli/cli#12725) - [@​Lslightly](https://github.com/Lslightly) made their first contribution in [#​13033](cli/cli#13033) **Full Changelog**: [v2.88.1...v2.89.0](cli/cli@v2.88.1...v2.89.0) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My45MS40IiwidXBkYXRlZEluVmVyIjoiNDMuOTEuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
Fixes #12798
Add a new
IssueRepoInfoAPI function that fetches only the minimal fields needed for issue operations (id,name,owner,hasIssuesEnabled,viewerPermission), and switch bothissue createandissue transferto use it instead ofGitHubRepo, which also fetchesdefaultBranchRefand merge-strategy fields that require additional token permissions beyond what issue commands need.Review notes
Most of the changes in this PR are test stub updates — switching mock query names from
RepositoryInfotoIssueRepositoryInfoand using the newStubIssueRepoInfoResponsehelper. The core logic change is minimal: a newIssueRepoInfofunction inapi/queries_repo.goand a one-line swap in each ofissue createandissue transfer. Each test stub was individually reviewed to confirm the response body only contains fields withinIssueRepoInfo's scope and no adjustments beyond the query name were needed.Alternative approach (#12873)
An alternative fix in #12873 uses
FetchRepositorywith onlyhasIssuesEnabled, but this missesid(needed by theIssueCreatemutation forrepositoryId) andviewerPermission(needed byViewerCanTriage()to decide whether to show the metadata prompt in interactive mode). A dedicated function likeIssueRepoInfoavoids this kind of issue by encapsulating the exact fields required, rather than pushing that responsibility onto each caller.