Repository: xanzy/go-gitlab
Pull request #766 (2020-02-06 02:36:09)

approval state of merge requests
Adds Support for getting the approval state of merge requests

https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-the-approval-state-of-merge-requests


Patch:
diff --git a/merge_request_approvals.go b/merge_request_approvals.go
index ff4ef88..60fd529 100644
--- a/merge_request_approvals.go
+++ b/merge_request_approvals.go
@@ -74,6 +74,17 @@ type MergeRequestApprovalRule struct {
 	Users                []*BasicUser         `json:"users"`
 	Groups               []*Group             `json:"groups"`
 	ContainsHiddenGroups bool                 `json:"contains_hidden_groups"`
+	ApprovedBy           []*BasicUser         `json:"approved_by"`
+	Approved             bool                 `json:"approved"`
+}
+
+// MergeRequestApprovalState represents a GitLab merge request approval state.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-the-approval-state-of-merge-requests
+type MergeRequestApprovalState struct {
+	ApprovalRulesOverwritten bool                        `json:"approval_rules_overwritten"`
+	Rules                    []*MergeRequestApprovalRule `json:"rules"`
 }
 
 // String is a stringify for MergeRequestApprovalRule
@@ -236,6 +247,31 @@ func (s *MergeRequestApprovalsService) GetApprovalRules(pid interface{}, mergeRe
 	return par, resp, err
 }
 
+// GetApprovalState requests information about a merge request’s approval state
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-the-approval-state-of-merge-requests
+func (s *MergeRequestApprovalsService) GetApprovalState(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequestApprovalState, *Response, error) {
+	project, err := parseID(pid)
+	if err != nil {
+		return nil, nil, err
+	}
+	u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_state", pathEscape(project), mergeRequest)
+
+	req, err := s.client.NewRequest("GET", u, nil, options)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var pas *MergeRequestApprovalState
+	resp, err := s.client.Do(req, &pas)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return pas, resp, err
+}
+
 // CreateMergeRequestApprovalRuleOptions represents the available CreateApprovalRule()
 // options.
 //


Test patch:
diff --git a/merge_request_approvals_test.go b/merge_request_approvals_test.go
index d5f0ce0..2f7a415 100644
--- a/merge_request_approvals_test.go
+++ b/merge_request_approvals_test.go
@@ -7,6 +7,160 @@ import (
 	"testing"
 )
 
+func TestGetApprovalState(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	mux.HandleFunc("/api/v4/projects/1/merge_requests/1/approval_state", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{
+			"approval_rules_overwritten": true,
+			"rules": [
+			{
+				"id": 1,
+				"name": "security",
+				"rule_type": "regular",
+				"eligible_approvers": [
+					{
+						"id": 5,
+						"name": "John Doe",
+						"username": "jdoe",
+						"state": "active",
+						"avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon",
+						"web_url": "http://localhost/jdoe"
+					},
+					{
+						"id": 50,
+						"name": "Group Member 1",
+						"username": "group_member_1",
+						"state": "active",
+						"avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon",
+						"web_url": "http://localhost/group_member_1"
+					}
+				],
+				"approvals_required": 3,
+				"source_rule": null,
+				"users": [
+					{
+						"id": 5,
+						"name": "John Doe",
+						"username": "jdoe",
+						"state": "active",
+						"avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon",
+						"web_url": "http://localhost/jdoe"
+					}
+				],
+				"groups": [
+					{
+						"id": 5,
+						"name": "group1",
+						"path": "group1",
+						"description": "",
+						"visibility": "public",
+						"lfs_enabled": false,
+						"avatar_url": null,
+						"web_url": "http://localhost/groups/group1",
+						"request_access_enabled": false,
+						"full_name": "group1",
+						"full_path": "group1",
+						"parent_id": null,
+						"ldap_cn": null,
+						"ldap_access": null
+					}
+				],
+				"contains_hidden_groups": false,
+				"approved_by": [
+					{
+						"id": 5,
+						"name": "John Doe",
+						"username": "jdoe",
+						"state": "active",
+						"avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon",
+						"web_url": "http://localhost/jdoe"
+					}
+				],
+				"approved": false
+			}
+		]
+		}`)
+	})
+
+	approvals, _, err := client.MergeRequestApprovals.GetApprovalState(1, 1)
+	if err != nil {
+		t.Errorf("MergeRequestApprovals.GetApprovalState returned error: %v", err)
+	}
+
+	want := &MergeRequestApprovalState{
+		ApprovalRulesOverwritten: true,
+		Rules: []*MergeRequestApprovalRule{
+			&MergeRequestApprovalRule{
+				ID:       1,
+				Name:     "security",
+				RuleType: "regular",
+				EligibleApprovers: []*BasicUser{
+					&BasicUser{
+						ID:        5,
+						Name:      "John Doe",
+						Username:  "jdoe",
+						State:     "active",
+						AvatarURL: "https://www.gravatar.com/avatar/0?s=80&d=identicon",
+						WebURL:    "http://localhost/jdoe",
+					},
+					&BasicUser{
+						ID:        50,
+						Name:      "Group Member 1",
+						Username:  "group_member_1",
+						State:     "active",
+						AvatarURL: "https://www.gravatar.com/avatar/0?s=80&d=identicon",
+						WebURL:    "http://localhost/group_member_1",
+					},
+				},
+				ApprovalsRequired: 3,
+				Users: []*BasicUser{
+					&BasicUser{
+						ID:        5,
+						Name:      "John Doe",
+						Username:  "jdoe",
+						State:     "active",
+						AvatarURL: "https://www.gravatar.com/avatar/0?s=80&d=identicon",
+						WebURL:    "http://localhost/jdoe",
+					},
+				},
+				Groups: []*Group{
+					&Group{
+						ID:                   5,
+						Name:                 "group1",
+						Path:                 "group1",
+						Description:          "",
+						Visibility:           PublicVisibility,
+						LFSEnabled:           false,
+						AvatarURL:            "",
+						WebURL:               "http://localhost/groups/group1",
+						RequestAccessEnabled: false,
+						FullName:             "group1",
+						FullPath:             "group1",
+					},
+				},
+				ApprovedBy: []*BasicUser{
+					&BasicUser{
+						ID:        5,
+						Name:      "John Doe",
+						Username:  "jdoe",
+						State:     "active",
+						AvatarURL: "https://www.gravatar.com/avatar/0?s=80&d=identicon",
+						WebURL:    "http://localhost/jdoe",
+					},
+				},
+				Approved: false,
+			},
+		},
+	}
+
+	if !reflect.DeepEqual(want, approvals) {
+		t.Errorf("MergeRequestApprovals.GetApprovalState returned %+v, want %+v", approvals, want)
+	}
+}
+
 func TestGetApprovalRules(t *testing.T) {
 	mux, server, client := setup()
 	defer teardown(server)