Merge pull request #2190 from quiye/issues-data-race

Fix issue label overrides caused by pagination
This commit is contained in:
Mislav Marohnić 2020-10-15 13:42:30 +02:00 committed by GitHub
commit 02f494693c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 9 deletions

View file

@ -270,7 +270,7 @@ func IssueList(client *Client, repo ghrepo.Interface, state string, labels []str
variables["milestone"] = milestoneRESTID
}
var response struct {
type responseData struct {
Repository struct {
Issues struct {
TotalCount int
@ -285,10 +285,12 @@ func IssueList(client *Client, repo ghrepo.Interface, state string, labels []str
}
var issues []Issue
var totalCount int
pageLimit := min(limit, 100)
loop:
for {
var response responseData
variables["limit"] = pageLimit
err := client.GraphQL(repo.RepoHost(), query, variables, &response)
if err != nil {
@ -297,6 +299,7 @@ loop:
if !response.Repository.HasIssuesEnabled {
return nil, fmt.Errorf("the '%s' repository has disabled issues", ghrepo.FullName(repo))
}
totalCount = response.Repository.Issues.TotalCount
for _, issue := range response.Repository.Issues.Nodes {
issues = append(issues, issue)
@ -313,7 +316,7 @@ loop:
}
}
res := IssuesAndTotalCount{Issues: issues, TotalCount: response.Repository.Issues.TotalCount}
res := IssuesAndTotalCount{Issues: issues, TotalCount: totalCount}
return &res, nil
}

View file

@ -6,6 +6,8 @@ import (
"io/ioutil"
"testing"
"github.com/stretchr/testify/assert"
"github.com/cli/cli/internal/ghrepo"
"github.com/cli/cli/pkg/httpmock"
)
@ -68,3 +70,76 @@ func TestIssueList(t *testing.T) {
t.Errorf("expected %q, got %q", "ENDCURSOR", endCursor)
}
}
func TestIssueList_pagination(t *testing.T) {
http := &httpmock.Registry{}
client := NewClient(ReplaceTripper(http))
http.StubResponse(200, bytes.NewBufferString(`
{ "data": { "repository": {
"hasIssuesEnabled": true,
"issues": {
"nodes": [
{
"title": "issue1",
"labels": { "nodes": [ { "name": "bug" } ], "totalCount": 1 },
"assignees": { "nodes": [ { "login": "user1" } ], "totalCount": 1 }
}
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "ENDCURSOR"
},
"totalCount": 2
}
} } }
`))
http.StubResponse(200, bytes.NewBufferString(`
{ "data": { "repository": {
"hasIssuesEnabled": true,
"issues": {
"nodes": [
{
"title": "issue2",
"labels": { "nodes": [ { "name": "enhancement" } ], "totalCount": 1 },
"assignees": { "nodes": [ { "login": "user2" } ], "totalCount": 1 }
}
],
"pageInfo": {
"hasNextPage": false,
"endCursor": "ENDCURSOR"
},
"totalCount": 2
}
} } }
`))
repo := ghrepo.New("OWNER", "REPO")
res, err := IssueList(client, repo, "", nil, "", 0, "", "", "")
if err != nil {
t.Fatalf("IssueList() error = %v", err)
}
assert.Equal(t, 2, res.TotalCount)
assert.Equal(t, 2, len(res.Issues))
getLabels := func(i Issue) []string {
var labels []string
for _, l := range i.Labels.Nodes {
labels = append(labels, l.Name)
}
return labels
}
getAssignees := func(i Issue) []string {
var logins []string
for _, u := range i.Assignees.Nodes {
logins = append(logins, u.Login)
}
return logins
}
assert.Equal(t, []string{"bug"}, getLabels(res.Issues[0]))
assert.Equal(t, []string{"user1"}, getAssignees(res.Issues[0]))
assert.Equal(t, []string{"enhancement"}, getLabels(res.Issues[1]))
assert.Equal(t, []string{"user2"}, getAssignees(res.Issues[1]))
}

View file

@ -9,7 +9,7 @@ import (
// OrganizationProjects fetches all open projects for an organization
func OrganizationProjects(client *Client, repo ghrepo.Interface) ([]RepoProject, error) {
var query struct {
type responseData struct {
Organization struct {
Projects struct {
Nodes []RepoProject
@ -30,6 +30,7 @@ func OrganizationProjects(client *Client, repo ghrepo.Interface) ([]RepoProject,
var projects []RepoProject
for {
var query responseData
err := gql.QueryNamed(context.Background(), "OrganizationProjectList", &query, variables)
if err != nil {
return nil, err
@ -52,7 +53,7 @@ type OrgTeam struct {
// OrganizationTeams fetches all the teams in an organization
func OrganizationTeams(client *Client, repo ghrepo.Interface) ([]OrgTeam, error) {
var query struct {
type responseData struct {
Organization struct {
Teams struct {
Nodes []OrgTeam
@ -73,6 +74,7 @@ func OrganizationTeams(client *Client, repo ghrepo.Interface) ([]OrgTeam, error)
var teams []OrgTeam
for {
var query responseData
err := gql.QueryNamed(context.Background(), "OrganizationTeamList", &query, variables)
if err != nil {
return nil, err

View file

@ -657,7 +657,7 @@ type RepoProject struct {
// RepoProjects fetches all open projects for a repository
func RepoProjects(client *Client, repo ghrepo.Interface) ([]RepoProject, error) {
var query struct {
type responseData struct {
Repository struct {
Projects struct {
Nodes []RepoProject
@ -679,6 +679,7 @@ func RepoProjects(client *Client, repo ghrepo.Interface) ([]RepoProject, error)
var projects []RepoProject
for {
var query responseData
err := gql.QueryNamed(context.Background(), "RepositoryProjectList", &query, variables)
if err != nil {
return nil, err
@ -701,7 +702,7 @@ type RepoAssignee struct {
// RepoAssignableUsers fetches all the assignable users for a repository
func RepoAssignableUsers(client *Client, repo ghrepo.Interface) ([]RepoAssignee, error) {
var query struct {
type responseData struct {
Repository struct {
AssignableUsers struct {
Nodes []RepoAssignee
@ -723,6 +724,7 @@ func RepoAssignableUsers(client *Client, repo ghrepo.Interface) ([]RepoAssignee,
var users []RepoAssignee
for {
var query responseData
err := gql.QueryNamed(context.Background(), "RepositoryAssignableUsers", &query, variables)
if err != nil {
return nil, err
@ -745,7 +747,7 @@ type RepoLabel struct {
// RepoLabels fetches all the labels in a repository
func RepoLabels(client *Client, repo ghrepo.Interface) ([]RepoLabel, error) {
var query struct {
type responseData struct {
Repository struct {
Labels struct {
Nodes []RepoLabel
@ -767,6 +769,7 @@ func RepoLabels(client *Client, repo ghrepo.Interface) ([]RepoLabel, error) {
var labels []RepoLabel
for {
var query responseData
err := gql.QueryNamed(context.Background(), "RepositoryLabelList", &query, variables)
if err != nil {
return nil, err
@ -789,7 +792,7 @@ type RepoMilestone struct {
// RepoMilestones fetches all open milestones in a repository
func RepoMilestones(client *Client, repo ghrepo.Interface) ([]RepoMilestone, error) {
var query struct {
type responseData struct {
Repository struct {
Milestones struct {
Nodes []RepoMilestone
@ -811,6 +814,7 @@ func RepoMilestones(client *Client, repo ghrepo.Interface) ([]RepoMilestone, err
var milestones []RepoMilestone
for {
var query responseData
err := gql.QueryNamed(context.Background(), "RepositoryMilestoneList", &query, variables)
if err != nil {
return nil, err

View file

@ -21,7 +21,7 @@ type Release struct {
}
func fetchReleases(httpClient *http.Client, repo ghrepo.Interface, limit int) ([]Release, error) {
var query struct {
type responseData struct {
Repository struct {
Releases struct {
Nodes []Release
@ -50,6 +50,7 @@ func fetchReleases(httpClient *http.Client, repo ghrepo.Interface, limit int) ([
var releases []Release
loop:
for {
var query responseData
err := gql.QueryNamed(context.Background(), "RepositoryReleaseList", &query, variables)
if err != nil {
return nil, err