...

Source file src/github.com/xanzy/go-gitlab/merge_request_approvals.go

Documentation: github.com/xanzy/go-gitlab

     1  //
     2  // Copyright 2021, Sander van Harmelen
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package gitlab
    18  
    19  import (
    20  	"fmt"
    21  	"net/http"
    22  	"time"
    23  )
    24  
    25  // MergeRequestApprovalsService handles communication with the merge request
    26  // approvals related methods of the GitLab API. This includes reading/updating
    27  // approval settings and approve/unapproving merge requests
    28  //
    29  // GitLab API docs: https://docs.gitlab.com/ee/api/merge_request_approvals.html
    30  type MergeRequestApprovalsService struct {
    31  	client *Client
    32  }
    33  
    34  // MergeRequestApprovals represents GitLab merge request approvals.
    35  //
    36  // GitLab API docs:
    37  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#merge-request-level-mr-approvals
    38  type MergeRequestApprovals struct {
    39  	ID                             int                          `json:"id"`
    40  	IID                            int                          `json:"iid"`
    41  	ProjectID                      int                          `json:"project_id"`
    42  	Title                          string                       `json:"title"`
    43  	Description                    string                       `json:"description"`
    44  	State                          string                       `json:"state"`
    45  	CreatedAt                      *time.Time                   `json:"created_at"`
    46  	UpdatedAt                      *time.Time                   `json:"updated_at"`
    47  	MergeStatus                    string                       `json:"merge_status"`
    48  	Approved                       bool                         `json:"approved"`
    49  	ApprovalsBeforeMerge           int                          `json:"approvals_before_merge"`
    50  	ApprovalsRequired              int                          `json:"approvals_required"`
    51  	ApprovalsLeft                  int                          `json:"approvals_left"`
    52  	RequirePasswordToApprove       bool                         `json:"require_password_to_approve"`
    53  	ApprovedBy                     []*MergeRequestApproverUser  `json:"approved_by"`
    54  	SuggestedApprovers             []*BasicUser                 `json:"suggested_approvers"`
    55  	Approvers                      []*MergeRequestApproverUser  `json:"approvers"`
    56  	ApproverGroups                 []*MergeRequestApproverGroup `json:"approver_groups"`
    57  	UserHasApproved                bool                         `json:"user_has_approved"`
    58  	UserCanApprove                 bool                         `json:"user_can_approve"`
    59  	ApprovalRulesLeft              []*MergeRequestApprovalRule  `json:"approval_rules_left"`
    60  	HasApprovalRules               bool                         `json:"has_approval_rules"`
    61  	MergeRequestApproversAvailable bool                         `json:"merge_request_approvers_available"`
    62  	MultipleApprovalRulesAvailable bool                         `json:"multiple_approval_rules_available"`
    63  }
    64  
    65  func (m MergeRequestApprovals) String() string {
    66  	return Stringify(m)
    67  }
    68  
    69  // MergeRequestApproverGroup  represents GitLab project level merge request approver group.
    70  //
    71  // GitLab API docs:
    72  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
    73  type MergeRequestApproverGroup struct {
    74  	Group struct {
    75  		ID                   int    `json:"id"`
    76  		Name                 string `json:"name"`
    77  		Path                 string `json:"path"`
    78  		Description          string `json:"description"`
    79  		Visibility           string `json:"visibility"`
    80  		AvatarURL            string `json:"avatar_url"`
    81  		WebURL               string `json:"web_url"`
    82  		FullName             string `json:"full_name"`
    83  		FullPath             string `json:"full_path"`
    84  		LFSEnabled           bool   `json:"lfs_enabled"`
    85  		RequestAccessEnabled bool   `json:"request_access_enabled"`
    86  	}
    87  }
    88  
    89  // MergeRequestApprovalRule represents a GitLab merge request approval rule.
    90  //
    91  // GitLab API docs:
    92  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-merge-request-level-rules
    93  type MergeRequestApprovalRule struct {
    94  	ID                   int                  `json:"id"`
    95  	Name                 string               `json:"name"`
    96  	RuleType             string               `json:"rule_type"`
    97  	EligibleApprovers    []*BasicUser         `json:"eligible_approvers"`
    98  	ApprovalsRequired    int                  `json:"approvals_required"`
    99  	SourceRule           *ProjectApprovalRule `json:"source_rule"`
   100  	Users                []*BasicUser         `json:"users"`
   101  	Groups               []*Group             `json:"groups"`
   102  	ContainsHiddenGroups bool                 `json:"contains_hidden_groups"`
   103  	Section              string               `json:"section"`
   104  	ApprovedBy           []*BasicUser         `json:"approved_by"`
   105  	Approved             bool                 `json:"approved"`
   106  }
   107  
   108  // MergeRequestApprovalState represents a GitLab merge request approval state.
   109  //
   110  // GitLab API docs:
   111  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-the-approval-state-of-merge-requests
   112  type MergeRequestApprovalState struct {
   113  	ApprovalRulesOverwritten bool                        `json:"approval_rules_overwritten"`
   114  	Rules                    []*MergeRequestApprovalRule `json:"rules"`
   115  }
   116  
   117  // String is a stringify for MergeRequestApprovalRule
   118  func (s MergeRequestApprovalRule) String() string {
   119  	return Stringify(s)
   120  }
   121  
   122  // MergeRequestApproverUser  represents GitLab project level merge request approver user.
   123  //
   124  // GitLab API docs:
   125  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
   126  type MergeRequestApproverUser struct {
   127  	User *BasicUser
   128  }
   129  
   130  // ApproveMergeRequestOptions represents the available ApproveMergeRequest() options.
   131  //
   132  // GitLab API docs:
   133  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#approve-merge-request
   134  type ApproveMergeRequestOptions struct {
   135  	SHA *string `url:"sha,omitempty" json:"sha,omitempty"`
   136  }
   137  
   138  // ApproveMergeRequest approves a merge request on GitLab. If a non-empty sha
   139  // is provided then it must match the sha at the HEAD of the MR.
   140  //
   141  // GitLab API docs:
   142  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#approve-merge-request
   143  func (s *MergeRequestApprovalsService) ApproveMergeRequest(pid interface{}, mr int, opt *ApproveMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) {
   144  	project, err := parseID(pid)
   145  	if err != nil {
   146  		return nil, nil, err
   147  	}
   148  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approve", PathEscape(project), mr)
   149  
   150  	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
   151  	if err != nil {
   152  		return nil, nil, err
   153  	}
   154  
   155  	m := new(MergeRequestApprovals)
   156  	resp, err := s.client.Do(req, m)
   157  	if err != nil {
   158  		return nil, resp, err
   159  	}
   160  
   161  	return m, resp, nil
   162  }
   163  
   164  // UnapproveMergeRequest unapproves a previously approved merge request on GitLab.
   165  //
   166  // GitLab API docs:
   167  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#unapprove-merge-request
   168  func (s *MergeRequestApprovalsService) UnapproveMergeRequest(pid interface{}, mr int, options ...RequestOptionFunc) (*Response, error) {
   169  	project, err := parseID(pid)
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  	u := fmt.Sprintf("projects/%s/merge_requests/%d/unapprove", PathEscape(project), mr)
   174  
   175  	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
   176  	if err != nil {
   177  		return nil, err
   178  	}
   179  
   180  	return s.client.Do(req, nil)
   181  }
   182  
   183  // ResetApprovalsOfMergeRequest clear all approvals of merge request on GitLab.
   184  // Available only for bot users based on project or group tokens.
   185  //
   186  // GitLab API docs:
   187  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#reset-approvals-of-a-merge-request
   188  func (s *MergeRequestApprovalsService) ResetApprovalsOfMergeRequest(pid interface{}, mr int, options ...RequestOptionFunc) (*Response, error) {
   189  	project, err := parseID(pid)
   190  	if err != nil {
   191  		return nil, err
   192  	}
   193  	u := fmt.Sprintf("projects/%s/merge_requests/%d/reset_approvals", PathEscape(project), mr)
   194  
   195  	req, err := s.client.NewRequest(http.MethodPut, u, nil, options)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	return s.client.Do(req, nil)
   201  }
   202  
   203  // ChangeMergeRequestApprovalConfigurationOptions represents the available
   204  // ChangeMergeRequestApprovalConfiguration() options.
   205  //
   206  // GitLab API docs:
   207  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-approval-configuration-deprecated
   208  type ChangeMergeRequestApprovalConfigurationOptions struct {
   209  	ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"`
   210  }
   211  
   212  // GetConfiguration shows information about single merge request approvals
   213  //
   214  // GitLab API docs:
   215  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-configuration-1
   216  func (s *MergeRequestApprovalsService) GetConfiguration(pid interface{}, mr int, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) {
   217  	project, err := parseID(pid)
   218  	if err != nil {
   219  		return nil, nil, err
   220  	}
   221  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approvals", PathEscape(project), mr)
   222  
   223  	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
   224  	if err != nil {
   225  		return nil, nil, err
   226  	}
   227  
   228  	m := new(MergeRequestApprovals)
   229  	resp, err := s.client.Do(req, m)
   230  	if err != nil {
   231  		return nil, resp, err
   232  	}
   233  
   234  	return m, resp, nil
   235  }
   236  
   237  // ChangeApprovalConfiguration updates the approval configuration of a merge request.
   238  //
   239  // GitLab API docs:
   240  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-approval-configuration-deprecated
   241  func (s *MergeRequestApprovalsService) ChangeApprovalConfiguration(pid interface{}, mergeRequest int, opt *ChangeMergeRequestApprovalConfigurationOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   242  	project, err := parseID(pid)
   243  	if err != nil {
   244  		return nil, nil, err
   245  	}
   246  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approvals", PathEscape(project), mergeRequest)
   247  
   248  	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
   249  	if err != nil {
   250  		return nil, nil, err
   251  	}
   252  
   253  	m := new(MergeRequest)
   254  	resp, err := s.client.Do(req, m)
   255  	if err != nil {
   256  		return nil, resp, err
   257  	}
   258  
   259  	return m, resp, nil
   260  }
   261  
   262  // ChangeMergeRequestAllowedApproversOptions represents the available
   263  // ChangeMergeRequestAllowedApprovers() options.
   264  //
   265  // GitLab API docs:
   266  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers-for-merge-request
   267  type ChangeMergeRequestAllowedApproversOptions struct {
   268  	ApproverIDs      []int `url:"approver_ids" json:"approver_ids"`
   269  	ApproverGroupIDs []int `url:"approver_group_ids" json:"approver_group_ids"`
   270  }
   271  
   272  // ChangeAllowedApprovers updates the approvers for a merge request.
   273  //
   274  // GitLab API docs:
   275  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers-for-merge-request
   276  func (s *MergeRequestApprovalsService) ChangeAllowedApprovers(pid interface{}, mergeRequest int, opt *ChangeMergeRequestAllowedApproversOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
   277  	project, err := parseID(pid)
   278  	if err != nil {
   279  		return nil, nil, err
   280  	}
   281  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approvers", PathEscape(project), mergeRequest)
   282  
   283  	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
   284  	if err != nil {
   285  		return nil, nil, err
   286  	}
   287  
   288  	m := new(MergeRequest)
   289  	resp, err := s.client.Do(req, m)
   290  	if err != nil {
   291  		return nil, resp, err
   292  	}
   293  
   294  	return m, resp, nil
   295  }
   296  
   297  // GetApprovalRules requests information about a merge request’s approval rules
   298  //
   299  // GitLab API docs:
   300  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-merge-request-level-rules
   301  func (s *MergeRequestApprovalsService) GetApprovalRules(pid interface{}, mergeRequest int, options ...RequestOptionFunc) ([]*MergeRequestApprovalRule, *Response, error) {
   302  	project, err := parseID(pid)
   303  	if err != nil {
   304  		return nil, nil, err
   305  	}
   306  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_rules", PathEscape(project), mergeRequest)
   307  
   308  	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
   309  	if err != nil {
   310  		return nil, nil, err
   311  	}
   312  
   313  	var par []*MergeRequestApprovalRule
   314  	resp, err := s.client.Do(req, &par)
   315  	if err != nil {
   316  		return nil, resp, err
   317  	}
   318  
   319  	return par, resp, nil
   320  }
   321  
   322  // GetApprovalState requests information about a merge request’s approval state
   323  //
   324  // GitLab API docs:
   325  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-the-approval-state-of-merge-requests
   326  func (s *MergeRequestApprovalsService) GetApprovalState(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*MergeRequestApprovalState, *Response, error) {
   327  	project, err := parseID(pid)
   328  	if err != nil {
   329  		return nil, nil, err
   330  	}
   331  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_state", PathEscape(project), mergeRequest)
   332  
   333  	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
   334  	if err != nil {
   335  		return nil, nil, err
   336  	}
   337  
   338  	var pas *MergeRequestApprovalState
   339  	resp, err := s.client.Do(req, &pas)
   340  	if err != nil {
   341  		return nil, resp, err
   342  	}
   343  
   344  	return pas, resp, nil
   345  }
   346  
   347  // CreateMergeRequestApprovalRuleOptions represents the available CreateApprovalRule()
   348  // options.
   349  //
   350  // GitLab API docs:
   351  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-merge-request-level-rule
   352  type CreateMergeRequestApprovalRuleOptions struct {
   353  	Name                  *string `url:"name,omitempty" json:"name,omitempty"`
   354  	ApprovalsRequired     *int    `url:"approvals_required,omitempty" json:"approvals_required,omitempty"`
   355  	ApprovalProjectRuleID *int    `url:"approval_project_rule_id,omitempty" json:"approval_project_rule_id,omitempty"`
   356  	UserIDs               *[]int  `url:"user_ids,omitempty" json:"user_ids,omitempty"`
   357  	GroupIDs              *[]int  `url:"group_ids,omitempty" json:"group_ids,omitempty"`
   358  }
   359  
   360  // CreateApprovalRule creates a new MR level approval rule.
   361  //
   362  // GitLab API docs:
   363  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-merge-request-level-rule
   364  func (s *MergeRequestApprovalsService) CreateApprovalRule(pid interface{}, mergeRequest int, opt *CreateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) {
   365  	project, err := parseID(pid)
   366  	if err != nil {
   367  		return nil, nil, err
   368  	}
   369  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_rules", PathEscape(project), mergeRequest)
   370  
   371  	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
   372  	if err != nil {
   373  		return nil, nil, err
   374  	}
   375  
   376  	par := new(MergeRequestApprovalRule)
   377  	resp, err := s.client.Do(req, &par)
   378  	if err != nil {
   379  		return nil, resp, err
   380  	}
   381  
   382  	return par, resp, nil
   383  }
   384  
   385  // UpdateMergeRequestApprovalRuleOptions represents the available UpdateApprovalRule()
   386  // options.
   387  //
   388  // GitLab API docs:
   389  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#update-merge-request-level-rule
   390  type UpdateMergeRequestApprovalRuleOptions struct {
   391  	Name              *string `url:"name,omitempty" json:"name,omitempty"`
   392  	ApprovalsRequired *int    `url:"approvals_required,omitempty" json:"approvals_required,omitempty"`
   393  	UserIDs           *[]int  `url:"user_ids,omitempty" json:"user_ids,omitempty"`
   394  	GroupIDs          *[]int  `url:"group_ids,omitempty" json:"group_ids,omitempty"`
   395  }
   396  
   397  // UpdateApprovalRule updates an existing approval rule with new options.
   398  //
   399  // GitLab API docs:
   400  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#update-merge-request-level-rule
   401  func (s *MergeRequestApprovalsService) UpdateApprovalRule(pid interface{}, mergeRequest int, approvalRule int, opt *UpdateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) {
   402  	project, err := parseID(pid)
   403  	if err != nil {
   404  		return nil, nil, err
   405  	}
   406  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_rules/%d", PathEscape(project), mergeRequest, approvalRule)
   407  
   408  	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
   409  	if err != nil {
   410  		return nil, nil, err
   411  	}
   412  
   413  	par := new(MergeRequestApprovalRule)
   414  	resp, err := s.client.Do(req, &par)
   415  	if err != nil {
   416  		return nil, resp, err
   417  	}
   418  
   419  	return par, resp, nil
   420  }
   421  
   422  // DeleteApprovalRule deletes a mr level approval rule.
   423  //
   424  // GitLab API docs:
   425  // https://docs.gitlab.com/ee/api/merge_request_approvals.html#delete-merge-request-level-rule
   426  func (s *MergeRequestApprovalsService) DeleteApprovalRule(pid interface{}, mergeRequest int, approvalRule int, options ...RequestOptionFunc) (*Response, error) {
   427  	project, err := parseID(pid)
   428  	if err != nil {
   429  		return nil, err
   430  	}
   431  	u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_rules/%d", PathEscape(project), mergeRequest, approvalRule)
   432  
   433  	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
   434  	if err != nil {
   435  		return nil, err
   436  	}
   437  
   438  	return s.client.Do(req, nil)
   439  }
   440  

View as plain text