##// END OF EJS Templates
pull-request-api: updated logic of closing a PR via API call....
marcink -
r1792:a62f3dac default
parent child Browse files
Show More
@@ -43,6 +43,7 b' class TestClosePullRequest(object):'
43 43 response = api_call(self.app, params)
44 44 expected = {
45 45 'pull_request_id': pull_request_id,
46 'close_status': 'Rejected',
46 47 'closed': True,
47 48 }
48 49 assert_ok(id_, expected, response.body)
@@ -21,6 +21,7 b''
21 21
22 22 import logging
23 23
24 from rhodecode import events
24 25 from rhodecode.api import jsonrpc_method, JSONRPCError, JSONRPCValidationError
25 26 from rhodecode.api.utils import (
26 27 has_superadmin_permission, Optional, OAttr, get_repo_or_error,
@@ -35,8 +36,8 b' from rhodecode.model.db import Session, '
35 36 from rhodecode.model.pull_request import PullRequestModel, MergeCheck
36 37 from rhodecode.model.settings import SettingsModel
37 38 from rhodecode.model.validation_schema import Invalid
38 from rhodecode.model.validation_schema.schemas.reviewer_schema import \
39 ReviewerListSchema
39 from rhodecode.model.validation_schema.schemas.reviewer_schema import(
40 ReviewerListSchema)
40 41
41 42 log = logging.getLogger(__name__)
42 43
@@ -227,7 +228,8 b' def get_pull_requests(request, apiuser, '
227 228
228 229
229 230 @jsonrpc_method()
230 def merge_pull_request(request, apiuser, repoid, pullrequestid,
231 def merge_pull_request(
232 request, apiuser, repoid, pullrequestid,
231 233 userid=Optional(OAttr('apiuser'))):
232 234 """
233 235 Merge the pull request specified by `pullrequestid` into its target
@@ -308,63 +310,6 b' def merge_pull_request(request, apiuser,'
308 310
309 311
310 312 @jsonrpc_method()
311 def close_pull_request(request, apiuser, repoid, pullrequestid,
312 userid=Optional(OAttr('apiuser'))):
313 """
314 Close the pull request specified by `pullrequestid`.
315
316 :param apiuser: This is filled automatically from the |authtoken|.
317 :type apiuser: AuthUser
318 :param repoid: Repository name or repository ID to which the pull
319 request belongs.
320 :type repoid: str or int
321 :param pullrequestid: ID of the pull request to be closed.
322 :type pullrequestid: int
323 :param userid: Close the pull request as this user.
324 :type userid: Optional(str or int)
325
326 Example output:
327
328 .. code-block:: bash
329
330 "id": <id_given_in_input>,
331 "result": {
332 "pull_request_id": "<int>",
333 "closed": "<bool>"
334 },
335 "error": null
336
337 """
338 repo = get_repo_or_error(repoid)
339 if not isinstance(userid, Optional):
340 if (has_superadmin_permission(apiuser) or
341 HasRepoPermissionAnyApi('repository.admin')(
342 user=apiuser, repo_name=repo.repo_name)):
343 apiuser = get_user_or_error(userid)
344 else:
345 raise JSONRPCError('userid is not the same as your user')
346
347 pull_request = get_pull_request_or_error(pullrequestid)
348 if not PullRequestModel().check_user_update(
349 pull_request, apiuser, api=True):
350 raise JSONRPCError(
351 'pull request `%s` close failed, no permission to close.' % (
352 pullrequestid,))
353 if pull_request.is_closed():
354 raise JSONRPCError(
355 'pull request `%s` is already closed' % (pullrequestid,))
356
357 PullRequestModel().close_pull_request(
358 pull_request.pull_request_id, apiuser)
359 Session().commit()
360 data = {
361 'pull_request_id': pull_request.pull_request_id,
362 'closed': True,
363 }
364 return data
365
366
367 @jsonrpc_method()
368 313 def comment_pull_request(
369 314 request, apiuser, repoid, pullrequestid, message=Optional(None),
370 315 commit_id=Optional(None), status=Optional(None),
@@ -610,7 +555,7 b' def create_pull_request('
610 555 def update_pull_request(
611 556 request, apiuser, repoid, pullrequestid, title=Optional(''),
612 557 description=Optional(''), reviewers=Optional(None),
613 update_commits=Optional(None), close_pull_request=Optional(None)):
558 update_commits=Optional(None)):
614 559 """
615 560 Updates a pull request.
616 561
@@ -632,8 +577,6 b' def update_pull_request('
632 577
633 578 :param update_commits: Trigger update of commits for this pull request
634 579 :type: update_commits: Optional(bool)
635 :param close_pull_request: Close this pull request with rejected state
636 :type: close_pull_request: Optional(bool)
637 580
638 581 Example output:
639 582
@@ -675,7 +618,6 b' def update_pull_request('
675 618 'pull request `%s` update failed, pull request is closed' % (
676 619 pullrequestid,))
677 620
678
679 621 reviewer_objects = Optional.extract(reviewers) or []
680 622 if reviewer_objects:
681 623 schema = ReviewerListSchema()
@@ -718,11 +660,6 b' def update_pull_request('
718 660 [get_user_or_error(n).username for n in removed_reviewers])
719 661 Session().commit()
720 662
721 if str2bool(Optional.extract(close_pull_request)):
722 PullRequestModel().close_pull_request_with_comment(
723 pull_request, apiuser, repo)
724 Session().commit()
725
726 663 data = {
727 664 'msg': 'Updated pull request `{}`'.format(
728 665 pull_request.pull_request_id),
@@ -732,3 +669,80 b' def update_pull_request('
732 669 }
733 670
734 671 return data
672
673
674 @jsonrpc_method()
675 def close_pull_request(
676 request, apiuser, repoid, pullrequestid,
677 userid=Optional(OAttr('apiuser')), message=Optional('')):
678 """
679 Close the pull request specified by `pullrequestid`.
680
681 :param apiuser: This is filled automatically from the |authtoken|.
682 :type apiuser: AuthUser
683 :param repoid: Repository name or repository ID to which the pull
684 request belongs.
685 :type repoid: str or int
686 :param pullrequestid: ID of the pull request to be closed.
687 :type pullrequestid: int
688 :param userid: Close the pull request as this user.
689 :type userid: Optional(str or int)
690 :param message: Optional message to close the Pull Request with. If not
691 specified it will be generated automatically.
692 :type message: Optional(str)
693
694 Example output:
695
696 .. code-block:: bash
697
698 "id": <id_given_in_input>,
699 "result": {
700 "pull_request_id": "<int>",
701 "close_status": "<str:status_lbl>,
702 "closed": "<bool>"
703 },
704 "error": null
705
706 """
707 _ = request.translate
708
709 repo = get_repo_or_error(repoid)
710 if not isinstance(userid, Optional):
711 if (has_superadmin_permission(apiuser) or
712 HasRepoPermissionAnyApi('repository.admin')(
713 user=apiuser, repo_name=repo.repo_name)):
714 apiuser = get_user_or_error(userid)
715 else:
716 raise JSONRPCError('userid is not the same as your user')
717
718 pull_request = get_pull_request_or_error(pullrequestid)
719
720 if pull_request.is_closed():
721 raise JSONRPCError(
722 'pull request `%s` is already closed' % (pullrequestid,))
723
724 # only owner or admin or person with write permissions
725 allowed_to_close = PullRequestModel().check_user_update(
726 pull_request, apiuser, api=True)
727
728 if not allowed_to_close:
729 raise JSONRPCError(
730 'pull request `%s` close failed, no permission to close.' % (
731 pullrequestid,))
732
733 # message we're using to close the PR, else it's automatically generated
734 message = Optional.extract(message)
735
736 # finally close the PR, with proper message comment
737 comment, status = PullRequestModel().close_pull_request_with_comment(
738 pull_request, apiuser, repo, message=message)
739 status_lbl = ChangesetStatus.get_status_lbl(status)
740
741 Session().commit()
742
743 data = {
744 'pull_request_id': pull_request.pull_request_id,
745 'close_status': status_lbl,
746 'closed': True,
747 }
748 return data
@@ -368,7 +368,6 b' class ChangesetController(BaseRepoContro'
368 368 comment_type=comment_type,
369 369 resolves_comment_id=resolves_comment_id
370 370 )
371 c.inline_comment = True if comment.line_no else False
372 371
373 372 # get status if set !
374 373 if status:
@@ -306,8 +306,6 b' class PullrequestsController(BaseRepoCon'
306 306 pull_request.reviewer_data)
307 307 elif str2bool(request.POST.get('update_commits', 'false')):
308 308 self._update_commits(pull_request)
309 elif str2bool(request.POST.get('close_pull_request', 'false')):
310 self._reject_close(pull_request)
311 309 elif str2bool(request.POST.get('edit_pull_request', 'false')):
312 310 self._edit_pull_request(pull_request)
313 311 else:
@@ -462,14 +460,6 b' class PullrequestsController(BaseRepoCon'
462 460 h.flash(_('Pull request reviewers updated.'), category='success')
463 461 Session().commit()
464 462
465 def _reject_close(self, pull_request):
466 if pull_request.is_closed():
467 raise HTTPForbidden()
468
469 PullRequestModel().close_pull_request_with_comment(
470 pull_request, c.rhodecode_user, c.rhodecode_db_repo)
471 Session().commit()
472
473 463 @LoginRequired()
474 464 @NotAnonymous()
475 465 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
@@ -888,6 +878,7 b' class PullrequestsController(BaseRepoCon'
888 878 pull_request_id = safe_int(pull_request_id)
889 879 pull_request = PullRequest.get_or_404(pull_request_id)
890 880 if pull_request.is_closed():
881 log.debug('comment: forbidden because pull request is closed')
891 882 raise HTTPForbidden()
892 883
893 884 status = request.POST.get('changeset_status', None)
@@ -896,19 +887,29 b' class PullrequestsController(BaseRepoCon'
896 887 resolves_comment_id = request.POST.get('resolves_comment_id', None)
897 888 close_pull_request = request.POST.get('close_pull_request')
898 889
899 close_pr = False
890 # the logic here should work like following, if we submit close
891 # pr comment, use `close_pull_request_with_comment` function
892 # else handle regular comment logic
893 user = c.rhodecode_user
894 repo = c.rhodecode_db_repo
895
896 if close_pull_request:
900 897 # only owner or admin or person with write permissions
901 898 allowed_to_close = PullRequestModel().check_user_update(
902 899 pull_request, c.rhodecode_user)
900 if not allowed_to_close:
901 log.debug('comment: forbidden because not allowed to close '
902 'pull request %s', pull_request_id)
903 raise HTTPForbidden()
904 comment, status = PullRequestModel().close_pull_request_with_comment(
905 pull_request, user, repo, message=text)
906 Session().flush()
907 events.trigger(
908 events.PullRequestCommentEvent(pull_request, comment))
903 909
904 if close_pull_request and allowed_to_close:
905 close_pr = True
906 pull_request_review_status = pull_request.calculated_review_status()
907 if pull_request_review_status == ChangesetStatus.STATUS_APPROVED:
908 # approved only if we have voting consent
909 status = ChangesetStatus.STATUS_APPROVED
910 910 else:
911 status = ChangesetStatus.STATUS_REJECTED
911 # regular comment case, could be inline, or one with status.
912 # for that one we check also permissions
912 913
913 914 allowed_to_change_status = PullRequestModel().check_user_change_status(
914 915 pull_request, c.rhodecode_user)
@@ -917,10 +918,9 b' class PullrequestsController(BaseRepoCon'
917 918 message = (_('Status change %(transition_icon)s %(status)s')
918 919 % {'transition_icon': '>',
919 920 'status': ChangesetStatus.get_status_lbl(status)})
920 if close_pr:
921 message = _('Closing with') + ' ' + message
922 921 text = text or message
923 comm = CommentsModel().create(
922
923 comment = CommentsModel().create(
924 924 text=text,
925 925 repo=c.rhodecode_db_repo.repo_id,
926 926 user=c.rhodecode_user.user_id,
@@ -931,25 +931,28 b' class PullrequestsController(BaseRepoCon'
931 931 if status and allowed_to_change_status else None),
932 932 status_change_type=(status
933 933 if status and allowed_to_change_status else None),
934 closing_pr=close_pr,
935 934 comment_type=comment_type,
936 935 resolves_comment_id=resolves_comment_id
937 936 )
938 937
939 938 if allowed_to_change_status:
939 # calculate old status before we change it
940 940 old_calculated_status = pull_request.calculated_review_status()
941
941 942 # get status if set !
942 943 if status:
943 944 ChangesetStatusModel().set_status(
944 945 c.rhodecode_db_repo.repo_id,
945 946 status,
946 947 c.rhodecode_user.user_id,
947 comm,
948 comment,
948 949 pull_request=pull_request_id
949 950 )
950 951
951 952 Session().flush()
952 events.trigger(events.PullRequestCommentEvent(pull_request, comm))
953 events.trigger(
954 events.PullRequestCommentEvent(pull_request, comment))
955
953 956 # we now calculate the status of pull request, and based on that
954 957 # calculation we set the commits status
955 958 calculated_status = pull_request.calculated_review_status()
@@ -957,23 +960,6 b' class PullrequestsController(BaseRepoCon'
957 960 PullRequestModel()._trigger_pull_request_hook(
958 961 pull_request, c.rhodecode_user, 'review_status_change')
959 962
960 calculated_status_lbl = ChangesetStatus.get_status_lbl(
961 calculated_status)
962
963 if close_pr:
964 status_completed = (
965 calculated_status in [ChangesetStatus.STATUS_APPROVED,
966 ChangesetStatus.STATUS_REJECTED])
967 if close_pull_request or status_completed:
968 PullRequestModel().close_pull_request(
969 pull_request_id, c.rhodecode_user)
970 else:
971 h.flash(_('Closing pull request on other statuses than '
972 'rejected or approved is forbidden. '
973 'Calculated status from all reviewers '
974 'is currently: %s') % calculated_status_lbl,
975 category='warning')
976
977 963 Session().commit()
978 964
979 965 if not request.is_xhr:
@@ -983,12 +969,11 b' class PullrequestsController(BaseRepoCon'
983 969 data = {
984 970 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
985 971 }
986 if comm:
987 c.co = comm
988 c.inline_comment = True if comm.line_no else False
989 data.update(comm.get_dict())
990 data.update({'rendered_text':
991 render('changeset/changeset_comment_block.mako')})
972 if comment:
973 c.co = comment
974 rendered_comment = render('changeset/changeset_comment_block.mako')
975 data.update(comment.get_dict())
976 data.update({'rendered_text': rendered_comment})
992 977
993 978 return data
994 979
@@ -3107,6 +3107,10 b' class ChangesetComment(Base, BaseModel):'
3107 3107 def is_todo(self):
3108 3108 return self.comment_type == self.COMMENT_TYPE_TODO
3109 3109
3110 @property
3111 def is_inline(self):
3112 return self.line_no and self.f_path
3113
3110 3114 def get_index_version(self, versions):
3111 3115 return self.get_index_from_version(
3112 3116 self.pull_request_version_id, versions)
@@ -34,6 +34,7 b' from pylons.i18n.translation import lazy'
34 34 from pyramid.threadlocal import get_current_request
35 35 from sqlalchemy import or_
36 36
37 from rhodecode import events
37 38 from rhodecode.lib import helpers as h, hooks_utils, diffs
38 39 from rhodecode.lib.compat import OrderedDict
39 40 from rhodecode.lib.hooks_daemon import prepare_callback_daemon
@@ -1064,42 +1065,61 b' class PullRequestModel(BaseModel):'
1064 1065 pull_request, pull_request.author, 'close')
1065 1066 self._log_action('user_closed_pull_request', user, pull_request)
1066 1067
1067 def close_pull_request_with_comment(self, pull_request, user, repo,
1068 message=None):
1069 status = ChangesetStatus.STATUS_REJECTED
1068 def close_pull_request_with_comment(
1069 self, pull_request, user, repo, message=None):
1070
1071 pull_request_review_status = pull_request.calculated_review_status()
1070 1072
1071 if not message:
1072 message = (
1073 _('Status change %(transition_icon)s %(status)s') % {
1074 'transition_icon': '>',
1075 'status': ChangesetStatus.get_status_lbl(status)})
1073 if pull_request_review_status == ChangesetStatus.STATUS_APPROVED:
1074 # approved only if we have voting consent
1075 status = ChangesetStatus.STATUS_APPROVED
1076 else:
1077 status = ChangesetStatus.STATUS_REJECTED
1078 status_lbl = ChangesetStatus.get_status_lbl(status)
1076 1079
1077 internal_message = _('Closing with') + ' ' + message
1080 default_message = (
1081 _('Closing with status change {transition_icon} {status}.')
1082 ).format(transition_icon='>', status=status_lbl)
1083 text = message or default_message
1078 1084
1079 comm = CommentsModel().create(
1080 text=internal_message,
1085 # create a comment, and link it to new status
1086 comment = CommentsModel().create(
1087 text=text,
1081 1088 repo=repo.repo_id,
1082 1089 user=user.user_id,
1083 1090 pull_request=pull_request.pull_request_id,
1084 f_path=None,
1085 line_no=None,
1086 status_change=ChangesetStatus.get_status_lbl(status),
1091 status_change=status_lbl,
1087 1092 status_change_type=status,
1088 1093 closing_pr=True
1089 1094 )
1090 1095
1096 # calculate old status before we change it
1097 old_calculated_status = pull_request.calculated_review_status()
1091 1098 ChangesetStatusModel().set_status(
1092 1099 repo.repo_id,
1093 1100 status,
1094 1101 user.user_id,
1095 comm,
1102 comment=comment,
1096 1103 pull_request=pull_request.pull_request_id
1097 1104 )
1105
1098 1106 Session().flush()
1107 events.trigger(events.PullRequestCommentEvent(pull_request, comment))
1108 # we now calculate the status of pull request again, and based on that
1109 # calculation trigger status change. This might happen in cases
1110 # that non-reviewer admin closes a pr, which means his vote doesn't
1111 # change the status, while if he's a reviewer this might change it.
1112 calculated_status = pull_request.calculated_review_status()
1113 if old_calculated_status != calculated_status:
1114 self._trigger_pull_request_hook(
1115 pull_request, user, 'review_status_change')
1099 1116
1117 # finally close the PR
1100 1118 PullRequestModel().close_pull_request(
1101 1119 pull_request.pull_request_id, user)
1102 1120
1121 return comment, status
1122
1103 1123 def merge_status(self, pull_request):
1104 1124 if not self._is_merge_enabled(pull_request):
1105 1125 return False, _('Server-side pull request merging is disabled.')
@@ -96,6 +96,7 b' function registerRCRoutes() {'
96 96 pyroutes.register('goto_switcher_data', '/_goto_data', []);
97 97 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
98 98 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
99 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
99 100 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
100 101 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
101 102 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
@@ -368,16 +368,6 b' var _updatePullRequest = function(repo_n'
368 368 };
369 369
370 370 /**
371 * PULL REQUEST reject & close
372 */
373 var closePullRequest = function(repo_name, pull_request_id) {
374 var postData = {
375 '_method': 'put',
376 'close_pull_request': true};
377 _updatePullRequest(repo_name, pull_request_id, postData);
378 };
379
380 /**
381 371 * PULL REQUEST update commits
382 372 */
383 373 var updateCommits = function(repo_name, pull_request_id) {
@@ -1,4 +1,4 b''
1 1 ## this is a dummy html file for partial rendering on server and sending
2 2 ## generated output via ajax after comment submit
3 3 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
4 ${comment.comment_block(c.co, inline=c.inline_comment)}
4 ${comment.comment_block(c.co, inline=c.co.is_inline)}
@@ -949,9 +949,6 b''
949 949 updateCommits("rhodecode-momentum", "720");
950 950 });
951 951
952 $('#close_pull_request').on('click', function(e){
953 closePullRequest("rhodecode-momentum", "720");
954 });
955 952 })
956 953 </script>
957 954
@@ -825,11 +825,6 b''
825 825 // fixing issue with caches on firefox
826 826 $('#update_commits').removeAttr("disabled");
827 827
828 $('#close_pull_request').on('click', function(e){
829 closePullRequest(
830 "${c.repo_name}", "${c.pull_request.pull_request_id}");
831 });
832
833 828 $('.show-inline-comments').on('click', function(e){
834 829 var boxid = $(this).attr('data-comment-id');
835 830 var button = $(this);
@@ -237,7 +237,9 b' class TestPullrequestsController(object)'
237 237 assertr.element_contains(
238 238 'span[data-role="merge-message"]', str(expected_msg))
239 239
240 def test_comment_and_close_pull_request(self, pr_util, csrf_token):
240 def test_comment_and_close_pull_request_custom_message_approved(
241 self, pr_util, csrf_token, xhr_header):
242
241 243 pull_request = pr_util.create_pull_request(approved=True)
242 244 pull_request_id = pull_request.pull_request_id
243 245 author = pull_request.user_id
@@ -249,11 +251,10 b' class TestPullrequestsController(object)'
249 251 repo_name=pull_request.target_repo.scm_instance().name,
250 252 pull_request_id=str(pull_request_id)),
251 253 params={
252 'changeset_status': ChangesetStatus.STATUS_APPROVED,
253 254 'close_pull_request': '1',
254 255 'text': 'Closing a PR',
255 256 'csrf_token': csrf_token},
256 status=302)
257 extra_environ=xhr_header,)
257 258
258 259 action = 'user_closed_pull_request:%d' % pull_request_id
259 260 journal = UserLog.query()\
@@ -270,45 +271,26 b' class TestPullrequestsController(object)'
270 271 status = ChangesetStatusModel().get_status(
271 272 pull_request.source_repo, pull_request=pull_request)
272 273 assert status == ChangesetStatus.STATUS_APPROVED
273
274 def test_reject_and_close_pull_request(self, pr_util, csrf_token):
275 pull_request = pr_util.create_pull_request()
276 pull_request_id = pull_request.pull_request_id
277 response = self.app.post(
278 url(controller='pullrequests',
279 action='update',
280 repo_name=pull_request.target_repo.scm_instance().name,
281 pull_request_id=str(pull_request.pull_request_id)),
282 params={'close_pull_request': 'true', '_method': 'put',
283 'csrf_token': csrf_token})
274 assert pull_request.comments[-1].text == 'Closing a PR'
284 275
285 pull_request = PullRequest.get(pull_request_id)
286
287 assert response.json is True
288 assert pull_request.is_closed()
289
290 # check only the latest status, not the review status
291 status = ChangesetStatusModel().get_status(
292 pull_request.source_repo, pull_request=pull_request)
293 assert status == ChangesetStatus.STATUS_REJECTED
294
295 def test_comment_force_close_pull_request(self, pr_util, csrf_token):
276 def test_comment_force_close_pull_request_rejected(
277 self, pr_util, csrf_token, xhr_header):
296 278 pull_request = pr_util.create_pull_request()
297 279 pull_request_id = pull_request.pull_request_id
298 280 PullRequestModel().update_reviewers(
299 281 pull_request_id, [(1, ['reason'], False), (2, ['reason2'], False)])
300 282 author = pull_request.user_id
301 283 repo = pull_request.target_repo.repo_id
284
302 285 self.app.post(
303 286 url(controller='pullrequests',
304 287 action='comment',
305 288 repo_name=pull_request.target_repo.scm_instance().name,
306 289 pull_request_id=str(pull_request_id)),
307 290 params={
308 'changeset_status': 'rejected',
309 291 'close_pull_request': '1',
310 292 'csrf_token': csrf_token},
311 status=302)
293 extra_environ=xhr_header)
312 294
313 295 pull_request = PullRequest.get(pull_request_id)
314 296
@@ -324,6 +306,31 b' class TestPullrequestsController(object)'
324 306 pull_request.source_repo, pull_request=pull_request)
325 307 assert status == ChangesetStatus.STATUS_REJECTED
326 308
309 def test_comment_and_close_pull_request(
310 self, pr_util, csrf_token, xhr_header):
311 pull_request = pr_util.create_pull_request()
312 pull_request_id = pull_request.pull_request_id
313
314 response = self.app.post(
315 url(controller='pullrequests',
316 action='comment',
317 repo_name=pull_request.target_repo.scm_instance().name,
318 pull_request_id=str(pull_request.pull_request_id)),
319 params={
320 'close_pull_request': 'true',
321 'csrf_token': csrf_token},
322 extra_environ=xhr_header)
323
324 assert response.json
325
326 pull_request = PullRequest.get(pull_request_id)
327 assert pull_request.is_closed()
328
329 # check only the latest status, not the review status
330 status = ChangesetStatusModel().get_status(
331 pull_request.source_repo, pull_request=pull_request)
332 assert status == ChangesetStatus.STATUS_REJECTED
333
327 334 def test_create_pull_request(self, backend, csrf_token):
328 335 commits = [
329 336 {'message': 'ancestor'},
General Comments 0
You need to be logged in to leave comments. Login now