##// END OF EJS Templates
reviewers: added validation and default review rules via API calls....
dan -
r1795:4b1dac88 default
parent child Browse files
Show More
@@ -77,7 +77,7 b' class TestCreatePullRequestApi(object):'
77 assert pull_request.source_repo.repo_name == data['source_repo']
77 assert pull_request.source_repo.repo_name == data['source_repo']
78 assert pull_request.target_repo.repo_name == data['target_repo']
78 assert pull_request.target_repo.repo_name == data['target_repo']
79 assert pull_request.revisions == [self.commit_ids['change']]
79 assert pull_request.revisions == [self.commit_ids['change']]
80 assert pull_request.reviewers == []
80 assert len(pull_request.reviewers) == 1
81
81
82 @pytest.mark.backends("git", "hg")
82 @pytest.mark.backends("git", "hg")
83 def test_create_with_empty_description(self, backend):
83 def test_create_with_empty_description(self, backend):
@@ -482,24 +482,26 b' def create_pull_request('
482 :param description: Set the pull request description.
482 :param description: Set the pull request description.
483 :type description: Optional(str)
483 :type description: Optional(str)
484 :param reviewers: Set the new pull request reviewers list.
484 :param reviewers: Set the new pull request reviewers list.
485 Reviewer defined by review rules will be added automatically to the
486 defined list.
485 :type reviewers: Optional(list)
487 :type reviewers: Optional(list)
486 Accepts username strings or objects of the format:
488 Accepts username strings or objects of the format:
487
489
488 {'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}
490 [{'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}]
489 """
491 """
490
492
491 source = get_repo_or_error(source_repo)
493 source_db_repo = get_repo_or_error(source_repo)
492 target = get_repo_or_error(target_repo)
494 target_db_repo = get_repo_or_error(target_repo)
493 if not has_superadmin_permission(apiuser):
495 if not has_superadmin_permission(apiuser):
494 _perms = ('repository.admin', 'repository.write', 'repository.read',)
496 _perms = ('repository.admin', 'repository.write', 'repository.read',)
495 validate_repo_permissions(apiuser, source_repo, source, _perms)
497 validate_repo_permissions(apiuser, source_repo, source_db_repo, _perms)
496
498
497 full_source_ref = resolve_ref_or_error(source_ref, source)
499 full_source_ref = resolve_ref_or_error(source_ref, source_db_repo)
498 full_target_ref = resolve_ref_or_error(target_ref, target)
500 full_target_ref = resolve_ref_or_error(target_ref, target_db_repo)
499 source_commit = get_commit_or_error(full_source_ref, source)
501 source_commit = get_commit_or_error(full_source_ref, source_db_repo)
500 target_commit = get_commit_or_error(full_target_ref, target)
502 target_commit = get_commit_or_error(full_target_ref, target_db_repo)
501 source_scm = source.scm_instance()
503 source_scm = source_db_repo.scm_instance()
502 target_scm = target.scm_instance()
504 target_scm = target_db_repo.scm_instance()
503
505
504 commit_ranges = target_scm.compare(
506 commit_ranges = target_scm.compare(
505 target_commit.raw_id, source_commit.raw_id, source_scm,
507 target_commit.raw_id, source_commit.raw_id, source_scm,
@@ -515,6 +517,7 b' def create_pull_request('
515 raise JSONRPCError('no common ancestor found')
517 raise JSONRPCError('no common ancestor found')
516
518
517 reviewer_objects = Optional.extract(reviewers) or []
519 reviewer_objects = Optional.extract(reviewers) or []
520
518 if reviewer_objects:
521 if reviewer_objects:
519 schema = ReviewerListSchema()
522 schema = ReviewerListSchema()
520 try:
523 try:
@@ -522,12 +525,28 b' def create_pull_request('
522 except Invalid as err:
525 except Invalid as err:
523 raise JSONRPCValidationError(colander_exc=err)
526 raise JSONRPCValidationError(colander_exc=err)
524
527
525 reviewers = []
528 # validate users
526 for reviewer_object in reviewer_objects:
529 for reviewer_object in reviewer_objects:
527 user = get_user_or_error(reviewer_object['username'])
530 user = get_user_or_error(reviewer_object['username'])
528 reasons = reviewer_object['reasons']
531 reviewer_object['user_id'] = user.user_id
529 mandatory = reviewer_object['mandatory']
532
530 reviewers.append((user.user_id, reasons, mandatory))
533 get_default_reviewers_data, get_validated_reviewers = \
534 PullRequestModel().get_reviewer_functions()
535
536 reviewer_rules = get_default_reviewers_data(
537 apiuser.get_instance(), source_db_repo,
538 source_commit, target_db_repo, target_commit)
539
540 # specified rules are later re-validated, thus we can assume users will
541 # eventually provide those that meet the reviewer criteria.
542 if not reviewer_objects:
543 reviewer_objects = reviewer_rules['reviewers']
544
545 try:
546 reviewers = get_validated_reviewers(
547 reviewer_objects, reviewer_rules)
548 except ValueError as e:
549 raise JSONRPCError('Reviewers Validation: {}'.format(e))
531
550
532 pull_request_model = PullRequestModel()
551 pull_request_model = PullRequestModel()
533 pull_request = pull_request_model.create(
552 pull_request = pull_request_model.create(
@@ -573,7 +592,7 b' def update_pull_request('
573 :type reviewers: Optional(list)
592 :type reviewers: Optional(list)
574 Accepts username strings or objects of the format:
593 Accepts username strings or objects of the format:
575
594
576 {'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}
595 [{'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}]
577
596
578 :param update_commits: Trigger update of commits for this pull request
597 :param update_commits: Trigger update of commits for this pull request
579 :type: update_commits: Optional(bool)
598 :type: update_commits: Optional(bool)
@@ -619,6 +638,7 b' def update_pull_request('
619 pullrequestid,))
638 pullrequestid,))
620
639
621 reviewer_objects = Optional.extract(reviewers) or []
640 reviewer_objects = Optional.extract(reviewers) or []
641
622 if reviewer_objects:
642 if reviewer_objects:
623 schema = ReviewerListSchema()
643 schema = ReviewerListSchema()
624 try:
644 try:
@@ -626,12 +646,23 b' def update_pull_request('
626 except Invalid as err:
646 except Invalid as err:
627 raise JSONRPCValidationError(colander_exc=err)
647 raise JSONRPCValidationError(colander_exc=err)
628
648
629 reviewers = []
649 # validate users
630 for reviewer_object in reviewer_objects:
650 for reviewer_object in reviewer_objects:
631 user = get_user_or_error(reviewer_object['username'])
651 user = get_user_or_error(reviewer_object['username'])
632 reasons = reviewer_object['reasons']
652 reviewer_object['user_id'] = user.user_id
633 mandatory = reviewer_object['mandatory']
653
634 reviewers.append((user.user_id, reasons, mandatory))
654 get_default_reviewers_data, get_validated_reviewers = \
655 PullRequestModel().get_reviewer_functions()
656
657 # re-use stored rules
658 reviewer_rules = pull_request.reviewer_data
659 try:
660 reviewers = get_validated_reviewers(
661 reviewer_objects, reviewer_rules)
662 except ValueError as e:
663 raise JSONRPCError('Reviewers Validation: {}'.format(e))
664 else:
665 reviewers = []
635
666
636 title = Optional.extract(title)
667 title = Optional.extract(title)
637 description = Optional.extract(description)
668 description = Optional.extract(description)
@@ -264,8 +264,8 b' class PullrequestsController(BaseRepoCon'
264 c.rhodecode_user.get_instance(), source_db_repo,
264 c.rhodecode_user.get_instance(), source_db_repo,
265 source_commit, target_db_repo, target_commit)
265 source_commit, target_db_repo, target_commit)
266
266
267 reviewers = validate_default_reviewers(
267 given_reviewers = _form['review_members']
268 _form['review_members'], reviewer_rules)
268 reviewers = validate_default_reviewers(given_reviewers, reviewer_rules)
269
269
270 try:
270 try:
271 pull_request = PullRequestModel().create(
271 pull_request = PullRequestModel().create(
@@ -452,7 +452,7 b' class PullrequestsController(BaseRepoCon'
452 try:
452 try:
453 reviewers = validate_default_reviewers(review_members, reviewer_rules)
453 reviewers = validate_default_reviewers(review_members, reviewer_rules)
454 except ValueError as e:
454 except ValueError as e:
455 log.error('Reviewers Validation:{}'.format(e))
455 log.error('Reviewers Validation: {}'.format(e))
456 h.flash(e, category='error')
456 h.flash(e, category='error')
457 return
457 return
458
458
@@ -1248,12 +1248,19 b' def initials_gravatar(email_address, fir'
1248 return klass.generate_svg(svg_type=svg_type)
1248 return klass.generate_svg(svg_type=svg_type)
1249
1249
1250
1250
1251 def gravatar_url(email_address, size=30):
1251 def gravatar_url(email_address, size=30, request=None):
1252 # doh, we need to re-import those to mock it later
1252 request = get_current_request()
1253 from pylons import tmpl_context as c
1253 if request and hasattr(request, 'call_context'):
1254 _use_gravatar = request.call_context.visual.use_gravatar
1255 _gravatar_url = request.call_context.visual.gravatar_url
1256 else:
1257 # doh, we need to re-import those to mock it later
1258 from pylons import tmpl_context as c
1254
1259
1255 _use_gravatar = c.visual.use_gravatar
1260 _use_gravatar = c.visual.use_gravatar
1256 _gravatar_url = c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL
1261 _gravatar_url = c.visual.gravatar_url
1262
1263 _gravatar_url = _gravatar_url or User.DEFAULT_GRAVATAR_URL
1257
1264
1258 email_address = email_address or User.DEFAULT_USER_EMAIL
1265 email_address = email_address or User.DEFAULT_USER_EMAIL
1259 if isinstance(email_address, unicode):
1266 if isinstance(email_address, unicode):
@@ -24,7 +24,7 b' from rhodecode.model.validation_schema i'
24
24
25 class ReviewerSchema(colander.MappingSchema):
25 class ReviewerSchema(colander.MappingSchema):
26 username = colander.SchemaNode(types.StrOrIntType())
26 username = colander.SchemaNode(types.StrOrIntType())
27 reasons = colander.SchemaNode(colander.List(), missing=[])
27 reasons = colander.SchemaNode(colander.List(), missing=['no reason specified'])
28 mandatory = colander.SchemaNode(colander.Boolean(), missing=False)
28 mandatory = colander.SchemaNode(colander.Boolean(), missing=False)
29
29
30
30
General Comments 0
You need to be logged in to leave comments. Login now