diff --git a/pkg/cmd/search/shared/shared.go b/pkg/cmd/search/shared/shared.go index f670548b3..d095e8769 100644 --- a/pkg/cmd/search/shared/shared.go +++ b/pkg/cmd/search/shared/shared.go @@ -114,12 +114,12 @@ func displayIssueResults(io *iostreams.IOStreams, now time.Time, et EntityType, issueNum = "#" + issueNum } if issue.IsPullRequest() { - tp.AddField(issueNum, nil, cs.ColorFromString(colorForPRState(issue.State))) + tp.AddField(issueNum, nil, cs.ColorFromString(colorForPRState(issue.State()))) } else { - tp.AddField(issueNum, nil, cs.ColorFromString(colorForIssueState(issue.State, issue.StateReason))) + tp.AddField(issueNum, nil, cs.ColorFromString(colorForIssueState(issue.State(), issue.StateReason))) } if !tp.IsTTY() { - tp.AddField(issue.State, nil, nil) + tp.AddField(issue.State(), nil, nil) } tp.AddField(text.RemoveExcessiveWhitespace(issue.Title), nil, nil) tp.AddField(listIssueLabels(&issue, cs, tp.IsTTY()), nil, nil) diff --git a/pkg/cmd/search/shared/shared_test.go b/pkg/cmd/search/shared/shared_test.go index fe6c8c57b..8c4d4ca45 100644 --- a/pkg/cmd/search/shared/shared_test.go +++ b/pkg/cmd/search/shared/shared_test.go @@ -54,9 +54,9 @@ func TestSearchIssues(t *testing.T) { return search.IssuesResult{ IncompleteResults: false, Items: []search.Issue{ - {RepositoryURL: "github.com/test/cli", Number: 123, State: "open", Title: "something broken", Labels: []search.Label{{Name: "bug"}, {Name: "p1"}}, UpdatedAt: updatedAt}, - {RepositoryURL: "github.com/what/what", Number: 456, State: "closed", Title: "feature request", Labels: []search.Label{{Name: "enhancement"}}, UpdatedAt: updatedAt}, - {RepositoryURL: "github.com/blah/test", Number: 789, State: "open", Title: "some title", UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/test/cli", Number: 123, StateInternal: "open", Title: "something broken", Labels: []search.Label{{Name: "bug"}, {Name: "p1"}}, UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/what/what", Number: 456, StateInternal: "closed", Title: "feature request", Labels: []search.Label{{Name: "enhancement"}}, UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/blah/test", Number: 789, StateInternal: "open", Title: "some title", UpdatedAt: updatedAt}, }, Total: 300, }, nil @@ -76,8 +76,8 @@ func TestSearchIssues(t *testing.T) { return search.IssuesResult{ IncompleteResults: false, Items: []search.Issue{ - {RepositoryURL: "github.com/test/cli", Number: 123, State: "open", Title: "bug", Labels: []search.Label{{Name: "bug"}, {Name: "p1"}}, UpdatedAt: updatedAt}, - {RepositoryURL: "github.com/what/what", Number: 456, State: "open", Title: "fix bug", Labels: []search.Label{{Name: "fix"}}, PullRequestLinks: search.PullRequestLinks{URL: "someurl"}, UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/test/cli", Number: 123, StateInternal: "open", Title: "bug", Labels: []search.Label{{Name: "bug"}, {Name: "p1"}}, UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/what/what", Number: 456, StateInternal: "open", Title: "fix bug", Labels: []search.Label{{Name: "fix"}}, PullRequest: search.PullRequest{URL: "someurl"}, UpdatedAt: updatedAt}, }, Total: 300, }, nil @@ -97,9 +97,9 @@ func TestSearchIssues(t *testing.T) { return search.IssuesResult{ IncompleteResults: false, Items: []search.Issue{ - {RepositoryURL: "github.com/test/cli", Number: 123, State: "open", Title: "something broken", Labels: []search.Label{{Name: "bug"}, {Name: "p1"}}, UpdatedAt: updatedAt}, - {RepositoryURL: "github.com/what/what", Number: 456, State: "closed", Title: "feature request", Labels: []search.Label{{Name: "enhancement"}}, UpdatedAt: updatedAt}, - {RepositoryURL: "github.com/blah/test", Number: 789, State: "open", Title: "some title", UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/test/cli", Number: 123, StateInternal: "open", Title: "something broken", Labels: []search.Label{{Name: "bug"}, {Name: "p1"}}, UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/what/what", Number: 456, StateInternal: "closed", Title: "feature request", Labels: []search.Label{{Name: "enhancement"}}, UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/blah/test", Number: 789, StateInternal: "open", Title: "some title", UpdatedAt: updatedAt}, }, Total: 300, }, nil @@ -118,8 +118,8 @@ func TestSearchIssues(t *testing.T) { return search.IssuesResult{ IncompleteResults: false, Items: []search.Issue{ - {RepositoryURL: "github.com/test/cli", Number: 123, State: "open", Title: "bug", Labels: []search.Label{{Name: "bug"}, {Name: "p1"}}, UpdatedAt: updatedAt}, - {RepositoryURL: "github.com/what/what", Number: 456, State: "open", Title: "fix bug", Labels: []search.Label{{Name: "fix"}}, PullRequestLinks: search.PullRequestLinks{URL: "someurl"}, UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/test/cli", Number: 123, StateInternal: "open", Title: "bug", Labels: []search.Label{{Name: "bug"}, {Name: "p1"}}, UpdatedAt: updatedAt}, + {RepositoryURL: "github.com/what/what", Number: 456, StateInternal: "open", Title: "fix bug", Labels: []search.Label{{Name: "fix"}}, PullRequest: search.PullRequest{URL: "someurl"}, UpdatedAt: updatedAt}, }, Total: 300, }, nil diff --git a/pkg/search/result.go b/pkg/search/result.go index 4447f48ee..6ef1b8bc0 100644 --- a/pkg/search/result.go +++ b/pkg/search/result.go @@ -117,28 +117,42 @@ type User struct { } type Issue struct { - Assignees []User `json:"assignees"` - Author User `json:"user"` - AuthorAssociation string `json:"author_association"` - Body string `json:"body"` - ClosedAt time.Time `json:"closed_at"` - CommentsCount int `json:"comments"` - CreatedAt time.Time `json:"created_at"` - ID string `json:"node_id"` - Labels []Label `json:"labels"` - IsLocked bool `json:"locked"` - Number int `json:"number"` - PullRequestLinks PullRequestLinks `json:"pull_request"` - RepositoryURL string `json:"repository_url"` - State string `json:"state"` - StateReason string `json:"state_reason"` - Title string `json:"title"` - URL string `json:"html_url"` - UpdatedAt time.Time `json:"updated_at"` + Assignees []User `json:"assignees"` + Author User `json:"user"` + AuthorAssociation string `json:"author_association"` + Body string `json:"body"` + ClosedAt time.Time `json:"closed_at"` + CommentsCount int `json:"comments"` + CreatedAt time.Time `json:"created_at"` + ID string `json:"node_id"` + Labels []Label `json:"labels"` + IsLocked bool `json:"locked"` + Number int `json:"number"` + PullRequest PullRequest `json:"pull_request"` + RepositoryURL string `json:"repository_url"` + // StateInternal should not be used directly. Use State() instead. + StateInternal string `json:"state"` + StateReason string `json:"state_reason"` + Title string `json:"title"` + URL string `json:"html_url"` + UpdatedAt time.Time `json:"updated_at"` } -type PullRequestLinks struct { - URL string `json:"html_url"` +type PullRequest struct { + URL string `json:"html_url"` + MergedAt time.Time `json:"merged_at"` +} + +// the state of an issue or a pull request, +// may be either open or closed. +// for a pull request, the "merged" state is +// inferred from a value for merged_at and +// which we take return instead of the "closed" state. +func (issue Issue) State() string { + if !issue.PullRequest.MergedAt.IsZero() { + return "merged" + } + return issue.StateInternal } type Label struct { @@ -175,7 +189,7 @@ func (repo Repository) ExportData(fields []string) map[string]interface{} { } func (issue Issue) IsPullRequest() bool { - return issue.PullRequestLinks.URL != "" + return issue.PullRequest.URL != "" } func (issue Issue) ExportData(fields []string) map[string]interface{} { @@ -220,6 +234,8 @@ func (issue Issue) ExportData(fields []string) map[string]interface{} { "name": name, "nameWithOwner": nameWithOwner, } + case "state": + data[f] = issue.State() default: sf := fieldByName(v, f) data[f] = sf.Interface() diff --git a/pkg/search/result_test.go b/pkg/search/result_test.go index ba173e591..c933eb304 100644 --- a/pkg/search/result_test.go +++ b/pkg/search/result_test.go @@ -68,6 +68,26 @@ func TestIssueExportData(t *testing.T) { }, output: `{"assignees":[{"id":"","login":"test","type":""}],"body":"body","commentsCount":1,"isLocked":true,"labels":[{"color":"","description":"","id":"","name":"label1"},{"color":"","description":"","id":"","name":"label2"}],"repository":{"name":"repo","nameWithOwner":"owner/repo"},"title":"title","updatedAt":"2021-02-28T12:30:00Z"}`, }, + { + name: "state when issue", + fields: []string{"isPullRequest", "state"}, + issue: Issue{ + StateInternal: "closed", + }, + output: `{"isPullRequest":false,"state":"closed"}`, + }, + { + name: "state when pull request", + fields: []string{"isPullRequest", "state"}, + issue: Issue{ + PullRequest: PullRequest{ + MergedAt: time.Now(), + URL: "a-url", + }, + StateInternal: "closed", + }, + output: `{"isPullRequest":true,"state":"merged"}`, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {