##// END OF EJS Templates
reviewers: use target repo owner as default reviewer in case of CE edition....
marcink -
r3230:3c9caf8e default
parent child Browse files
Show More
@@ -1,342 +1,349 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import pytest
21 import pytest
22
22
23 from rhodecode.model.db import User
23 from rhodecode.model.db import User
24 from rhodecode.model.pull_request import PullRequestModel
24 from rhodecode.model.pull_request import PullRequestModel
25 from rhodecode.model.repo import RepoModel
25 from rhodecode.model.repo import RepoModel
26 from rhodecode.model.user import UserModel
26 from rhodecode.model.user import UserModel
27 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN
27 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN
28 from rhodecode.api.tests.utils import build_data, api_call, assert_error
28 from rhodecode.api.tests.utils import build_data, api_call, assert_error
29
29
30
30
31 @pytest.mark.usefixtures("testuser_api", "app")
31 @pytest.mark.usefixtures("testuser_api", "app")
32 class TestCreatePullRequestApi(object):
32 class TestCreatePullRequestApi(object):
33 finalizers = []
33 finalizers = []
34
34
35 def teardown_method(self, method):
35 def teardown_method(self, method):
36 if self.finalizers:
36 if self.finalizers:
37 for finalizer in self.finalizers:
37 for finalizer in self.finalizers:
38 finalizer()
38 finalizer()
39 self.finalizers = []
39 self.finalizers = []
40
40
41 def test_create_with_wrong_data(self):
41 def test_create_with_wrong_data(self):
42 required_data = {
42 required_data = {
43 'source_repo': 'tests/source_repo',
43 'source_repo': 'tests/source_repo',
44 'target_repo': 'tests/target_repo',
44 'target_repo': 'tests/target_repo',
45 'source_ref': 'branch:default:initial',
45 'source_ref': 'branch:default:initial',
46 'target_ref': 'branch:default:new-feature',
46 'target_ref': 'branch:default:new-feature',
47 }
47 }
48 for key in required_data:
48 for key in required_data:
49 data = required_data.copy()
49 data = required_data.copy()
50 data.pop(key)
50 data.pop(key)
51 id_, params = build_data(
51 id_, params = build_data(
52 self.apikey, 'create_pull_request', **data)
52 self.apikey, 'create_pull_request', **data)
53 response = api_call(self.app, params)
53 response = api_call(self.app, params)
54
54
55 expected = 'Missing non optional `{}` arg in JSON DATA'.format(key)
55 expected = 'Missing non optional `{}` arg in JSON DATA'.format(key)
56 assert_error(id_, expected, given=response.body)
56 assert_error(id_, expected, given=response.body)
57
57
58 @pytest.mark.backends("git", "hg")
58 @pytest.mark.backends("git", "hg")
59 def test_create_with_correct_data(self, backend):
59 def test_create_with_correct_data(self, backend):
60 data = self._prepare_data(backend)
60 data = self._prepare_data(backend)
61 RepoModel().revoke_user_permission(
61 RepoModel().revoke_user_permission(
62 self.source.repo_name, User.DEFAULT_USER)
62 self.source.repo_name, User.DEFAULT_USER)
63 id_, params = build_data(
63 id_, params = build_data(
64 self.apikey_regular, 'create_pull_request', **data)
64 self.apikey_regular, 'create_pull_request', **data)
65 response = api_call(self.app, params)
65 response = api_call(self.app, params)
66 expected_message = "Created new pull request `{title}`".format(
66 expected_message = "Created new pull request `{title}`".format(
67 title=data['title'])
67 title=data['title'])
68 result = response.json
68 result = response.json
69 assert result['error'] == None
69 assert result['error'] is None
70 assert result['result']['msg'] == expected_message
70 assert result['result']['msg'] == expected_message
71 pull_request_id = result['result']['pull_request_id']
71 pull_request_id = result['result']['pull_request_id']
72 pull_request = PullRequestModel().get(pull_request_id)
72 pull_request = PullRequestModel().get(pull_request_id)
73 assert pull_request.title == data['title']
73 assert pull_request.title == data['title']
74 assert pull_request.description == data['description']
74 assert pull_request.description == data['description']
75 assert pull_request.source_ref == data['source_ref']
75 assert pull_request.source_ref == data['source_ref']
76 assert pull_request.target_ref == data['target_ref']
76 assert pull_request.target_ref == data['target_ref']
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 len(pull_request.reviewers) == 1
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):
84 data = self._prepare_data(backend)
84 data = self._prepare_data(backend)
85 data.pop('description')
85 data.pop('description')
86 id_, params = build_data(
86 id_, params = build_data(
87 self.apikey_regular, 'create_pull_request', **data)
87 self.apikey_regular, 'create_pull_request', **data)
88 response = api_call(self.app, params)
88 response = api_call(self.app, params)
89 expected_message = "Created new pull request `{title}`".format(
89 expected_message = "Created new pull request `{title}`".format(
90 title=data['title'])
90 title=data['title'])
91 result = response.json
91 result = response.json
92 assert result['error'] == None
92 assert result['error'] is None
93 assert result['result']['msg'] == expected_message
93 assert result['result']['msg'] == expected_message
94 pull_request_id = result['result']['pull_request_id']
94 pull_request_id = result['result']['pull_request_id']
95 pull_request = PullRequestModel().get(pull_request_id)
95 pull_request = PullRequestModel().get(pull_request_id)
96 assert pull_request.description == ''
96 assert pull_request.description == ''
97
97
98 @pytest.mark.backends("git", "hg")
98 @pytest.mark.backends("git", "hg")
99 def test_create_with_empty_title(self, backend):
99 def test_create_with_empty_title(self, backend):
100 data = self._prepare_data(backend)
100 data = self._prepare_data(backend)
101 data.pop('title')
101 data.pop('title')
102 id_, params = build_data(
102 id_, params = build_data(
103 self.apikey_regular, 'create_pull_request', **data)
103 self.apikey_regular, 'create_pull_request', **data)
104 response = api_call(self.app, params)
104 response = api_call(self.app, params)
105 result = response.json
105 result = response.json
106 pull_request_id = result['result']['pull_request_id']
106 pull_request_id = result['result']['pull_request_id']
107 pull_request = PullRequestModel().get(pull_request_id)
107 pull_request = PullRequestModel().get(pull_request_id)
108 data['ref'] = backend.default_branch_name
108 data['ref'] = backend.default_branch_name
109 title = '{source_repo}#{ref} to {target_repo}'.format(**data)
109 title = '{source_repo}#{ref} to {target_repo}'.format(**data)
110 assert pull_request.title == title
110 assert pull_request.title == title
111
111
112 @pytest.mark.backends("git", "hg")
112 @pytest.mark.backends("git", "hg")
113 def test_create_with_reviewers_specified_by_names(
113 def test_create_with_reviewers_specified_by_names(
114 self, backend, no_notifications):
114 self, backend, no_notifications):
115 data = self._prepare_data(backend)
115 data = self._prepare_data(backend)
116 reviewers = [
116 reviewers = [
117 {'username': TEST_USER_REGULAR_LOGIN,
117 {'username': TEST_USER_REGULAR_LOGIN,
118 'reasons': ['{} added manually'.format(TEST_USER_REGULAR_LOGIN)]},
118 'reasons': ['{} added manually'.format(TEST_USER_REGULAR_LOGIN)]},
119 {'username': TEST_USER_ADMIN_LOGIN,
119 {'username': TEST_USER_ADMIN_LOGIN,
120 'reasons': ['{} added manually'.format(TEST_USER_ADMIN_LOGIN)],
120 'reasons': ['{} added manually'.format(TEST_USER_ADMIN_LOGIN)],
121 'mandatory': True},
121 'mandatory': True},
122 ]
122 ]
123 data['reviewers'] = reviewers
123 data['reviewers'] = reviewers
124
124
125 id_, params = build_data(
125 id_, params = build_data(
126 self.apikey_regular, 'create_pull_request', **data)
126 self.apikey_regular, 'create_pull_request', **data)
127 response = api_call(self.app, params)
127 response = api_call(self.app, params)
128
128
129 expected_message = "Created new pull request `{title}`".format(
129 expected_message = "Created new pull request `{title}`".format(
130 title=data['title'])
130 title=data['title'])
131 result = response.json
131 result = response.json
132 assert result['error'] == None
132 assert result['error'] is None
133 assert result['result']['msg'] == expected_message
133 assert result['result']['msg'] == expected_message
134 pull_request_id = result['result']['pull_request_id']
134 pull_request_id = result['result']['pull_request_id']
135 pull_request = PullRequestModel().get(pull_request_id)
135 pull_request = PullRequestModel().get(pull_request_id)
136
136
137 actual_reviewers = []
137 actual_reviewers = []
138 for rev in pull_request.reviewers:
138 for rev in pull_request.reviewers:
139 entry = {
139 entry = {
140 'username': rev.user.username,
140 'username': rev.user.username,
141 'reasons': rev.reasons,
141 'reasons': rev.reasons,
142 }
142 }
143 if rev.mandatory:
143 if rev.mandatory:
144 entry['mandatory'] = rev.mandatory
144 entry['mandatory'] = rev.mandatory
145 actual_reviewers.append(entry)
145 actual_reviewers.append(entry)
146
146
147 # default reviewer will be added who is an owner of the repo
147 owner_username = pull_request.target_repo.user.username
148 reviewers.append(
148 for spec_reviewer in reviewers[::]:
149 {'username': pull_request.author.username,
149 # default reviewer will be added who is an owner of the repo
150 'reasons': [u'Default reviewer', u'Repository owner']},
150 # this get's overridden by a add owner to reviewers rule
151 )
151 if spec_reviewer['username'] == owner_username:
152 spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner']
153 # since owner is more important, we don't inherit mandatory flag
154 del spec_reviewer['mandatory']
155
152 assert sorted(actual_reviewers, key=lambda e: e['username']) \
156 assert sorted(actual_reviewers, key=lambda e: e['username']) \
153 == sorted(reviewers, key=lambda e: e['username'])
157 == sorted(reviewers, key=lambda e: e['username'])
154
158
155 @pytest.mark.backends("git", "hg")
159 @pytest.mark.backends("git", "hg")
156 def test_create_with_reviewers_specified_by_ids(
160 def test_create_with_reviewers_specified_by_ids(
157 self, backend, no_notifications):
161 self, backend, no_notifications):
158 data = self._prepare_data(backend)
162 data = self._prepare_data(backend)
159 reviewers = [
163 reviewers = [
160 {'username': UserModel().get_by_username(
164 {'username': UserModel().get_by_username(
161 TEST_USER_REGULAR_LOGIN).user_id,
165 TEST_USER_REGULAR_LOGIN).user_id,
162 'reasons': ['added manually']},
166 'reasons': ['added manually']},
163 {'username': UserModel().get_by_username(
167 {'username': UserModel().get_by_username(
164 TEST_USER_ADMIN_LOGIN).user_id,
168 TEST_USER_ADMIN_LOGIN).user_id,
165 'reasons': ['added manually']},
169 'reasons': ['added manually']},
166 ]
170 ]
167
171
168 data['reviewers'] = reviewers
172 data['reviewers'] = reviewers
169 id_, params = build_data(
173 id_, params = build_data(
170 self.apikey_regular, 'create_pull_request', **data)
174 self.apikey_regular, 'create_pull_request', **data)
171 response = api_call(self.app, params)
175 response = api_call(self.app, params)
172
176
173 expected_message = "Created new pull request `{title}`".format(
177 expected_message = "Created new pull request `{title}`".format(
174 title=data['title'])
178 title=data['title'])
175 result = response.json
179 result = response.json
176 assert result['error'] == None
180 assert result['error'] is None
177 assert result['result']['msg'] == expected_message
181 assert result['result']['msg'] == expected_message
178 pull_request_id = result['result']['pull_request_id']
182 pull_request_id = result['result']['pull_request_id']
179 pull_request = PullRequestModel().get(pull_request_id)
183 pull_request = PullRequestModel().get(pull_request_id)
180
184
181 actual_reviewers = []
185 actual_reviewers = []
182 for rev in pull_request.reviewers:
186 for rev in pull_request.reviewers:
183 entry = {
187 entry = {
184 'username': rev.user.user_id,
188 'username': rev.user.user_id,
185 'reasons': rev.reasons,
189 'reasons': rev.reasons,
186 }
190 }
187 if rev.mandatory:
191 if rev.mandatory:
188 entry['mandatory'] = rev.mandatory
192 entry['mandatory'] = rev.mandatory
189 actual_reviewers.append(entry)
193 actual_reviewers.append(entry)
190 # default reviewer will be added who is an owner of the repo
194
191 reviewers.append(
195 owner_user_id = pull_request.target_repo.user.user_id
192 {'username': pull_request.author.user_id,
196 for spec_reviewer in reviewers[::]:
193 'reasons': [u'Default reviewer', u'Repository owner']},
197 # default reviewer will be added who is an owner of the repo
194 )
198 # this get's overridden by a add owner to reviewers rule
199 if spec_reviewer['username'] == owner_user_id:
200 spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner']
201
195 assert sorted(actual_reviewers, key=lambda e: e['username']) \
202 assert sorted(actual_reviewers, key=lambda e: e['username']) \
196 == sorted(reviewers, key=lambda e: e['username'])
203 == sorted(reviewers, key=lambda e: e['username'])
197
204
198 @pytest.mark.backends("git", "hg")
205 @pytest.mark.backends("git", "hg")
199 def test_create_fails_when_the_reviewer_is_not_found(self, backend):
206 def test_create_fails_when_the_reviewer_is_not_found(self, backend):
200 data = self._prepare_data(backend)
207 data = self._prepare_data(backend)
201 data['reviewers'] = [{'username': 'somebody'}]
208 data['reviewers'] = [{'username': 'somebody'}]
202 id_, params = build_data(
209 id_, params = build_data(
203 self.apikey_regular, 'create_pull_request', **data)
210 self.apikey_regular, 'create_pull_request', **data)
204 response = api_call(self.app, params)
211 response = api_call(self.app, params)
205 expected_message = 'user `somebody` does not exist'
212 expected_message = 'user `somebody` does not exist'
206 assert_error(id_, expected_message, given=response.body)
213 assert_error(id_, expected_message, given=response.body)
207
214
208 @pytest.mark.backends("git", "hg")
215 @pytest.mark.backends("git", "hg")
209 def test_cannot_create_with_reviewers_in_wrong_format(self, backend):
216 def test_cannot_create_with_reviewers_in_wrong_format(self, backend):
210 data = self._prepare_data(backend)
217 data = self._prepare_data(backend)
211 reviewers = ','.join([TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_LOGIN])
218 reviewers = ','.join([TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_LOGIN])
212 data['reviewers'] = reviewers
219 data['reviewers'] = reviewers
213 id_, params = build_data(
220 id_, params = build_data(
214 self.apikey_regular, 'create_pull_request', **data)
221 self.apikey_regular, 'create_pull_request', **data)
215 response = api_call(self.app, params)
222 response = api_call(self.app, params)
216 expected_message = {u'': '"test_regular,test_admin" is not iterable'}
223 expected_message = {u'': '"test_regular,test_admin" is not iterable'}
217 assert_error(id_, expected_message, given=response.body)
224 assert_error(id_, expected_message, given=response.body)
218
225
219 @pytest.mark.backends("git", "hg")
226 @pytest.mark.backends("git", "hg")
220 def test_create_with_no_commit_hashes(self, backend):
227 def test_create_with_no_commit_hashes(self, backend):
221 data = self._prepare_data(backend)
228 data = self._prepare_data(backend)
222 expected_source_ref = data['source_ref']
229 expected_source_ref = data['source_ref']
223 expected_target_ref = data['target_ref']
230 expected_target_ref = data['target_ref']
224 data['source_ref'] = 'branch:{}'.format(backend.default_branch_name)
231 data['source_ref'] = 'branch:{}'.format(backend.default_branch_name)
225 data['target_ref'] = 'branch:{}'.format(backend.default_branch_name)
232 data['target_ref'] = 'branch:{}'.format(backend.default_branch_name)
226 id_, params = build_data(
233 id_, params = build_data(
227 self.apikey_regular, 'create_pull_request', **data)
234 self.apikey_regular, 'create_pull_request', **data)
228 response = api_call(self.app, params)
235 response = api_call(self.app, params)
229 expected_message = "Created new pull request `{title}`".format(
236 expected_message = "Created new pull request `{title}`".format(
230 title=data['title'])
237 title=data['title'])
231 result = response.json
238 result = response.json
232 assert result['result']['msg'] == expected_message
239 assert result['result']['msg'] == expected_message
233 pull_request_id = result['result']['pull_request_id']
240 pull_request_id = result['result']['pull_request_id']
234 pull_request = PullRequestModel().get(pull_request_id)
241 pull_request = PullRequestModel().get(pull_request_id)
235 assert pull_request.source_ref == expected_source_ref
242 assert pull_request.source_ref == expected_source_ref
236 assert pull_request.target_ref == expected_target_ref
243 assert pull_request.target_ref == expected_target_ref
237
244
238 @pytest.mark.backends("git", "hg")
245 @pytest.mark.backends("git", "hg")
239 @pytest.mark.parametrize("data_key", ["source_repo", "target_repo"])
246 @pytest.mark.parametrize("data_key", ["source_repo", "target_repo"])
240 def test_create_fails_with_wrong_repo(self, backend, data_key):
247 def test_create_fails_with_wrong_repo(self, backend, data_key):
241 repo_name = 'fake-repo'
248 repo_name = 'fake-repo'
242 data = self._prepare_data(backend)
249 data = self._prepare_data(backend)
243 data[data_key] = repo_name
250 data[data_key] = repo_name
244 id_, params = build_data(
251 id_, params = build_data(
245 self.apikey_regular, 'create_pull_request', **data)
252 self.apikey_regular, 'create_pull_request', **data)
246 response = api_call(self.app, params)
253 response = api_call(self.app, params)
247 expected_message = 'repository `{}` does not exist'.format(repo_name)
254 expected_message = 'repository `{}` does not exist'.format(repo_name)
248 assert_error(id_, expected_message, given=response.body)
255 assert_error(id_, expected_message, given=response.body)
249
256
250 @pytest.mark.backends("git", "hg")
257 @pytest.mark.backends("git", "hg")
251 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
258 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
252 def test_create_fails_with_non_existing_branch(self, backend, data_key):
259 def test_create_fails_with_non_existing_branch(self, backend, data_key):
253 branch_name = 'test-branch'
260 branch_name = 'test-branch'
254 data = self._prepare_data(backend)
261 data = self._prepare_data(backend)
255 data[data_key] = "branch:{}".format(branch_name)
262 data[data_key] = "branch:{}".format(branch_name)
256 id_, params = build_data(
263 id_, params = build_data(
257 self.apikey_regular, 'create_pull_request', **data)
264 self.apikey_regular, 'create_pull_request', **data)
258 response = api_call(self.app, params)
265 response = api_call(self.app, params)
259 expected_message = 'The specified value:{type}:`{name}` ' \
266 expected_message = 'The specified value:{type}:`{name}` ' \
260 'does not exist, or is not allowed.'.format(type='branch',
267 'does not exist, or is not allowed.'.format(type='branch',
261 name=branch_name)
268 name=branch_name)
262 assert_error(id_, expected_message, given=response.body)
269 assert_error(id_, expected_message, given=response.body)
263
270
264 @pytest.mark.backends("git", "hg")
271 @pytest.mark.backends("git", "hg")
265 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
272 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
266 def test_create_fails_with_ref_in_a_wrong_format(self, backend, data_key):
273 def test_create_fails_with_ref_in_a_wrong_format(self, backend, data_key):
267 data = self._prepare_data(backend)
274 data = self._prepare_data(backend)
268 ref = 'stange-ref'
275 ref = 'stange-ref'
269 data[data_key] = ref
276 data[data_key] = ref
270 id_, params = build_data(
277 id_, params = build_data(
271 self.apikey_regular, 'create_pull_request', **data)
278 self.apikey_regular, 'create_pull_request', **data)
272 response = api_call(self.app, params)
279 response = api_call(self.app, params)
273 expected_message = (
280 expected_message = (
274 'Ref `{ref}` given in a wrong format. Please check the API'
281 'Ref `{ref}` given in a wrong format. Please check the API'
275 ' documentation for more details'.format(ref=ref))
282 ' documentation for more details'.format(ref=ref))
276 assert_error(id_, expected_message, given=response.body)
283 assert_error(id_, expected_message, given=response.body)
277
284
278 @pytest.mark.backends("git", "hg")
285 @pytest.mark.backends("git", "hg")
279 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
286 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
280 def test_create_fails_with_non_existing_ref(self, backend, data_key):
287 def test_create_fails_with_non_existing_ref(self, backend, data_key):
281 commit_id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10'
288 commit_id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10'
282 ref = self._get_full_ref(backend, commit_id)
289 ref = self._get_full_ref(backend, commit_id)
283 data = self._prepare_data(backend)
290 data = self._prepare_data(backend)
284 data[data_key] = ref
291 data[data_key] = ref
285 id_, params = build_data(
292 id_, params = build_data(
286 self.apikey_regular, 'create_pull_request', **data)
293 self.apikey_regular, 'create_pull_request', **data)
287 response = api_call(self.app, params)
294 response = api_call(self.app, params)
288 expected_message = 'Ref `{}` does not exist'.format(ref)
295 expected_message = 'Ref `{}` does not exist'.format(ref)
289 assert_error(id_, expected_message, given=response.body)
296 assert_error(id_, expected_message, given=response.body)
290
297
291 @pytest.mark.backends("git", "hg")
298 @pytest.mark.backends("git", "hg")
292 def test_create_fails_when_no_revisions(self, backend):
299 def test_create_fails_when_no_revisions(self, backend):
293 data = self._prepare_data(backend, source_head='initial')
300 data = self._prepare_data(backend, source_head='initial')
294 id_, params = build_data(
301 id_, params = build_data(
295 self.apikey_regular, 'create_pull_request', **data)
302 self.apikey_regular, 'create_pull_request', **data)
296 response = api_call(self.app, params)
303 response = api_call(self.app, params)
297 expected_message = 'no commits found'
304 expected_message = 'no commits found'
298 assert_error(id_, expected_message, given=response.body)
305 assert_error(id_, expected_message, given=response.body)
299
306
300 @pytest.mark.backends("git", "hg")
307 @pytest.mark.backends("git", "hg")
301 def test_create_fails_when_no_permissions(self, backend):
308 def test_create_fails_when_no_permissions(self, backend):
302 data = self._prepare_data(backend)
309 data = self._prepare_data(backend)
303 RepoModel().revoke_user_permission(
310 RepoModel().revoke_user_permission(
304 self.source.repo_name, self.test_user)
311 self.source.repo_name, self.test_user)
305 RepoModel().revoke_user_permission(
312 RepoModel().revoke_user_permission(
306 self.source.repo_name, User.DEFAULT_USER)
313 self.source.repo_name, User.DEFAULT_USER)
307
314
308 id_, params = build_data(
315 id_, params = build_data(
309 self.apikey_regular, 'create_pull_request', **data)
316 self.apikey_regular, 'create_pull_request', **data)
310 response = api_call(self.app, params)
317 response = api_call(self.app, params)
311 expected_message = 'repository `{}` does not exist'.format(
318 expected_message = 'repository `{}` does not exist'.format(
312 self.source.repo_name)
319 self.source.repo_name)
313 assert_error(id_, expected_message, given=response.body)
320 assert_error(id_, expected_message, given=response.body)
314
321
315 def _prepare_data(
322 def _prepare_data(
316 self, backend, source_head='change', target_head='initial'):
323 self, backend, source_head='change', target_head='initial'):
317 commits = [
324 commits = [
318 {'message': 'initial'},
325 {'message': 'initial'},
319 {'message': 'change'},
326 {'message': 'change'},
320 {'message': 'new-feature', 'parents': ['initial']},
327 {'message': 'new-feature', 'parents': ['initial']},
321 ]
328 ]
322 self.commit_ids = backend.create_master_repo(commits)
329 self.commit_ids = backend.create_master_repo(commits)
323 self.source = backend.create_repo(heads=[source_head])
330 self.source = backend.create_repo(heads=[source_head])
324 self.target = backend.create_repo(heads=[target_head])
331 self.target = backend.create_repo(heads=[target_head])
325
332
326 data = {
333 data = {
327 'source_repo': self.source.repo_name,
334 'source_repo': self.source.repo_name,
328 'target_repo': self.target.repo_name,
335 'target_repo': self.target.repo_name,
329 'source_ref': self._get_full_ref(
336 'source_ref': self._get_full_ref(
330 backend, self.commit_ids[source_head]),
337 backend, self.commit_ids[source_head]),
331 'target_ref': self._get_full_ref(
338 'target_ref': self._get_full_ref(
332 backend, self.commit_ids[target_head]),
339 backend, self.commit_ids[target_head]),
333 'title': 'Test PR 1',
340 'title': 'Test PR 1',
334 'description': 'Test'
341 'description': 'Test'
335 }
342 }
336 RepoModel().grant_user_permission(
343 RepoModel().grant_user_permission(
337 self.source.repo_name, self.TEST_USER_LOGIN, 'repository.read')
344 self.source.repo_name, self.TEST_USER_LOGIN, 'repository.read')
338 return data
345 return data
339
346
340 def _get_full_ref(self, backend, commit_id):
347 def _get_full_ref(self, backend, commit_id):
341 return 'branch:{branch}:{commit_id}'.format(
348 return 'branch:{branch}:{commit_id}'.format(
342 branch=backend.default_branch_name, commit_id=commit_id)
349 branch=backend.default_branch_name, commit_id=commit_id)
@@ -1,79 +1,79 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 from rhodecode.lib import helpers as h
21 from rhodecode.lib import helpers as h
22 from rhodecode.lib.utils2 import safe_int
22 from rhodecode.lib.utils2 import safe_int
23
23
24
24
25 def reviewer_as_json(user, reasons=None, mandatory=False, rules=None, user_group=None):
25 def reviewer_as_json(user, reasons=None, mandatory=False, rules=None, user_group=None):
26 """
26 """
27 Returns json struct of a reviewer for frontend
27 Returns json struct of a reviewer for frontend
28
28
29 :param user: the reviewer
29 :param user: the reviewer
30 :param reasons: list of strings of why they are reviewers
30 :param reasons: list of strings of why they are reviewers
31 :param mandatory: bool, to set user as mandatory
31 :param mandatory: bool, to set user as mandatory
32 """
32 """
33
33
34 return {
34 return {
35 'user_id': user.user_id,
35 'user_id': user.user_id,
36 'reasons': reasons or [],
36 'reasons': reasons or [],
37 'rules': rules or [],
37 'rules': rules or [],
38 'mandatory': mandatory,
38 'mandatory': mandatory,
39 'user_group': user_group,
39 'user_group': user_group,
40 'username': user.username,
40 'username': user.username,
41 'first_name': user.first_name,
41 'first_name': user.first_name,
42 'last_name': user.last_name,
42 'last_name': user.last_name,
43 'user_link': h.link_to_user(user),
43 'user_link': h.link_to_user(user),
44 'gravatar_link': h.gravatar_url(user.email, 14),
44 'gravatar_link': h.gravatar_url(user.email, 14),
45 }
45 }
46
46
47
47
48 def get_default_reviewers_data(
48 def get_default_reviewers_data(
49 current_user, source_repo, source_commit, target_repo, target_commit):
49 current_user, source_repo, source_commit, target_repo, target_commit):
50
50
51 """ Return json for default reviewers of a repository """
51 """ Return json for default reviewers of a repository """
52
52
53 reasons = ['Default reviewer', 'Repository owner']
53 reasons = ['Default reviewer', 'Repository owner']
54 default = reviewer_as_json(
54 json_reviewers = [reviewer_as_json(
55 user=current_user, reasons=reasons, mandatory=False)
55 user=target_repo.user, reasons=reasons, mandatory=False, rules=None)]
56
56
57 return {
57 return {
58 'api_ver': 'v1', # define version for later possible schema upgrade
58 'api_ver': 'v1', # define version for later possible schema upgrade
59 'reviewers': [default],
59 'reviewers': json_reviewers,
60 'rules': {},
60 'rules': {},
61 'rules_data': {},
61 'rules_data': {},
62 }
62 }
63
63
64
64
65 def validate_default_reviewers(review_members, reviewer_rules):
65 def validate_default_reviewers(review_members, reviewer_rules):
66 """
66 """
67 Function to validate submitted reviewers against the saved rules
67 Function to validate submitted reviewers against the saved rules
68
68
69 """
69 """
70 reviewers = []
70 reviewers = []
71 reviewer_by_id = {}
71 reviewer_by_id = {}
72 for r in review_members:
72 for r in review_members:
73 reviewer_user_id = safe_int(r['user_id'])
73 reviewer_user_id = safe_int(r['user_id'])
74 entry = (reviewer_user_id, r['reasons'], r['mandatory'], r['rules'])
74 entry = (reviewer_user_id, r['reasons'], r['mandatory'], r['rules'])
75
75
76 reviewer_by_id[reviewer_user_id] = entry
76 reviewer_by_id[reviewer_user_id] = entry
77 reviewers.append(entry)
77 reviewers.append(entry)
78
78
79 return reviewers
79 return reviewers
General Comments 0
You need to be logged in to leave comments. Login now