Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

Commit

Permalink
feat: Add group flag to mr list command (#931)
Browse files Browse the repository at this point in the history
* feat: Add group flag to mr list command

This adds a flag for listing groups mrs. This works only for groups in
authenticated repos. This is acceptable since mr list only works on
authenticated repos too.

Issue #909

* feat: Add group flag for issue listing

Issue #909
  • Loading branch information
zemzale authored Jan 10, 2022
1 parent ecd2c2a commit 612ff86
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 29 deletions.
44 changes: 44 additions & 0 deletions api/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,50 @@ var GetIssue = func(client *gitlab.Client, projectID interface{}, issueID int) (
return issue, nil
}

var ProjectListIssueOptionsToGroup = func(l *gitlab.ListProjectIssuesOptions) *gitlab.ListGroupIssuesOptions {
return &gitlab.ListGroupIssuesOptions{
ListOptions: l.ListOptions,
State: l.State,
Labels: l.Labels,
NotLabels: l.NotLabels,
WithLabelDetails: l.WithLabelDetails,
IIDs: l.IIDs,
Milestone: l.Milestone,
Scope: l.Scope,
AuthorID: l.AuthorID,
NotAuthorID: l.NotAuthorID,
AssigneeID: l.AssigneeID,
NotAssigneeID: l.NotAssigneeID,
AssigneeUsername: l.AssigneeUsername,
MyReactionEmoji: l.MyReactionEmoji,
NotMyReactionEmoji: l.NotMyReactionEmoji,
OrderBy: l.OrderBy,
Sort: l.Sort,
Search: l.Search,
In: l.In,
CreatedAfter: l.CreatedAfter,
CreatedBefore: l.CreatedBefore,
UpdatedAfter: l.UpdatedAfter,
UpdatedBefore: l.UpdatedBefore,
IssueType: l.IssueType,
}
}

var ListGroupIssues = func(client *gitlab.Client, groupID interface{}, opts *gitlab.ListGroupIssuesOptions) ([]*gitlab.Issue, error) {
if client == nil {
client = apiClient.Lab()
}
if opts.PerPage == 0 {
opts.PerPage = DefaultListLimit
}
issues, _, err := client.Issues.ListGroupIssues(groupID, opts)
if err != nil {
return nil, err
}

return issues, nil
}

var ListIssues = func(client *gitlab.Client, projectID interface{}, opts *gitlab.ListProjectIssuesOptions) ([]*gitlab.Issue, error) {
if client == nil {
client = apiClient.Lab()
Expand Down
45 changes: 45 additions & 0 deletions api/merge_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,51 @@ var GetMR = func(client *gitlab.Client, projectID interface{}, mrID int, opts *g
return mr, nil
}

var ListGroupMRs = func(client *gitlab.Client, groupID interface{}, opts *gitlab.ListGroupMergeRequestsOptions) ([]*gitlab.MergeRequest, error) {
if client == nil {
client = apiClient.Lab()
}
if opts.PerPage == 0 {
opts.PerPage = DefaultListLimit
}

mrs, _, err := client.MergeRequests.ListGroupMergeRequests(groupID, opts)
if err != nil {
return nil, err
}

return mrs, nil
}

var ProjectListMROptionsToGroup = func(l *gitlab.ListProjectMergeRequestsOptions) *gitlab.ListGroupMergeRequestsOptions {
return &gitlab.ListGroupMergeRequestsOptions{
ListOptions: l.ListOptions,
State: l.State,
OrderBy: l.OrderBy,
Sort: l.Sort,
Milestone: l.Milestone,
View: l.View,
Labels: l.Labels,
NotLabels: l.NotLabels,
WithLabelsDetails: l.WithLabelsDetails,
WithMergeStatusRecheck: l.WithMergeStatusRecheck,
CreatedAfter: l.CreatedAfter,
CreatedBefore: l.CreatedBefore,
UpdatedAfter: l.UpdatedAfter,
UpdatedBefore: l.UpdatedBefore,
Scope: l.Scope,
AuthorID: l.AuthorID,
AssigneeID: l.AssigneeID,
ReviewerID: l.ReviewerID,
ReviewerUsername: l.ReviewerUsername,
MyReactionEmoji: l.MyReactionEmoji,
SourceBranch: l.SourceBranch,
TargetBranch: l.TargetBranch,
Search: l.Search,
WIP: l.WIP,
}
}

var ListMRs = func(client *gitlab.Client, projectID interface{}, opts *gitlab.ListProjectMergeRequestsOptions) ([]*gitlab.MergeRequest, error) {
if client == nil {
client = apiClient.Lab()
Expand Down
21 changes: 16 additions & 5 deletions commands/issue/list/issue_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type ListOptions struct {
Milestone string
Mine bool
Search string
Group string

// issue states
State string
Expand Down Expand Up @@ -124,6 +125,7 @@ func NewCmdList(f *cmdutils.Factory, runE func(opts *ListOptions) error) *cobra.
issueListCmd.Flags().BoolVarP(&opts.Confidential, "confidential", "C", false, "Filter by confidential issues")
issueListCmd.Flags().IntVarP(&opts.Page, "page", "p", 1, "Page number")
issueListCmd.Flags().IntVarP(&opts.PerPage, "per-page", "P", 30, "Number of items to list per page. (default 30)")
issueListCmd.Flags().StringVarP(&opts.Group, "group", "g", "", "Get issues from group and it's subgroups")

issueListCmd.Flags().BoolP("opened", "o", false, "Get only opened issues")
_ = issueListCmd.Flags().MarkHidden("opened")
Expand Down Expand Up @@ -214,13 +216,22 @@ func listRun(opts *ListOptions) error {
opts.ListType = "search"
}

issues, err := api.ListIssues(apiClient, repo.FullName(), listOpts)
if err != nil {
return err
}

var issues []*gitlab.Issue
title := utils.NewListTitle(opts.TitleQualifier + " issue")
title.RepoName = repo.FullName()
if opts.Group != "" {
issues, err = api.ListGroupIssues(apiClient, opts.Group, api.ProjectListIssueOptionsToGroup(listOpts))
if err != nil {
return err
}
title.RepoName = opts.Group
} else {
issues, err = api.ListIssues(apiClient, repo.FullName(), listOpts)
if err != nil {
return err
}
}

title.Page = listOpts.Page
title.ListActionType = opts.ListType
title.CurrentPageTotal = len(issues)
Expand Down
40 changes: 30 additions & 10 deletions commands/issue/list/issue_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,42 @@ func TestIssueList_tty(t *testing.T) {
}

func TestIssueList_tty_withFlags(t *testing.T) {
fakeHTTP := httpmock.New()
defer fakeHTTP.Verify(t)
t.Run("project", func(t *testing.T) {
fakeHTTP := httpmock.New()
defer fakeHTTP.Verify(t)

fakeHTTP.RegisterResponder("GET", "/projects/OWNER/REPO/issues",
httpmock.NewStringResponse(200, `[]`))
fakeHTTP.RegisterResponder("GET", "/projects/OWNER/REPO/issues",
httpmock.NewStringResponse(200, `[]`))

output, err := runCommand(fakeHTTP, true, "--opened -P1 -p100 --confidential -a someuser -l bug -m1", nil, "")
if err != nil {
t.Errorf("error running command `issue list`: %v", err)
}
output, err := runCommand(fakeHTTP, true, "--opened -P1 -p100 --confidential -a someuser -l bug -m1", nil, "")
if err != nil {
t.Errorf("error running command `issue list`: %v", err)
}

cmdtest.Eq(t, output.Stderr(), "")
cmdtest.Eq(t, output.String(), `No open issues match your search in OWNER/REPO
cmdtest.Eq(t, output.Stderr(), "")
cmdtest.Eq(t, output.String(), `No open issues match your search in OWNER/REPO
`)
})
t.Run("group", func(t *testing.T) {
fakeHTTP := httpmock.New()
defer fakeHTTP.Verify(t)

fakeHTTP.RegisterResponder("GET", "/groups/GROUP/issues",
httpmock.NewStringResponse(200, `[]`))

output, err := runCommand(fakeHTTP, true, "--group GROUP", nil, "")
if err != nil {
t.Errorf("error running command `issue list`: %v", err)
}

cmdtest.Eq(t, output.Stderr(), "")
cmdtest.Eq(t, output.String(), `No open issues match your search in GROUP
`)
})
}

func TestIssueList_tty_mine(t *testing.T) {
Expand Down
9 changes: 7 additions & 2 deletions commands/mr/list/mr_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type ListOptions struct {
TargetBranch string
Search string
Mine bool
Group string

// issue states
State string
Expand Down Expand Up @@ -135,6 +136,7 @@ func NewCmdList(f *cmdutils.Factory, runE func(opts *ListOptions) error) *cobra.
mrListCmd.Flags().BoolVarP(&opts.Mine, "mine", "", false, "Get only merge requests assigned to me")
_ = mrListCmd.Flags().MarkHidden("mine")
_ = mrListCmd.Flags().MarkDeprecated("mine", "use --assignee=@me")
mrListCmd.Flags().StringVarP(&opts.Group, "group", "g", "", "Get MRs from group and it's subgroups")

return mrListCmd
}
Expand Down Expand Up @@ -223,19 +225,22 @@ func listRun(opts *ListOptions) error {
reviewerIds = append(reviewerIds, user.ID)
}
}
title := utils.NewListTitle(opts.TitleQualifier + " merge request")
title.RepoName = repo.FullName()

if len(assigneeIds) > 0 || len(reviewerIds) > 0 {
mergeRequests, err = api.ListMRsWithAssigneesOrReviewers(apiClient, repo.FullName(), l, assigneeIds, reviewerIds)

} else if opts.Group != "" {
mergeRequests, err = api.ListGroupMRs(apiClient, opts.Group, api.ProjectListMROptionsToGroup(l))
title.RepoName = opts.Group
} else {
mergeRequests, err = api.ListMRs(apiClient, repo.FullName(), l)
}
if err != nil {
return err
}

title := utils.NewListTitle(opts.TitleQualifier + " merge request")
title.RepoName = repo.FullName()
title.Page = l.Page
title.ListActionType = opts.ListType
title.CurrentPageTotal = len(mergeRequests)
Expand Down
43 changes: 31 additions & 12 deletions commands/mr/list/mr_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,25 +174,44 @@ func TestMergeRequestList_tty(t *testing.T) {
}

func TestMergeRequestList_tty_withFlags(t *testing.T) {
fakeHTTP := httpmock.New()
defer fakeHTTP.Verify(t)
t.Run("repo", func(t *testing.T) {
fakeHTTP := httpmock.New()
defer fakeHTTP.Verify(t)

fakeHTTP.RegisterResponder("GET", "/projects/OWNER/REPO/merge_requests",
httpmock.NewStringResponse(200, `[]`))
fakeHTTP.RegisterResponder("GET", "/projects/OWNER/REPO/merge_requests",
httpmock.NewStringResponse(200, `[]`))

fakeHTTP.RegisterResponder("GET", "/users",
httpmock.NewStringResponse(200, `[{"id" : 1, "iid" : 1, "username": "john_smith"}]`))
fakeHTTP.RegisterResponder("GET", "/users",
httpmock.NewStringResponse(200, `[{"id" : 1, "iid" : 1, "username": "john_smith"}]`))

output, err := runCommand(fakeHTTP, true, "--opened -P1 -p100 -a someuser -l bug -m1", nil, "")
if err != nil {
t.Errorf("error running command `issue list`: %v", err)
}
output, err := runCommand(fakeHTTP, true, "--opened -P1 -p100 -a someuser -l bug -m1", nil, "")
if err != nil {
t.Errorf("error running command `issue list`: %v", err)
}

cmdtest.Eq(t, output.Stderr(), "")
cmdtest.Eq(t, output.String(), `No open merge requests match your search in OWNER/REPO
cmdtest.Eq(t, output.Stderr(), "")
cmdtest.Eq(t, output.String(), `No open merge requests match your search in OWNER/REPO
`)
})
t.Run("group", func(t *testing.T) {
fakeHTTP := httpmock.New()
defer fakeHTTP.Verify(t)

fakeHTTP.RegisterResponder("GET", "/groups/GROUP/merge_requests",
httpmock.NewStringResponse(200, `[]`))

output, err := runCommand(fakeHTTP, true, "--group GROUP", nil, "")
if err != nil {
t.Errorf("error running command `mr list`: %v", err)
}

cmdtest.Eq(t, output.Stderr(), "")
cmdtest.Eq(t, output.String(), `No open merge requests available on GROUP
`)
})
}

func makeHyperlink(linkText, targetURL string) string {
Expand Down

0 comments on commit 612ff86

Please sign in to comment.