diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -4002,6 +4002,14 @@ class _PullRequestBase(BaseModel): def reviewer_data_json(self): return json.dumps(self.reviewer_data) + @property + def work_in_progress(self): + """checks if pull request is work in progress by checking the title""" + title = self.title.upper() + if re.match(r'^(\[WIP\]\s*|WIP:\s*|WIP\s+)', title): + return True + return False + @hybrid_property def description_safe(self): from rhodecode.lib import helpers as h diff --git a/rhodecode/model/pull_request.py b/rhodecode/model/pull_request.py --- a/rhodecode/model/pull_request.py +++ b/rhodecode/model/pull_request.py @@ -1614,6 +1614,7 @@ class MergeCheck(object): PERM_CHECK = 'perm' REVIEW_CHECK = 'review' MERGE_CHECK = 'merge' + WIP_CHECK = 'wip' def __init__(self): self.review_status = None @@ -1638,6 +1639,15 @@ class MergeCheck(object): _ = translator merge_check = cls() + # title has WIP: + if pull_request.work_in_progress: + log.debug("MergeCheck: cannot merge, title has wip: marker.") + + msg = _('WIP marker in title prevents from accidental merge.') + merge_check.push_error('error', msg, cls.WIP_CHECK, pull_request.title) + if fail_early: + return merge_check + # permissions to merge user_allowed_to_merge = PullRequestModel().check_user_merge( pull_request, auth_user) diff --git a/rhodecode/tests/models/test_pullrequest.py b/rhodecode/tests/models/test_pullrequest.py --- a/rhodecode/tests/models/test_pullrequest.py +++ b/rhodecode/tests/models/test_pullrequest.py @@ -402,7 +402,7 @@ class TestPullRequestModel(object): assert pull_request.merge_rev is None def test_get_commit_ids(self, pull_request): - # The PR has been not merget yet, so expect an exception + # The PR has been not merged yet, so expect an exception with pytest.raises(ValueError): PullRequestModel()._get_commit_ids(pull_request) @@ -433,6 +433,20 @@ class TestPullRequestModel(object): ) assert type(title) == unicode + @pytest.mark.parametrize('title, has_wip', [ + ('hello', False), + ('hello wip', False), + ('hello wip: xxx', False), + ('[wip] hello', True), + ('[wip] hello', True), + ('wip: hello', True), + ('wip hello', True), + + ]) + def test_wip_title_marker(self, pull_request, title, has_wip): + pull_request.title = title + assert pull_request.work_in_progress == has_wip + @pytest.mark.usefixtures('config_stub') class TestIntegrationMerge(object):