diff --git a/atlassian/bitbucket/cloud/repositories/pullRequests.py b/atlassian/bitbucket/cloud/repositories/pullRequests.py index e01784a33..bedd00f0c 100644 --- a/atlassian/bitbucket/cloud/repositories/pullRequests.py +++ b/atlassian/bitbucket/cloud/repositories/pullRequests.py @@ -50,10 +50,43 @@ def get(self, id): """ return self.__get_object(super(PullRequests, self).get(id)) - # def add(self): - # TODO add a new pull request - # TODO https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/pullrequests#post - # return PullRequest object + def create( + self, + title, + source_branch, + destination_branch=None, + description=None, + close_source_branch=None, + reviewers=None, + ): + """ + Creates a new pull requests for a given source branch + Be careful, adding this mulitple times for the same source branch updates the pull request! + + :param title: string: pull request title + :param source_branch: string: name of the source branch + :param destination_branch: string: name of the destination branch, if None the repository main branch is used + :param description: string: pull request description + :param close_source_branch: bool: specifies if the source branch should be closed upon merging + :param reviewers: list: list of user uuids in curly brackets + :return: Pull Request Object + + API docs: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/pullrequests#post + """ + + rv = [{"uuid": x} for x in reviewers] if reviewers else [] + data = { + "title": title, + "source": {"branch": {"name": source_branch}}, + "description": description, + "close_source_branch": close_source_branch, + "reviewers": rv, + } + if destination_branch: + data["destination"] = {"branch": {"name": destination_branch}} + response = self.post(self.url, data, absolute=True) + + return PullRequest(response["links"]["self"], response, **self._new_session_args) class PullRequest(BitbucketCloudBase): diff --git a/tests/responses/bitbucket/cloud/2.0/repositories/TestWorkspace1/testrepository1/pullrequests/POST b/tests/responses/bitbucket/cloud/2.0/repositories/TestWorkspace1/testrepository1/pullrequests/POST new file mode 100644 index 000000000..03af9fcd5 --- /dev/null +++ b/tests/responses/bitbucket/cloud/2.0/repositories/TestWorkspace1/testrepository1/pullrequests/POST @@ -0,0 +1,254 @@ +responses[ + '{"title": "PRTitle", "source": {"branch": {"name": "feature/test-branch"}}, "description": "PRDescription", "close_source_branch": true, "reviewers": [{"uuid": "{User04UUID}"}, {"uuid": "{User02UUID}"}, {"uuid": "{User01UUID}"}], "destination": {"branch": {"name": "master"}}}' +] = { + "rendered": { + "description": { + "raw": "PRDescription", + "markup": "markdown", + "html": "
PRDescription
", + "type": "rendered", + }, + "title": {"raw": "PRTitle", "markup": "markdown", "html": "PRTitle
", "type": "rendered"}, + }, + "type": "pullrequest", + "description": "PRDescription", + "links": { + "decline": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1/decline"}, + "diffstat": { + "href": "repositories/TestWorkspace1/testrepository1/diffstat/TestWorkspace1/testrepository1:16182c4698fb%0D1fbd047cd123?from_pullrequest_id=1" + }, + "commits": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1/commits"}, + "self": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1"}, + "comments": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1/comments"}, + "merge": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1/merge"}, + "html": {"href": "https://bitbucket.org/TestWorkspace1/testrepository1/pull-requests/1"}, + "activity": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1/activity"}, + "request-changes": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1/request-changes"}, + "diff": { + "href": "repositories/TestWorkspace1/testrepository1/diff/TestWorkspace1/testrepository1:16182c4698fb%0D1fbd047cd123?from_pullrequest_id=1" + }, + "approve": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1/approve"}, + "statuses": {"href": "repositories/TestWorkspace1/testrepository1/pullrequests/1/statuses"}, + }, + "title": "PRTitle", + "close_source_branch": true, + "reviewers": [ + { + "display_name": "User04DisplayName", + "uuid": "{User04UUID}", + "links": { + "self": {"href": "users/%7BUser04UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser04UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU4-2.png" + }, + }, + "nickname": "User04Nickname", + "type": "user", + "account_id": "User04AccountID", + }, + { + "display_name": "User02DisplayName", + "uuid": "{User02UUID}", + "links": { + "self": {"href": "users/%7BUser02UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser02UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU2-3.png" + }, + }, + "nickname": "User02Nickname", + "type": "user", + "account_id": "User02AccountID", + }, + { + "display_name": "User01DisplayName", + "uuid": "{User01UUID}", + "links": { + "self": {"href": "users/%7BUser01UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser01UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU1-3.png" + }, + }, + "nickname": "User01Nickname", + "type": "user", + "account_id": "User01AccountID", + }, + ], + "id": 1, + "destination": { + "commit": { + "hash": "1fbd047cd99a", + "type": "commit", + "links": { + "self": {"href": "repositories/TestWorkspace1/testrepository1/commit/1fbd047cd99a"}, + "html": {"href": "https://bitbucket.org/TestWorkspace1/testrepository1/commits/1fbd047cd99a"}, + }, + }, + "repository": { + "links": { + "self": {"href": "repositories/TestWorkspace1/testrepository1"}, + "html": {"href": "https://bitbucket.org/TestWorkspace1/testrepository1"}, + "avatar": {"href": "https://bytebucket.org/ravatar/%7BRepoUUID%7D?ts=default"}, + }, + "type": "repository", + "name": "testrepository1", + "full_name": "TestWorkspace1/testrepository1", + "uuid": "{RepoUUID}", + }, + "branch": {"name": "master"}, + }, + "created_on": "2020-03-19T12:00:03.494356+00:00", + "summary": {"raw": "PRDescription", "markup": "markdown", "html": "PRDescription
", "type": "rendered"}, + "source": { + "commit": { + "hash": "16182c4123fb", + "type": "commit", + "links": { + "self": {"href": "repositories/TestWorkspace1/testrepository1/commit/16182c4123fb"}, + "html": {"href": "https://bitbucket.org/TestWorkspace1/testrepository1/commits/16182c4123fb"}, + }, + }, + "repository": { + "links": { + "self": {"href": "repositories/TestWorkspace1/testrepository1"}, + "html": {"href": "https://bitbucket.org/TestWorkspace1/testrepository1"}, + "avatar": {"href": "https://bytebucket.org/ravatar/%7BRepoUUID%7D?ts=default"}, + }, + "type": "repository", + "name": "testrepository1", + "full_name": "TestWorkspace1/testrepository1", + "uuid": "{RepoUUID}", + }, + "branch": {"name": "feature/test-branch"}, + }, + "comment_count": 5, + "state": "OPEN", + "task_count": 0, + "participants": [ + { + "participated_on": "2020-03-19T14:29:24.928709+00:00", + "state": null, + "role": "PARTICIPANT", + "user": { + "display_name": "User05DisplayName", + "uuid": "{User05UUID}", + "links": { + "self": {"href": "users/%7BUser05UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser05UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2U5-5.png" + }, + }, + "nickname": "User05Nickname", + "type": "user", + "account_id": "User05AccountID", + }, + "type": "participant", + "approved": false, + }, + { + "participated_on": "2020-07-09T07:00:54.416331+00:00", + "state": null, + "role": "PARTICIPANT", + "user": { + "display_name": "User03DisplayName", + "uuid": "{User03UUID}", + "links": { + "self": {"href": "users/%7BUser03UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser03UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU3-0.png" + }, + }, + "nickname": "User03Nickname", + "type": "user", + "account_id": "User03AccountID", + }, + "type": "participant", + "approved": false, + }, + { + "participated_on": "2020-12-27T14:09:14.660262+00:00", + "state": "approved", + "role": "REVIEWER", + "user": { + "display_name": "User04DisplayName", + "uuid": "{User04UUID}", + "links": { + "self": {"href": "users/%7BUser04UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser04UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU4-2.png" + }, + }, + "nickname": "User04Nickname", + "type": "user", + "account_id": "User04AccountID", + }, + "type": "participant", + "approved": true, + }, + { + "participated_on": "2020-12-27T14:05:58.999476+00:00", + "state": "changes_requested", + "role": "REVIEWER", + "user": { + "display_name": "User01DisplayName", + "uuid": "{User01UUID}", + "links": { + "self": {"href": "users/%7BUser01UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser01UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU1-3.png" + }, + }, + "nickname": "User01Nickname", + "type": "user", + "account_id": "User01AccountID", + }, + "type": "participant", + "approved": false, + }, + { + "participated_on": null, + "state": null, + "role": "REVIEWER", + "user": { + "display_name": "User02DisplayName", + "uuid": "{User02UUID}", + "links": { + "self": {"href": "users/%7BUser02UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser02UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU2-3.png" + }, + }, + "nickname": "User02Nickname", + "type": "user", + "account_id": "User02AccountID", + }, + "type": "participant", + "approved": false, + }, + ], + "reason": "", + "updated_on": "2020-12-27T14:09:14.660262+00:00", + "author": { + "display_name": "User03DisplayName", + "uuid": "{User03UUID}", + "links": { + "self": {"href": "users/%7BUser03UUID%7D"}, + "html": {"href": "https://bitbucket.org/%7BUser03UUID%7D/"}, + "avatar": { + "href": "https://secure.gravatar.com/avatar/ad2424dafaasdssaew12232344434432?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU3-0.png" + }, + }, + "nickname": "User03Nickname", + "type": "user", + "account_id": "User03AccountID", + }, + "merge_commit": null, + "closed_by": null, +} diff --git a/tests/test_bitbucket_cloud.py b/tests/test_bitbucket_cloud.py index 784c214e7..e8c1e5682 100644 --- a/tests/test_bitbucket_cloud.py +++ b/tests/test_bitbucket_cloud.py @@ -166,7 +166,7 @@ def tc1(self): @pytest.fixture(scope="module") def tc2(self): - return CLOUD.workspaces.get("TestWorkspace1").repositories.get("testrepository1").pullrequests.each() + return CLOUD.workspaces.get("TestWorkspace1").repositories.get("testrepository1").pullrequests def test_id(self, tc1): assert tc1.id == 1 @@ -293,8 +293,21 @@ def test_merge(self, tc1): assert merge["merge_commit"]["hash"] == "36bb9607a8c9e0c6222342486e3393ae154b46c0" def test_each(self, tc2): - prs = list(tc2) + prs = list(tc2.each()) assert len(prs) == 2 assert isinstance(prs[0], PullRequest) assert prs[0].id == 1 assert prs[1].id == 25 + + def test_create(self, tc2): + reviewers = ["{User04UUID}", "{User02UUID}", "{User01UUID}"] + pr = tc2.create( + title="PRTitle", + source_branch="feature/test-branch", + destination_branch="master", + description="PRDescription", + close_source_branch=True, + reviewers=reviewers, + ) + assert pr.id == 1 + assert len(list(pr.reviewers())) == 3