#5291 Add API endpoint for reopening pull requests
Merged 2 years ago by ngompa. Opened 2 years ago by mfocko.
mfocko/pagure api-pr-reopen  into  master

file modified
+1
@@ -589,6 +589,7 @@ 

          fork.api_pull_request_merge,

          fork.api_pull_request_rebase,

          fork.api_pull_request_close,

+         fork.api_pull_request_reopen,

          fork.api_pull_request_add_comment,

          fork.api_pull_request_add_flag,

          fork.api_pull_request_get_flag,

file modified
+68
@@ -797,6 +797,74 @@ 

      return jsonout

  

  

+ @API.route("/<repo>/pull-request/<int:requestid>/reopen", methods=["POST"])

+ @API.route(

+     "/<namespace>/<repo>/pull-request/<int:requestid>/reopen", methods=["POST"]

+ )

+ @API.route(

+     "/fork/<username>/<repo>/pull-request/<int:requestid>/reopen",

+     methods=["POST"],

+ )

+ @API.route(

+     "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/reopen",

+     methods=["POST"],

+ )

+ @api_login_required(acls=["pull_request_close", "pull_request_update"])

+ @api_method

+ def api_pull_request_reopen(repo, requestid, username=None, namespace=None):

+     """

+     Reopen a pull-request

+     --------------------

+     Instruct Pagure to reopen a pull request.

+ 

+     ::

+ 

+         POST /api/0/<repo>/pull-request/<request id>/reopen

+         POST /api/0/<namespace>/<repo>/pull-request/<request id>/reopen

+ 

+     ::

+ 

+         POST /api/0/fork/<username>/<repo>/pull-request/<request id>/reopen

+         POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id>/reopen

+ 

+     Sample response

+     ^^^^^^^^^^^^^^^

+ 

+     ::

+ 

+         {

+           "message": "Pull-request reopened!"

+         }

+ 

+     """  # noqa

+     output = {}

+ 

+     repo = _get_repo(repo, username, namespace)

+     _check_pull_request(repo)

+     _check_token(repo, project_token=False)

+     request = _get_request(repo, requestid)

+ 

+     if (

+         not is_repo_committer(repo)

+         and not flask.g.fas_user.username == request.user.username

+     ):

+         raise pagure.exceptions.APIError(403, error_code=APIERROR.ENOPRCLOSE)

+ 

+     try:

+         pagure.lib.query.reopen_pull_request(

+             flask.g.session, request, flask.g.fas_user.username

+         )

+         flask.g.session.commit()

+         output["message"] = "Pull-request reopened!"

+     except SQLAlchemyError as err:  # pragma: no cover

+         flask.g.session.rollback()

+         _log.exception(err)

+         raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)

+ 

+     jsonout = flask.jsonify(output)

+     return jsonout

+ 

+ 

  @API.route("/<repo>/pull-request/<int:requestid>/comment", methods=["POST"])

  @API.route(

      "/<namespace>/<repo>/pull-request/<int:requestid>/comment",

@@ -1284,6 +1284,123 @@ 

          self.assertDictEqual(data, {"message": "Pull-request closed!"})

  

      @patch("pagure.lib.notify.send_email")

+     def test_api_pull_request_reopen(self, send_email):

+         """Test the api_pull_request_reopen method of the flask api."""

+         send_email.return_value = True

+ 

+         tests.create_projects(self.session)

+         tests.create_tokens(self.session)

+         tests.create_tokens_acl(self.session)

+ 

+         # Create the pull-request to close and reopen

+         repo = pagure.lib.query.get_authorized_project(self.session, "test")

+         forked_repo = pagure.lib.query.get_authorized_project(

+             self.session, "test"

+         )

+         req = pagure.lib.query.new_pull_request(

+             session=self.session,

+             repo_from=forked_repo,

+             branch_from="master",

+             repo_to=repo,

+             branch_to="master",

+             title="test pull-request",

+             user="pingou",

+         )

+         self.session.commit()

+         self.assertEqual(req.id, 1)

+         self.assertEqual(req.title, "test pull-request")

+ 

+         headers = {"Authorization": "token aaabbbcccddd"}

+ 

+         # Invalid project

+         output = self.app.post(

+             "/api/0/foo/pull-request/1/close", headers=headers

+         )

+         self.assertEqual(output.status_code, 404)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data, {"error": "Project not found", "error_code": "ENOPROJECT"}

+         )

+ 

+         # Valid token, wrong project

+         output = self.app.post(

+             "/api/0/test2/pull-request/1/close", headers=headers

+         )

+         self.assertEqual(output.status_code, 401)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertEqual(

+             pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]

+         )

+         self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])

+ 

+         # Invalid PR

+         output = self.app.post(

+             "/api/0/test/pull-request/2/close", headers=headers

+         )

+         self.assertEqual(output.status_code, 404)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}

+         )

+ 

+         # Create a token for foo for this project

+         item = pagure.lib.model.Token(

+             id="foobar_token",

+             user_id=2,

+             project_id=1,

+             expiration=datetime.datetime.utcnow()

+             + datetime.timedelta(days=30),

+         )

+         self.session.add(item)

+         self.session.commit()

+ 

+         # Allow the token to close and reopen PR

+         acls = pagure.lib.query.get_acls(self.session)

+         for acl in acls:

+             if acl.name == "pull_request_close":

+                 break

+         item = pagure.lib.model.TokenAcl(

+             token_id="foobar_token", acl_id=acl.id

+         )

+         self.session.add(item)

+         self.session.commit()

+ 

+         headers = {"Authorization": "token foobar_token"}

+ 

+         # User not admin

+         output = self.app.post(

+             "/api/0/test/pull-request/1/close", headers=headers

+         )

+         self.assertEqual(output.status_code, 403)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(

+             data,

+             {

+                 "error": "You are not allowed to merge/close pull-request "

+                 "for this project",

+                 "error_code": "ENOPRCLOSE",

+             },

+         )

+ 

+         headers = {"Authorization": "token aaabbbcccddd"}

+ 

+         # Close PR

+         output = self.app.post(

+             "/api/0/test/pull-request/1/close", headers=headers

+         )

+         self.assertEqual(output.status_code, 200)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(data, {"message": "Pull-request closed!"})

+ 

+         # Reopen PR

+         output = self.app.post(

+             "/api/0/test/pull-request/1/reopen", headers=headers

+         )

+         self.assertEqual(output.status_code, 200)

+         data = json.loads(output.get_data(as_text=True))

+         self.assertDictEqual(data, {"message": "Pull-request reopened!"})

+ 

+     @patch("pagure.lib.notify.send_email")

      def test_api_pull_request_merge_pr_disabled(self, send_email):

          """Test the api_pull_request_merge method of the flask api when PR

          are disabled."""

rebased onto 175f1949b5db8788130fb1d2f482185f1a2eb6ba

2 years ago

The new API endpoint should be added to the API documentation

rebased onto f2c6211e623e1b601c51b8917b10e1c9f1c6a68f

2 years ago

Hi, I have added it to the __init__.py for generation and also squashed it. Please have a look when you have time :)

rebased onto 4302d5d66a475ba37769c3272d30668672cf5a9d

2 years ago

rebased onto 60a979d198560fd4117d489ec8a86fc363341bd5

2 years ago

Hey @mfocko, I'm working on reviewing your changes. I'm trying to get the tests to run on my computer without triggering OOM to validate locally. :)

pretty please pagure-ci rebuild

2 years ago

Can I help in any way?

pretty please pagure-ci rebuild

2 years ago

rebased onto 2fe216caa85351290caba7aae53db4b305eae8b0

2 years ago

Our PR depending on this feature just got labelled as stale :) just a small reminder to not forget about this one

Maybe pull_request_update as well?

Other than expanding the ACLs needed to re-open a PR, I think this looks good :)

pretty please pagure-ci rebuild

2 years ago

@pingou @zlopez This is odd:

10:03:38 _pygit2.GitError: failed to resolve path '/tmp/pagure-tests-path-dxgm57fl/repos/test.git/': Operation not permitted

There's a lot of these in the CI log. What's going on here?

rebased onto 3112c395227e45ef8a66c6dd6b81ee0c66368352

2 years ago

rebased onto 378d3b6

2 years ago

I created a ticket for the errors in CentOS infra tracker. It seems that this was happening till the migration to new CI.

The tests pass locally, so I'm just going to merge this.

Pull-Request has been merged by ngompa

2 years ago