reviewers: added validation and default review rules via API calls.

- update/create pull request now validate and update the default reviewer rules.
This commit is contained in:
Daniel Dourvaris 2017-06-14 11:10:19 +02:00
parent 930c7eebbd
commit 2beb24a857
5 changed files with 71 additions and 33 deletions

View file

@ -77,7 +77,7 @@ class TestCreatePullRequestApi(object):
assert pull_request.source_repo.repo_name == data['source_repo']
assert pull_request.target_repo.repo_name == data['target_repo']
assert pull_request.revisions == [self.commit_ids['change']]
assert pull_request.reviewers == []
assert len(pull_request.reviewers) == 1
@pytest.mark.backends("git", "hg")
def test_create_with_empty_description(self, backend):

View file

@ -482,24 +482,26 @@ def create_pull_request(
:param description: Set the pull request description.
:type description: Optional(str)
:param reviewers: Set the new pull request reviewers list.
Reviewer defined by review rules will be added automatically to the
defined list.
:type reviewers: Optional(list)
Accepts username strings or objects of the format:
{'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}
[{'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}]
"""
source = get_repo_or_error(source_repo)
target = get_repo_or_error(target_repo)
source_db_repo = get_repo_or_error(source_repo)
target_db_repo = get_repo_or_error(target_repo)
if not has_superadmin_permission(apiuser):
_perms = ('repository.admin', 'repository.write', 'repository.read',)
validate_repo_permissions(apiuser, source_repo, source, _perms)
validate_repo_permissions(apiuser, source_repo, source_db_repo, _perms)
full_source_ref = resolve_ref_or_error(source_ref, source)
full_target_ref = resolve_ref_or_error(target_ref, target)
source_commit = get_commit_or_error(full_source_ref, source)
target_commit = get_commit_or_error(full_target_ref, target)
source_scm = source.scm_instance()
target_scm = target.scm_instance()
full_source_ref = resolve_ref_or_error(source_ref, source_db_repo)
full_target_ref = resolve_ref_or_error(target_ref, target_db_repo)
source_commit = get_commit_or_error(full_source_ref, source_db_repo)
target_commit = get_commit_or_error(full_target_ref, target_db_repo)
source_scm = source_db_repo.scm_instance()
target_scm = target_db_repo.scm_instance()
commit_ranges = target_scm.compare(
target_commit.raw_id, source_commit.raw_id, source_scm,
@ -515,6 +517,7 @@ def create_pull_request(
raise JSONRPCError('no common ancestor found')
reviewer_objects = Optional.extract(reviewers) or []
if reviewer_objects:
schema = ReviewerListSchema()
try:
@ -522,12 +525,28 @@ def create_pull_request(
except Invalid as err:
raise JSONRPCValidationError(colander_exc=err)
reviewers = []
for reviewer_object in reviewer_objects:
user = get_user_or_error(reviewer_object['username'])
reasons = reviewer_object['reasons']
mandatory = reviewer_object['mandatory']
reviewers.append((user.user_id, reasons, mandatory))
# validate users
for reviewer_object in reviewer_objects:
user = get_user_or_error(reviewer_object['username'])
reviewer_object['user_id'] = user.user_id
get_default_reviewers_data, get_validated_reviewers = \
PullRequestModel().get_reviewer_functions()
reviewer_rules = get_default_reviewers_data(
apiuser.get_instance(), source_db_repo,
source_commit, target_db_repo, target_commit)
# specified rules are later re-validated, thus we can assume users will
# eventually provide those that meet the reviewer criteria.
if not reviewer_objects:
reviewer_objects = reviewer_rules['reviewers']
try:
reviewers = get_validated_reviewers(
reviewer_objects, reviewer_rules)
except ValueError as e:
raise JSONRPCError('Reviewers Validation: {}'.format(e))
pull_request_model = PullRequestModel()
pull_request = pull_request_model.create(
@ -573,7 +592,7 @@ def update_pull_request(
:type reviewers: Optional(list)
Accepts username strings or objects of the format:
{'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}
[{'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}]
:param update_commits: Trigger update of commits for this pull request
:type: update_commits: Optional(bool)
@ -619,6 +638,7 @@ def update_pull_request(
pullrequestid,))
reviewer_objects = Optional.extract(reviewers) or []
if reviewer_objects:
schema = ReviewerListSchema()
try:
@ -626,12 +646,23 @@ def update_pull_request(
except Invalid as err:
raise JSONRPCValidationError(colander_exc=err)
reviewers = []
for reviewer_object in reviewer_objects:
user = get_user_or_error(reviewer_object['username'])
reasons = reviewer_object['reasons']
mandatory = reviewer_object['mandatory']
reviewers.append((user.user_id, reasons, mandatory))
# validate users
for reviewer_object in reviewer_objects:
user = get_user_or_error(reviewer_object['username'])
reviewer_object['user_id'] = user.user_id
get_default_reviewers_data, get_validated_reviewers = \
PullRequestModel().get_reviewer_functions()
# re-use stored rules
reviewer_rules = pull_request.reviewer_data
try:
reviewers = get_validated_reviewers(
reviewer_objects, reviewer_rules)
except ValueError as e:
raise JSONRPCError('Reviewers Validation: {}'.format(e))
else:
reviewers = []
title = Optional.extract(title)
description = Optional.extract(description)

View file

@ -264,8 +264,8 @@ class PullrequestsController(BaseRepoController):
c.rhodecode_user.get_instance(), source_db_repo,
source_commit, target_db_repo, target_commit)
reviewers = validate_default_reviewers(
_form['review_members'], reviewer_rules)
given_reviewers = _form['review_members']
reviewers = validate_default_reviewers(given_reviewers, reviewer_rules)
try:
pull_request = PullRequestModel().create(
@ -452,7 +452,7 @@ class PullrequestsController(BaseRepoController):
try:
reviewers = validate_default_reviewers(review_members, reviewer_rules)
except ValueError as e:
log.error('Reviewers Validation:{}'.format(e))
log.error('Reviewers Validation: {}'.format(e))
h.flash(e, category='error')
return

View file

@ -1248,12 +1248,19 @@ def initials_gravatar(email_address, first_name, last_name, size=30):
return klass.generate_svg(svg_type=svg_type)
def gravatar_url(email_address, size=30):
# doh, we need to re-import those to mock it later
from pylons import tmpl_context as c
def gravatar_url(email_address, size=30, request=None):
request = get_current_request()
if request and hasattr(request, 'call_context'):
_use_gravatar = request.call_context.visual.use_gravatar
_gravatar_url = request.call_context.visual.gravatar_url
else:
# doh, we need to re-import those to mock it later
from pylons import tmpl_context as c
_use_gravatar = c.visual.use_gravatar
_gravatar_url = c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL
_use_gravatar = c.visual.use_gravatar
_gravatar_url = c.visual.gravatar_url
_gravatar_url = _gravatar_url or User.DEFAULT_GRAVATAR_URL
email_address = email_address or User.DEFAULT_USER_EMAIL
if isinstance(email_address, unicode):

View file

@ -24,7 +24,7 @@ from rhodecode.model.validation_schema import validators, preparers, types
class ReviewerSchema(colander.MappingSchema):
username = colander.SchemaNode(types.StrOrIntType())
reasons = colander.SchemaNode(colander.List(), missing=[])
reasons = colander.SchemaNode(colander.List(), missing=['no reason specified'])
mandatory = colander.SchemaNode(colander.Boolean(), missing=False)