@@ -2996,13 +2996,18 @@ class ProjectMergeRequestApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTMan
2996
2996
2997
2997
@exc .on_http_error (exc .GitlabUpdateError )
2998
2998
def set_approvers (
2999
- self , approvals_required , approver_ids = None , approver_group_ids = None , ** kwargs
2999
+ self ,
3000
+ approvals_required ,
3001
+ approver_ids = None ,
3002
+ approver_group_ids = None ,
3003
+ approval_rule_name = "name" ,
3004
+ ** kwargs
3000
3005
):
3001
3006
"""Change MR-level allowed approvers and approver groups.
3002
3007
3003
3008
Args:
3004
3009
approvals_required (integer): The number of required approvals for this rule
3005
- approver_ids (list): User IDs that can approve MRs
3010
+ approver_ids (list of integers ): User IDs that can approve MRs
3006
3011
approver_group_ids (list): Group IDs whose members can approve MRs
3007
3012
3008
3013
Raises:
@@ -3012,18 +3017,93 @@ def set_approvers(
3012
3017
approver_ids = approver_ids or []
3013
3018
approver_group_ids = approver_group_ids or []
3014
3019
3015
- path = "%s/%s/approval_rules" % (
3016
- self ._parent .manager .path ,
3017
- self ._parent .get_id (),
3018
- )
3019
3020
data = {
3020
- "name" : "name" ,
3021
+ "name" : approval_rule_name ,
3021
3022
"approvals_required" : approvals_required ,
3022
3023
"rule_type" : "regular" ,
3023
3024
"user_ids" : approver_ids ,
3024
3025
"group_ids" : approver_group_ids ,
3025
3026
}
3026
- self .gitlab .http_post (path , post_data = data , ** kwargs )
3027
+ approval_rules = self ._parent .approval_rules
3028
+ """ update any existing approval rule matching the name"""
3029
+ existing_approval_rules = approval_rules .list ()
3030
+ for ar in existing_approval_rules :
3031
+ if ar .name == approval_rule_name :
3032
+ ar .user_ids = data ["user_ids" ]
3033
+ ar .approvals_required = data ["approvals_required" ]
3034
+ ar .group_ids = data ["group_ids" ]
3035
+ ar .save ()
3036
+ return
3037
+ """ if there was no rule matching the rule name, create a new one"""
3038
+ approval_rules .create (data = data )
3039
+
3040
+
3041
+ class ProjectMergeRequestApprovalRule (SaveMixin , RESTObject ):
3042
+ _id_attr = "approval_rule_id"
3043
+ _short_print_attr = "approval_rule"
3044
+
3045
+ @exc .on_http_error (exc .GitlabUpdateError )
3046
+ def save (self , ** kwargs ):
3047
+ """Save the changes made to the object to the server.
3048
+
3049
+ The object is updated to match what the server returns.
3050
+
3051
+ Args:
3052
+ **kwargs: Extra options to send to the server (e.g. sudo)
3053
+
3054
+ Raise:
3055
+ GitlabAuthenticationError: If authentication is not correct
3056
+ GitlabUpdateError: If the server cannot perform the request
3057
+ """
3058
+ # There is a mismatch between the name of our id attribute and the put REST API name for the
3059
+ # project_id, so we override it here.
3060
+ self .approval_rule_id = self .id
3061
+ self .merge_request_iid = self ._parent_attrs ["mr_iid" ]
3062
+ self .id = self ._parent_attrs ["project_id" ]
3063
+ # save will update self.id with the result from the server, so no need to overwrite with
3064
+ # what it was before we overwrote it."""
3065
+ SaveMixin .save (self , ** kwargs )
3066
+
3067
+
3068
+ class ProjectMergeRequestApprovalRuleManager (
3069
+ ListMixin , UpdateMixin , CreateMixin , RESTManager
3070
+ ):
3071
+ _path = "/projects/%(project_id)s/merge_requests/%(mr_iid)s/approval_rules"
3072
+ _obj_cls = ProjectMergeRequestApprovalRule
3073
+ _from_parent_attrs = {"project_id" : "project_id" , "mr_iid" : "iid" }
3074
+ _list_filters = ("name" , "rule_type" )
3075
+ _update_attrs = (
3076
+ ("id" , "merge_request_iid" , "approval_rule_id" , "name" , "approvals_required" ),
3077
+ ("user_ids" , "group_ids" ),
3078
+ )
3079
+ # Important: When approval_project_rule_id is set, the name, users and groups of
3080
+ # project-level rule will be copied. The approvals_required specified will be used. """
3081
+ _create_attrs = (
3082
+ ("id" , "merge_request_iid" , "name" , "approvals_required" ),
3083
+ ("approval_project_rule_id" , "user_ids" , "group_ids" ),
3084
+ )
3085
+
3086
+ def create (self , data , ** kwargs ):
3087
+ """Create a new object.
3088
+
3089
+ Args:
3090
+ data (dict): Parameters to send to the server to create the
3091
+ resource
3092
+ **kwargs: Extra options to send to the server (e.g. sudo or
3093
+ 'ref_name', 'stage', 'name', 'all')
3094
+
3095
+ Raises:
3096
+ GitlabAuthenticationError: If authentication is not correct
3097
+ GitlabCreateError: If the server cannot perform the request
3098
+
3099
+ Returns:
3100
+ RESTObject: A new instance of the manage object class build with
3101
+ the data sent by the server
3102
+ """
3103
+ new_data = data .copy ()
3104
+ new_data ["id" ] = self ._from_parent_attrs ["project_id" ]
3105
+ new_data ["merge_request_iid" ] = self ._from_parent_attrs ["mr_iid" ]
3106
+ return CreateMixin .create (self , new_data , ** kwargs )
3027
3107
3028
3108
3029
3109
class ProjectMergeRequestAwardEmoji (ObjectDeleteMixin , RESTObject ):
@@ -3149,6 +3229,7 @@ class ProjectMergeRequest(
3149
3229
3150
3230
_managers = (
3151
3231
("approvals" , "ProjectMergeRequestApprovalManager" ),
3232
+ ("approval_rules" , "ProjectMergeRequestApprovalRuleManager" ),
3152
3233
("awardemojis" , "ProjectMergeRequestAwardEmojiManager" ),
3153
3234
("diffs" , "ProjectMergeRequestDiffManager" ),
3154
3235
("discussions" , "ProjectMergeRequestDiscussionManager" ),
0 commit comments