Merge pull request #12884 from cli/babakks/use-min-discovery-fields-for-issue-create

fix(issue): avoid fetching unnecessary fields for discovery
This commit is contained in:
William Martin 2026-03-25 15:39:40 +01:00 committed by GitHub
commit 69d89a6590
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 247 additions and 26 deletions

View file

@ -314,6 +314,47 @@ func FetchRepository(client *Client, repo ghrepo.Interface, fields []string) (*R
return InitRepoHostname(result.Repository, repo.RepoHost()), nil
}
// IssueRepoInfo fetches only the repository fields needed for issue operations such as
// issue creation and transfer, avoiding fields like defaultBranchRef that require additional
// token permissions.
func IssueRepoInfo(client *Client, repo ghrepo.Interface) (*Repository, error) {
query := `
query IssueRepositoryInfo($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) {
id
name
owner { login }
hasIssuesEnabled
viewerPermission
}
}`
variables := map[string]interface{}{
"owner": repo.RepoOwner(),
"name": repo.RepoName(),
}
var result struct {
Repository *Repository
}
if err := client.GraphQL(repo.RepoHost(), query, variables, &result); err != nil {
return nil, err
}
// The GraphQL API should have returned an error in case of a missing repository, but this isn't
// guaranteed to happen when an authentication token with insufficient permissions is being used.
if result.Repository == nil {
return nil, GraphQLError{
GraphQLError: &ghAPI.GraphQLError{
Errors: []ghAPI.GraphQLErrorItem{{
Type: "NOT_FOUND",
Message: fmt.Sprintf("Could not resolve to a Repository with the name '%s/%s'.", repo.RepoOwner(), repo.RepoName()),
}},
},
}
}
return InitRepoHostname(result.Repository, repo.RepoHost()), nil
}
func GitHubRepo(client *Client, repo ghrepo.Interface) (*Repository, error) {
query := `
fragment repo on Repository {

View file

@ -26,15 +26,181 @@ func TestGitHubRepo_notFound(t *testing.T) {
client := newTestClient(httpReg)
repo, err := GitHubRepo(client, ghrepo.New("OWNER", "REPO"))
if err == nil {
t.Fatal("GitHubRepo did not return an error")
}
if wants := "GraphQL: Could not resolve to a Repository with the name 'OWNER/REPO'."; err.Error() != wants {
t.Errorf("GitHubRepo error: want %q, got %q", wants, err.Error())
}
if repo != nil {
t.Errorf("GitHubRepo: expected nil repo, got %v", repo)
require.EqualError(t, err, "GraphQL: Could not resolve to a Repository with the name 'OWNER/REPO'.")
assert.Nil(t, repo)
}
func TestGitHubRepo_success(t *testing.T) {
httpReg := &httpmock.Registry{}
defer httpReg.Verify(t)
httpReg.Register(
httpmock.GraphQL(`query RepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"name": "REPO",
"owner": {"login": "OWNER"},
"hasIssuesEnabled": true,
"description": "a cool repo",
"hasWikiEnabled": true,
"viewerPermission": "ADMIN",
"defaultBranchRef": {"name": "main"},
"parent": null,
"mergeCommitAllowed": true,
"rebaseMergeAllowed": true,
"squashMergeAllowed": false
} } }`))
client := newTestClient(httpReg)
repo, err := GitHubRepo(client, ghrepo.New("OWNER", "REPO"))
require.NoError(t, err)
assert.Equal(t, &Repository{
ID: "REPOID",
Name: "REPO",
Owner: RepositoryOwner{Login: "OWNER"},
HasIssuesEnabled: true,
Description: "a cool repo",
HasWikiEnabled: true,
ViewerPermission: "ADMIN",
DefaultBranchRef: BranchRef{Name: "main"},
MergeCommitAllowed: true,
RebaseMergeAllowed: true,
hostname: "github.com",
}, repo)
assert.True(t, repo.ViewerCanPush())
assert.True(t, repo.ViewerCanTriage())
}
func TestGitHubRepo_withParent(t *testing.T) {
httpReg := &httpmock.Registry{}
defer httpReg.Verify(t)
httpReg.Register(
httpmock.GraphQL(`query RepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"name": "REPO",
"owner": {"login": "OWNER"},
"hasIssuesEnabled": true,
"description": "",
"hasWikiEnabled": false,
"viewerPermission": "READ",
"defaultBranchRef": {"name": "main"},
"parent": {
"id": "PARENTID",
"name": "PARENT-REPO",
"owner": {"login": "PARENT-OWNER"},
"hasIssuesEnabled": true,
"description": "parent repo",
"hasWikiEnabled": true,
"viewerPermission": "READ",
"defaultBranchRef": {"name": "develop"}
},
"mergeCommitAllowed": false,
"rebaseMergeAllowed": false,
"squashMergeAllowed": true
} } }`))
client := newTestClient(httpReg)
repo, err := GitHubRepo(client, ghrepo.New("OWNER", "REPO"))
require.NoError(t, err)
wantParent := &Repository{
ID: "PARENTID",
Name: "PARENT-REPO",
Owner: RepositoryOwner{Login: "PARENT-OWNER"},
HasIssuesEnabled: true,
Description: "parent repo",
HasWikiEnabled: true,
ViewerPermission: "READ",
DefaultBranchRef: BranchRef{Name: "develop"},
hostname: "github.com",
}
assert.Equal(t, &Repository{
ID: "REPOID",
Name: "REPO",
Owner: RepositoryOwner{Login: "OWNER"},
HasIssuesEnabled: true,
ViewerPermission: "READ",
DefaultBranchRef: BranchRef{Name: "main"},
Parent: wantParent,
SquashMergeAllowed: true,
hostname: "github.com",
}, repo)
assert.False(t, repo.ViewerCanPush())
assert.False(t, repo.ViewerCanTriage())
}
func TestIssueRepoInfo_notFound(t *testing.T) {
httpReg := &httpmock.Registry{}
defer httpReg.Verify(t)
httpReg.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`{ "data": { "repository": null } }`))
client := newTestClient(httpReg)
repo, err := IssueRepoInfo(client, ghrepo.New("OWNER", "REPO"))
require.EqualError(t, err, "GraphQL: Could not resolve to a Repository with the name 'OWNER/REPO'.")
assert.Nil(t, repo)
}
func TestIssueRepoInfo_success(t *testing.T) {
httpReg := &httpmock.Registry{}
defer httpReg.Verify(t)
httpReg.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"name": "REPO",
"owner": {"login": "OWNER"},
"hasIssuesEnabled": true,
"viewerPermission": "WRITE"
} } }`))
client := newTestClient(httpReg)
repo, err := IssueRepoInfo(client, ghrepo.New("OWNER", "REPO"))
require.NoError(t, err)
assert.Equal(t, &Repository{
ID: "REPOID",
Name: "REPO",
Owner: RepositoryOwner{Login: "OWNER"},
HasIssuesEnabled: true,
ViewerPermission: "WRITE",
hostname: "github.com",
}, repo)
assert.True(t, repo.ViewerCanTriage())
}
func TestIssueRepoInfo_issuesDisabled(t *testing.T) {
httpReg := &httpmock.Registry{}
defer httpReg.Verify(t)
httpReg.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"name": "REPO",
"owner": {"login": "OWNER"},
"hasIssuesEnabled": false,
"viewerPermission": "READ"
} } }`))
client := newTestClient(httpReg)
repo, err := IssueRepoInfo(client, ghrepo.New("OWNER", "REPO"))
require.NoError(t, err)
assert.Equal(t, &Repository{
ID: "REPOID",
Name: "REPO",
Owner: RepositoryOwner{Login: "OWNER"},
ViewerPermission: "READ",
hostname: "github.com",
}, repo)
assert.False(t, repo.ViewerCanTriage())
}
func Test_RepoMetadata(t *testing.T) {