Unverified Commit 38397d41 authored by Sander van Harmelen's avatar Sander van Harmelen Committed by GitHub

Merge pull request #528 from bilby91/add-project-approvers-and-approvals

Add project level MergeRequest API
parents c2683335 946516dd
package gitlab
import (
"bytes"
"context"
"encoding/json"
"io/ioutil"
......@@ -44,6 +45,19 @@ func testMethod(t *testing.T, r *http.Request, want string) {
}
}
func testBody(t *testing.T, r *http.Request, want string) {
buffer := new(bytes.Buffer)
_, err := buffer.ReadFrom(r.Body)
if err != nil {
t.Fatalf("Failed to Read Body: %v", err)
}
if got := buffer.String(); got != want {
t.Errorf("Request body: %s, want %s", got, want)
}
}
func TestNewClient(t *testing.T) {
c := NewClient(nil, "")
expectedBaseURL := defaultBaseURL + apiVersionPath
......
......@@ -31,27 +31,16 @@ type MergeRequestApprovals struct {
ApprovalsBeforeMerge int `json:"approvals_before_merge"`
ApprovalsRequired int `json:"approvals_required"`
ApprovalsLeft int `json:"approvals_left"`
ApprovedBy []struct {
User struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
State string `json:"state"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
} `json:"user"`
} `json:"approved_by"`
Approvers []struct {
User struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
State string `json:"state"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
} `json:"user"`
} `json:"approvers"`
ApproverGroups []struct {
ApprovedBy []*MergeRequestApproverUser `json:"approved_by"`
Approvers []*MergeRequestApproverUser `json:"approvers"`
ApproverGroups []*MergeRequestApproverGroup `json:"approver_groups"`
}
// MergeRequestApproverGroup represents GitLab project level merge request approver group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
type MergeRequestApproverGroup struct {
Group struct {
ID int `json:"id"`
Name string `json:"name"`
......@@ -64,8 +53,22 @@ type MergeRequestApprovals struct {
FullPath string `json:"full_path"`
LFSEnabled bool `json:"lfs_enabled"`
RequestAccessEnabled bool `json:"request_access_enabled"`
} `json:"group"`
} `json:"approver_group"`
}
}
// MergeRequestApproverUser represents GitLab project level merge request approver user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
type MergeRequestApproverUser struct {
User struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
State string `json:"state"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
}
}
func (m MergeRequestApprovals) String() string {
......
......@@ -1172,3 +1172,114 @@ func (s *ProjectsService) DeleteProjectPushRule(pid interface{}, options ...Opti
return s.client.Do(req, nil)
}
// ProjectApprovals represents GitLab project level merge request approvals.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
type ProjectApprovals struct {
ApprovalsBeforeMerge int `json:"approvals_before_merge"`
ResetApprovalsOnPush bool `json:"reset_approvals_on_push"`
DisableOverridingApproversPerMergeRequest bool `json:"disable_overriding_approvers_per_merge_request"`
Approvers []*MergeRequestApproverUser `json:"approvers"`
ApproverGroups []*MergeRequestApproverGroup `json:"approver_groups"`
}
// ApprovalsConfigurationOptions represents the available
// ApprovalsConfigurationOptions() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-configuration
type ApprovalsConfigurationOptions struct {
ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
ResetApprovalsOnPush *bool `url:"reset_approvals_on_push,omitempty" json:"reset_approvals_on_push,omitempty"`
DisableOverridingApproversPerMergeRequest *bool `url:"disable_overriding_approvers_per_merge_request,omitempty" json:"disable_overriding_approvers_per_merge_request,omitempty"`
}
// ApproversConfigurationOptions represents the available
// ApproversConfigurationOptions() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers
type ApproversConfigurationOptions struct {
ApproverIDs []*int `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
ApproverGroupIDs []*int `url:"approver_group_ids,omitempty" json:"approver_group_ids,omitempty"`
}
// GetApprovalsConfigurationOptions get the approval configurations options for a given project on GitLab.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-configuration
func (s *ProjectsService) GetApprovalsConfigurationOptions(pid interface{}, options ...OptionFunc) (*ProjectApprovals, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approvals", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil, options)
if err != nil {
return nil, nil, err
}
mrp := new(ProjectApprovals)
resp, err := s.client.Do(req, mrp)
if err != nil {
return nil, resp, err
}
return mrp, resp, err
}
// ChangeApprovalsConfigurationOptions updates the approval configurations for a given project on GitLab.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-configuration
func (s *ProjectsService) ChangeApprovalsConfigurationOptions(pid interface{}, opt *ApprovalsConfigurationOptions, options ...OptionFunc) (*ProjectApprovals, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approvals", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt, options)
if err != nil {
return nil, nil, err
}
mrp := new(ProjectApprovals)
resp, err := s.client.Do(req, mrp)
if err != nil {
return nil, resp, err
}
return mrp, resp, err
}
// ChangeApproversConfigurationOptions updates the list of approvers for a given project on GitLab.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers
func (s *ProjectsService) ChangeApproversConfigurationOptions(pid interface{}, opt *ApproversConfigurationOptions, options ...OptionFunc) (*ProjectApprovals, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approvers", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt, options)
if err != nil {
return nil, nil, err
}
mrp := new(ProjectApprovals)
resp, err := s.client.Do(req, mrp)
if err != nil {
return nil, resp, err
}
return mrp, resp, err
}
......@@ -351,3 +351,141 @@ func TestDeleteSharedProjectFromGroup(t *testing.T) {
t.Errorf("Projects.DeleteSharedProjectFromGroup returned error: %v", err)
}
}
func TestGetApprovalsConfigurationOptions(t *testing.T) {
mux, server, client := setup()
defer teardown(server)
mux.HandleFunc("/api/v4/projects/1/approvals", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{
"approvals_before_merge": 3,
"reset_approvals_on_push": false,
"disable_overriding_approvers_per_merge_request": false,
"approvers": [],
"approver_groups": []
}`)
})
approvals, _, err := client.Projects.GetApprovalsConfigurationOptions(1)
if err != nil {
t.Errorf("Projects.GetApprovalsConfigurationOptions returned error: %v", err)
}
want := &ProjectApprovals{
ApprovalsBeforeMerge: 3,
ResetApprovalsOnPush: false,
DisableOverridingApproversPerMergeRequest: false,
Approvers: []*MergeRequestApproverUser{},
ApproverGroups: []*MergeRequestApproverGroup{},
}
if !reflect.DeepEqual(want, approvals) {
t.Errorf("Projects.GetApprovalsConfigurationOptions returned %+v, want %+v", approvals, want)
}
}
func TestChangeApprovalsConfigurationOptions(t *testing.T) {
mux, server, client := setup()
defer teardown(server)
mux.HandleFunc("/api/v4/projects/1/approvals", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "POST")
testBody(t, r, `{"approvals_before_merge":3}`)
fmt.Fprint(w, `{
"approvals_before_merge": 3,
"reset_approvals_on_push": false,
"disable_overriding_approvers_per_merge_request": false,
"approvers": [],
"approver_groups": []
}`)
})
opt := &ApprovalsConfigurationOptions{
ApprovalsBeforeMerge: Int(3),
}
approvals, _, err := client.Projects.ChangeApprovalsConfigurationOptions(1, opt)
if err != nil {
t.Errorf("Projects.ChangeApprovalConfigurationOptions returned error: %v", err)
}
want := &ProjectApprovals{
ApprovalsBeforeMerge: 3,
ResetApprovalsOnPush: false,
DisableOverridingApproversPerMergeRequest: false,
Approvers: []*MergeRequestApproverUser{},
ApproverGroups: []*MergeRequestApproverGroup{},
}
if !reflect.DeepEqual(want, approvals) {
t.Errorf("Projects.ChangeApprovalConfigurationOptions returned %+v, want %+v", approvals, want)
}
}
func TestChangeApproversConfigurationOptions(t *testing.T) {
mux, server, client := setup()
defer teardown(server)
mux.HandleFunc("/api/v4/projects/1/approvers", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "POST")
testBody(t, r, `{"approver_ids":[1],"approver_group_ids":[2]}`)
fmt.Fprint(w, `{
"approvers": [{"user":{"id":1}}],
"approver_groups": [{"group":{"id":2}}]
}`)
})
opt := &ApproversConfigurationOptions{
ApproverIDs: []*int{Int(1)},
ApproverGroupIDs: []*int{Int(2)},
}
approvals, _, err := client.Projects.ChangeApproversConfigurationOptions(1, opt)
if err != nil {
t.Errorf("Projects.ChangeApproversConfigurationOptions returned error: %v", err)
}
want := &ProjectApprovals{
Approvers: []*MergeRequestApproverUser{
&MergeRequestApproverUser{
User: struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
State string `json:"state"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
}{
ID: 1,
},
},
},
ApproverGroups: []*MergeRequestApproverGroup{
&MergeRequestApproverGroup{
Group: struct {
ID int `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Description string `json:"description"`
Visibility string `json:"visibility"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
FullName string `json:"full_name"`
FullPath string `json:"full_path"`
LFSEnabled bool `json:"lfs_enabled"`
RequestAccessEnabled bool `json:"request_access_enabled"`
}{
ID: 2,
},
},
},
}
if !reflect.DeepEqual(want, approvals) {
t.Errorf("Projects.ChangeApproversConfigurationOptions returned %+v, want %+v", approvals, want)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment