Skip to content
This repository was archived by the owner on Dec 10, 2024. It is now read-only.

Commit

Permalink
Add None and Any options for AssigneeID for all merge request list fu…
Browse files Browse the repository at this point in the history
…nctions.

Fixes #751

The fix that has been added implement a type just like we do for AssigneeIDs. A value object that encapsulates the possible values. This is a backwards breaking fix.
  • Loading branch information
Bouwdie committed Jan 4, 2022
1 parent c465c6c commit 2ea307f
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 54 deletions.
106 changes: 53 additions & 53 deletions merge_requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ type ListMergeRequestsOptions struct {
Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"`
AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"`
AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
ApprovedByIDs *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
ReviewerID *int `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
ReviewerUsername *string `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
Expand Down Expand Up @@ -198,32 +198,32 @@ func (s *MergeRequestsService) ListMergeRequests(opt *ListMergeRequestsOptions,
// https://docs.gitlab.com/ce/api/merge_requests.html#list-group-merge-requests
type ListGroupMergeRequestsOptions struct {
ListOptions
State *string `url:"state,omitempty" json:"state,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"`
View *string `url:"view,omitempty" json:"view,omitempty"`
Labels *Labels `url:"labels,comma,omitempty" json:"labels,omitempty"`
NotLabels *Labels `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"`
WithLabelsDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"`
WithMergeStatusRecheck *bool `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"`
UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"`
Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"`
AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"`
AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
ReviewerID *int `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
ReviewerUsername *string `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
In *string `url:"in,omitempty" json:"in,omitempty"`
Draft *bool `url:"draft,omitempty" json:"draft,omitempty"`
WIP *string `url:"wip,omitempty" json:"wip,omitempty"`
State *string `url:"state,omitempty" json:"state,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"`
View *string `url:"view,omitempty" json:"view,omitempty"`
Labels *Labels `url:"labels,comma,omitempty" json:"labels,omitempty"`
NotLabels *Labels `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"`
WithLabelsDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"`
WithMergeStatusRecheck *bool `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"`
UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"`
Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"`
AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"`
AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
ReviewerID *int `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
ReviewerUsername *string `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
In *string `url:"in,omitempty" json:"in,omitempty"`
Draft *bool `url:"draft,omitempty" json:"draft,omitempty"`
WIP *string `url:"wip,omitempty" json:"wip,omitempty"`
}

// ListGroupMergeRequests gets all merge requests for this group.
Expand Down Expand Up @@ -258,32 +258,32 @@ func (s *MergeRequestsService) ListGroupMergeRequests(gid interface{}, opt *List
// https://docs.gitlab.com/ce/api/merge_requests.html#list-project-merge-requests
type ListProjectMergeRequestsOptions struct {
ListOptions
IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"`
State *string `url:"state,omitempty" json:"state,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"`
View *string `url:"view,omitempty" json:"view,omitempty"`
Labels *Labels `url:"labels,comma,omitempty" json:"labels,omitempty"`
NotLabels *Labels `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"`
WithLabelsDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"`
WithMergeStatusRecheck *bool `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"`
UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"`
Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"`
AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"`
AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
ReviewerID *int `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
ReviewerUsername *string `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
Draft *bool `url:"draft,omitempty" json:"draft,omitempty"`
WIP *string `url:"wip,omitempty" json:"wip,omitempty"`
IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"`
State *string `url:"state,omitempty" json:"state,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"`
View *string `url:"view,omitempty" json:"view,omitempty"`
Labels *Labels `url:"labels,comma,omitempty" json:"labels,omitempty"`
NotLabels *Labels `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"`
WithLabelsDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"`
WithMergeStatusRecheck *bool `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"`
UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"`
Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"`
AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"`
AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
ReviewerID *int `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
ReviewerUsername *string `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
Draft *bool `url:"draft,omitempty" json:"draft,omitempty"`
WIP *string `url:"wip,omitempty" json:"wip,omitempty"`
}

// ListProjectMergeRequests gets all merge requests for this project.
Expand Down
34 changes: 33 additions & 1 deletion merge_requests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package gitlab

import (
"encoding/json"
"fmt"
"log"
"net/http"
Expand Down Expand Up @@ -153,13 +154,14 @@ func TestListProjectMergeRequests(t *testing.T) {

mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
testParams(t, r, "with_labels_details=true&with_merge_status_recheck=true")
testParams(t, r, "assignee_id=Any&with_labels_details=true&with_merge_status_recheck=true")
mustWriteHTTPResponse(t, w, "testdata/get_merge_requests.json")
})

opts := ListProjectMergeRequestsOptions{
WithLabelsDetails: Bool(true),
WithMergeStatusRecheck: Bool(true),
AssigneeID: AssigneeID(AssigneeIDDAny),
}

mergeRequests, _, err := client.MergeRequests.ListProjectMergeRequests(278964, &opts)
Expand Down Expand Up @@ -271,3 +273,33 @@ func TestIntSliceOrString(t *testing.T) {
assert.Equal(t, []string{"1", "2", "3"}, includedIDs)
})
}

func TestAssigneeIDMarshalling(t *testing.T) {
t.Run("any", func(t *testing.T) {
opts := &ListMergeRequestsOptions{}
opts.AssigneeID = AssigneeID(AssigneeIDDAny)
q, err := query.Values(opts)
assert.NoError(t, err)
assert.Equal(t, "Any", q.Get("assignee_id"))
js, _ := json.Marshal(opts)
assert.Equal(t, `{"assignee_id":"Any"}`, string(js))
})
t.Run("none", func(t *testing.T) {
opts := &ListMergeRequestsOptions{}
opts.AssigneeID = AssigneeID(AssigneeIDDNone)
q, err := query.Values(opts)
assert.NoError(t, err)
assert.Equal(t, "None", q.Get("assignee_id"))
js, _ := json.Marshal(opts)
assert.Equal(t, `{"assignee_id":"None"}`, string(js))
})
t.Run("id", func(t *testing.T) {
opts := &ListMergeRequestsOptions{}
opts.AssigneeID = AssigneeID(5)
q, err := query.Values(opts)
assert.NoError(t, err)
assert.Equal(t, "5", q.Get("assignee_id"))
js, _ := json.Marshal(opts)
assert.Equal(t, `{"assignee_id":5}`, string(js))
})
}
41 changes: 41 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -737,3 +737,44 @@ func (t *BoolValue) UnmarshalJSON(b []byte) error {
return err
}
}

// AssigneeIDStringValue is a type to represent valid assignee id string values
type AssigneeIDStringValue string

// List of available assignee ID string values.
const (
AssigneeIDDAny AssigneeIDStringValue = "Any"
AssigneeIDDNone AssigneeIDStringValue = "None"
)

// AssigneeIDValue represents an assignee ID value within GitLab.
type AssigneeIDValue struct {
value interface{}
}

func (a *AssigneeIDValue) UnmarshalJSON(bytes []byte) error {
return json.Unmarshal(bytes, a.value)
}

func (a *AssigneeIDValue) MarshalJSON() ([]byte, error) {
return json.Marshal(a.value)
}

func AssigneeID(v interface{}) *AssigneeIDValue {
switch v.(type) {
case AssigneeIDStringValue, int:
return &AssigneeIDValue{value: v}
default:
panic("Unsupported value passed as assignee ID")
}
}

func (a *AssigneeIDValue) EncodeValues(key string, v *url.Values) error {
switch value := a.value.(type) {
case AssigneeIDStringValue:
v.Set(key, string(value))
case int:
v.Set(key, strconv.Itoa(value))
}
return nil
}

0 comments on commit 2ea307f

Please sign in to comment.