async def test_labeled_on_unmerged_pr_is_ignored(): data = {"action": "labeled", "pull_request": {"merged": False}} event = sansio.Event(data, event="pull_request", delivery_id="1") gh = FakeGH() await backport_pr.router.dispatch(event, gh) assert gh.getitem_url is None
async def test_check_run_completed_with_awaiting_merge_label_not_miss_islington_is_not_merged( ): sha = "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9" data = { "action": "completed", "check_run": { "head_sha": sha }, "sender": { "login": "******" }, } event = sansio.Event(data, event="check_run", delivery_id="1") getitem = { f"/repos/python/cpython/commits/{sha}/status": { "state": "success", "statuses": [ { "state": "success", "description": "Issue report skipped", "context": "bedevere/issue-number", }, { "state": "success", "description": "The Travis CI build passed", "target_url": "https://travis-ci.org/python/cpython/builds/340259685?utm_source=github_status&utm_medium=notification", "context": "continuous-integration/travis-ci/pr", }, ], }, "/repos/python/cpython/pulls/5544": { "user": { "login": "******" }, "merged_by": { "login": "******" }, }, "/repos/python/cpython/pulls/5547": { "labels": [{ "name": "awaiting merge" }] }, f"/search/issues?q=type:pr+repo:python/cpython+sha:{sha}": { "total_count": 1, "items": [{ "number": 5547, "title": "bpo-32720: Fixed the replacement field grammar documentation.", "body": "\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>", "labels": [{ "name": "awaiting merge" }], }], }, } gh = FakeGH(getitem=getitem) await check_run.router.dispatch(event, gh) assert not hasattr(gh, "post_data") # does not leave a comment assert not hasattr(gh, "put_data") # is not merged
async def test_non_core_dev_does_not_downgrade(): core_dev = "brettcannon" non_core_dev = "andreamcinnes" teams = [{"name": "python core", "id": 6}] items = { f"https://api.github.com/teams/6/memberships/{non_core_dev}": gidgethub.BadRequest(status_code=http.HTTPStatus(404)), f"https://api.github.com/teams/6/memberships/{core_dev}": True, "https://api.github.com/issue/42": { "labels": [], "labels_url": "https://api.github.com/labels/42", } } # Approval from a core dev changes the state to "Awaiting merge". data = { "action": "submitted", "review": { "state": "approved", "user": { "login": core_dev, }, }, "pull_request": { "url": "https://api.github.com/pr/42", "issue_url": "https://api.github.com/issue/42", }, } event = sansio.Event(data, event="pull_request_review", delivery_id="12345") iterators = { "https://api.github.com/orgs/python/teams": teams, "https://api.github.com/pr/42/reviews": [{ "user": { "login": core_dev }, "state": "approved" }], } gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert len(gh.post_) == 1 post_ = gh.post_[0] assert post_[0] == "https://api.github.com/labels/42" assert post_[1] == [awaiting.Blocker.merge.value] # Non-comment review from a non-core dev doesn't "downgrade" the PR's state. data = { "action": "submitted", "review": { "state": "approved", "user": { "login": non_core_dev, }, }, "pull_request": { "url": "https://api.github.com/pr/42", "issue_url": "https://api.github.com/issue/42", }, } event = sansio.Event(data, event="pull_request_review", delivery_id="12345") iterators = { "https://api.github.com/orgs/python/teams": teams, "https://api.github.com/pr/42/reviews": [ { "user": { "login": core_dev }, "state": "approved" }, { "user": { "login": non_core_dev }, "state": "approved" }, ], } gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert not gh.post_
async def test_new_comment(): # Comment not from PR author. data = { "action": "created", "issue": { "user": { "login": "******" } }, "comment": { "user": { "login": "******" }, "body": awaiting.BORING_TRIGGER_PHRASE, }, } event = sansio.Event(data, event="issue_comment", delivery_id="12345") gh = FakeGH() await awaiting.router.dispatch(event, gh) assert not len(gh.post_) # Comment from PR author but missing trigger phrase. data = { "action": "created", "issue": { "user": { "login": "******" } }, "comment": { "user": { "login": "******" }, "body": "I DID expect the Spanish Inquisition", }, } event = sansio.Event(data, event="issue_comment", delivery_id="12345") gh = FakeGH() await awaiting.router.dispatch(event, gh) assert not len(gh.post_) # Everything is right with the world. data = { "action": "created", "issue": { "user": { "login": "******" }, "labels": [], "labels_url": "https://api.github.com/labels/42", "url": "https://api.github.com/issue/42", "pull_request": { "url": "https://api.github.com/pr/42" }, "comments_url": "https://api.github.com/comments/42", }, "comment": { "user": { "login": "******" }, "body": awaiting.BORING_TRIGGER_PHRASE, }, } event = sansio.Event(data, event="issue_comment", delivery_id="12345") items = { "https://api.github.com/teams/6/memberships/brettcannon": True, "https://api.github.com/teams/6/memberships/gvanrossum": True, "https://api.github.com/teams/6/memberships/not-core-dev": gidgethub.BadRequest(status_code=http.HTTPStatus(404)), } iterators = { "https://api.github.com/orgs/python/teams": [{ "name": "python core", "id": 6 }], "https://api.github.com/pr/42/reviews": [ { "user": { "login": "******" }, "state": "approved" }, { "user": { "login": "******" }, "state": "changes_requested" }, { "user": { "login": "******" }, "state": "approved" }, ], } gh = FakeGH(getitem=items, getiter=iterators) await awaiting.router.dispatch(event, gh) assert len(gh.post_) == 3 labeling, comment, review_request = gh.post_ assert labeling[0] == "https://api.github.com/labels/42" assert labeling[1] == [awaiting.Blocker.change_review.value] assert comment[0] == "https://api.github.com/comments/42" comment_body = comment[1]["body"] assert "@brettcannon" in comment_body assert "@gvanrossum" in comment_body assert "not-core-dev" not in comment_body assert review_request[ 0] == "https://api.github.com/pr/42/requested_reviewers" requested_reviewers = review_request[1]["reviewers"] assert "brettcannon" in requested_reviewers assert "gvanrossum" in requested_reviewers assert "not-core-dev" not in requested_reviewers # All is right with the Monty Python world. data = { "action": "created", "issue": { "user": { "login": "******" }, "labels": [], "labels_url": "https://api.github.com/labels/42", "url": "https://api.github.com/issue/42", "pull_request": { "url": "https://api.github.com/pr/42" }, "comments_url": "https://api.github.com/comments/42", }, "comment": { "user": { "login": "******" }, "body": awaiting.FUN_TRIGGER_PHRASE, }, } event = sansio.Event(data, event="issue_comment", delivery_id="12345") gh = FakeGH(getitem=items, getiter=iterators) await awaiting.router.dispatch(event, gh) assert len(gh.post_) == 3 labeling, comment, review_request = gh.post_ assert labeling[0] == "https://api.github.com/labels/42" assert labeling[1] == [awaiting.Blocker.change_review.value] assert comment[0] == "https://api.github.com/comments/42" comment_body = comment[1]["body"] assert "@brettcannon" in comment_body assert "@gvanrossum" in comment_body assert "not-core-dev" not in comment_body assert review_request[ 0] == "https://api.github.com/pr/42/requested_reviewers" requested_reviewers = review_request[1]["reviewers"] assert "brettcannon" in requested_reviewers assert "gvanrossum" in requested_reviewers assert "not-core-dev" not in requested_reviewers
async def test_ci_passed_automerge(): sha = "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9" data = { "action": "completed", "check_run": { "head_sha": sha }, "sender": { "login": "******" }, } event = sansio.Event(data, event="check_run", delivery_id="1") getitem = { f"/repos/python/cpython/commits/{sha}/status": { "state": "success", "statuses": [ { "state": "success", "description": "Issue report skipped", "context": "bedevere/issue-number", }, { "state": "success", "description": "The Travis CI build passed", "target_url": "https://travis-ci.org/python/cpython/builds/340259685?utm_source=github_status&utm_medium=notification", "context": "continuous-integration/travis-ci/pr", }, ], }, "/repos/python/cpython/pulls/5547": { "user": { "login": "******" }, "merged_by": None, "labels": [ { "name": "awaiting merge" }, { "name": AUTOMERGE_LABEL }, ], }, f"/search/issues?q=type:pr+repo:python/cpython+sha:{sha}": { "total_count": 1, "items": [{ "number": 5547, "title": "bpo-32720: Fixed the replacement field grammar documentation.", "body": "\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>", "labels": [ { "name": "awaiting merge" }, { "name": AUTOMERGE_LABEL }, ], }], }, f"/repos/python/cpython/commits/{sha}/check-runs": { "check_runs": [{ "conclusion": "success", "name": "Travis CI - Pull Request", "status": "completed", }], "total_count": 1, }, } getiter = { "/repos/python/cpython/pulls/5547/commits": [{ "sha": "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9", "commit": { "message": "bpo-32720: Fixed the replacement field grammar documentation." }, }] } gh = FakeGH(getitem=getitem, getiter=getiter) await check_run.router.dispatch(event, gh) assert len(gh.post_data["body"]) is not None # leaves a comment assert gh.put_data["sha"] == sha # is merged assert gh.put_data["merge_method"] == "squash" assert ( gh.put_data["commit_title"] == "bpo-32720: Fixed the replacement field grammar documentation. (GH-5547)" )
async def test_new_review(): # First non-comment review from a non-core dev. username = "******" data = { "action": "submitted", "review": { "state": "approved", "user": { "login": username, }, }, "pull_request": { "url": "https://api.github.com/pr/42", "issue_url": "https://api.github.com/issue/42", }, } event = sansio.Event(data, event="pull_request_review", delivery_id="12345") teams = [{"name": "python core", "id": 6}] items = { f"https://api.github.com/teams/6/memberships/{username}": gidgethub.BadRequest(status_code=http.HTTPStatus(404)), "https://api.github.com/teams/6/memberships/brettcannon": True, "https://api.github.com/issue/42": { "labels": [], "labels_url": "https://api.github.com/labels/42", } } iterators = { "https://api.github.com/orgs/python/teams": teams, "https://api.github.com/pr/42/reviews": [{ "user": { "login": "******" }, "state": "commented" }], } gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert len(gh.post_) == 1 post_ = gh.post_[0] assert post_[0] == "https://api.github.com/labels/42" assert post_[1] == [awaiting.Blocker.core_review.value] # First and second review from a non-core dev. items = { f"https://api.github.com/teams/6/memberships/{username}": gidgethub.BadRequest(status_code=http.HTTPStatus(404)), "https://api.github.com/teams/6/memberships/brettcannon": True, "https://api.github.com/issue/42": { "labels": [], "labels_url": "https://api.github.com/labels/42", } } iterators = { "https://api.github.com/orgs/python/teams": teams, "https://api.github.com/pr/42/reviews": [{ "user": { "login": "******" }, "state": "approved" }], } gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert not gh.post_ # First comment review from a non-core dev. data = { "action": "submitted", "review": { "state": "comment", "user": { "login": username, }, }, "pull_request": { "url": "https://api.github.com/pr/42", "issue_url": "https://api.github.com/issue/42", }, } event = sansio.Event(data, event="pull_request_review", delivery_id="12345") items = { f"https://api.github.com/teams/6/memberships/{username}": gidgethub.BadRequest(status_code=http.HTTPStatus(404)), "https://api.github.com/teams/6/memberships/brettcannon": True, "https://api.github.com/issue/42": { "labels": [], "labels_url": "https://api.github.com/labels/42", } } iterators = { "https://api.github.com/orgs/python/teams": teams, "https://api.github.com/pr/42/reviews": [{ "user": { "login": "******" }, "state": "approved" }], } gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert not gh.post_ # Core dev submits an approving review. username = "******" data = { "action": "submitted", "review": { "user": { "login": username, }, "state": "APPROVED", }, "pull_request": { "url": "https://api.github.com/pr/42", "issue_url": "https://api.github.com/issue/42", }, } event = sansio.Event(data, event="pull_request_review", delivery_id="12345") teams = [{"name": "python core", "id": 6}] items = { f"https://api.github.com/teams/6/memberships/{username}": True, "https://api.github.com/issue/42": { "labels": [{ "name": awaiting.Blocker.changes.value }], "labels_url": "https://api.github.com/labels/42", } } iterators = { "https://api.github.com/orgs/python/teams": teams, "https://api.github.com/pr/42/reviews": [], } gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert len(gh.post_) == 1 post_ = gh.post_[0] assert post_[0] == "https://api.github.com/labels/42" assert post_[1] == [awaiting.Blocker.merge.value] # Core dev requests changes. data = { "action": "submitted", "review": { "user": { "login": username, }, "state": "changes_requested".upper(), }, "pull_request": { "url": "https://api.github.com/pr/42", "issue_url": "https://api.github.com/issue/42", "comments_url": "https://api.github.com/comment/42", "user": { "login": "******" } }, } event = sansio.Event(data, event="pull_request_review", delivery_id="12345") items = { f"https://api.github.com/teams/6/memberships/{username}": True, f"https://api.github.com/teams/6/memberships/miss-islington": gidgethub.BadRequest(status_code=http.HTTPStatus(404)), "https://api.github.com/issue/42": { "labels": [], "labels_url": "https://api.github.com/labels/42", } } gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert len(gh.post_) == 2 labeling = gh.post_[0] assert labeling[0] == "https://api.github.com/labels/42" assert labeling[1] == [awaiting.Blocker.changes.value] message = gh.post_[1] assert message[0] == "https://api.github.com/comment/42" assert awaiting.BORING_TRIGGER_PHRASE in message[1]["body"] # Comment reviews do nothing. data = { "action": "submitted", "review": { "user": { "login": username, }, "state": "commented".upper(), }, "pull_request": { "url": "https://api.github.com/pr/42", "issue_url": "https://api.github.com/issue/42", "comments_url": "https://api.github.com/comment/42", }, } event = sansio.Event(data, event="pull_request_review", delivery_id="12345") gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert not len(gh.post_) # Skip commenting if "awaiting changes" is already set. data = { "action": "submitted", "review": { "user": { "login": username, }, "state": "changes_requested".upper(), }, "pull_request": { "url": "https://api.github.com/pr/42", "issue_url": "https://api.github.com/issue/42", "comments_url": "https://api.github.com/comment/42", }, } event = sansio.Event(data, event="pull_request_review", delivery_id="12345") items = { f"https://api.github.com/teams/6/memberships/{username}": True, "https://api.github.com/issue/42": { "labels": [{ "name": awaiting.Blocker.changes.value }], "labels_url": "https://api.github.com/labels/42", } } gh = FakeGH(getiter=iterators, getitem=items) await awaiting.router.dispatch(event, gh) assert not len(gh.post_)
async def test_travis_not_done(): sha = "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9" data = { "sha": sha, "commit": { "committer": { "login": "******", }, } } event = sansio.Event(data, event='status', delivery_id='1') getitem = { f'/repos/python/cpython/commits/{sha}/status': { "state": "success", "statuses": [{ "state": "success", "description": "Issue report skipped", "context": "bedevere/issue-number", }] }, "/repos/python/cpython/pulls/5544": { "user": { "login": "******" }, "merged_by": { "login": "******" } }, "/teams/42/memberships/Mariatta": True } getiter = { '/repos/miss-islington/cpython/git/refs/heads/': [{ "ref": f"refs/heads/backport-{sha[0:7]}-3.6", "object": { "sha": sha, } }, { "ref": "refs/heads/backport-63ae044-3.6", "object": { "sha": "67a2b0b7713e40dea7762b7d7764ae18fe967561", "type": "commit", "url": "https://api.github.com/repos/miss-islington/cpython/git/commits/67a2b0b7713e40dea7762b7d7764ae18fe967561" } }], f'/repos/python/cpython/pulls?state=open&head=miss-islington:backport-{sha[0:7]}-3.6': [ { "number": 5547, "title": "[3.6] bpo-32720: Fixed the replacement field grammar documentation. (GH-5544)", "body": "\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>" }, ], '/repos/python/cpython/pulls/5547/reviews': [{ "user": { "login": "******" }, "state": "APPROVED" }], '/repos/python/cpython/pulls/5547/commits': [{ "sha": "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9", "commit": { "message": "bpo-32720: Fixed the replacement field grammar documentation. (GH-5544)\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>" } }], "/orgs/python/teams": [{ "name": "Python core", "id": 42 }], } gh = FakeGH(getitem=getitem, getiter=getiter) await status_change.router.dispatch(event, gh) assert not hasattr(gh, 'post_data') # does not leave a comment assert not hasattr(gh, 'put_data') # is not merged
async def test_branch_sha_not_matched_pr_not_merged(): sha = "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9" data = {"sha": sha, "commit": {"committer": {"login": "******"}}} event = sansio.Event(data, event="status", delivery_id="1") getitem = { f"/repos/python/cpython/commits/{sha}/status": { "state": "success", "statuses": [ { "state": "success", "description": "Issue report skipped", "context": "bedevere/issue-number", }, { "state": "success", "description": "The Travis CI build passed", "target_url": "https://travis-ci.org/python/cpython/builds/340259685?utm_source=github_status&utm_medium=notification", "context": "continuous-integration/travis-ci/pr", }, ], }, "/repos/python/cpython/pulls/5544": { "user": { "login": "******" }, "merged_by": { "login": "******" }, }, "/repos/python/cpython/pulls/5547": { "labels": [{ "name": "awaiting merge" }] }, } getiter = { "/repos/miss-islington/cpython/git/refs/heads/": [ { "ref": f"refs/heads/backport-{sha[0:7]}-3.6", "object": { "sha": sha } }, { "ref": "refs/heads/backport-63ae044-3.6", "object": { "sha": "67a2b0b7713e40dea7762b7d7764ae18fe967561", "type": "commit", "url": "https://api.github.com/repos/miss-islington/cpython/git/commits/67a2b0b7713e40dea7762b7d7764ae18fe967561", }, }, ], f"/repos/python/cpython/pulls?state=open&head=miss-islington:backport-{sha[0:7]}-3.6": [{ "number": 5547, "title": "[3.6] bpo-32720: Fixed the replacement field grammar documentation. (GH-5544)", "body": "\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>", }], "/repos/python/cpython/pulls/5547/commits": [{ "sha": "f2393593c99dd2d3", "commit": { "message": "bpo-32720: Fixed the replacement field grammar documentation. (GH-5544)\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>" }, }], } gh = FakeGH(getitem=getitem, getiter=getiter) await status_change.router.dispatch(event, gh) assert not hasattr(gh, "put_data") # is not merged
async def test_check_run_completed_failing_with_label(): data = { "action": "completed", "check_run": { "head_sha": sha, "status": "completed", "conclusion": "timed_out", }, "name": "Travis CI - Pull Request", "repository": { "full_name": repository }, "installation": { "id": MOCK_INSTALLATION_ID }, } event = sansio.Event(data, event="check_run", delivery_id="7") getitem = { search_url: { "total_count": 1, "items": [{ "number": number, "state": "open", "labels": [ { "name": "Status: awaiting reviews" }, { "name": Label.FAILED_TEST }, ], "labels_url": check_run_url, }], }, check_run_url: { "total_count": 2, "check_runs": [ { "status": "completed", "conclusion": "timed_out", "name": "Travis CI - Pull Request", }, { "status": "completed", "conclusion": "success", "name": "pre-commit", }, ], }, } gh = MockGitHubAPI(getitem=getitem) result = await check_runs.router.dispatch(event, gh) assert result is None assert len(gh.getitem_url) == 2 assert gh.getitem_url == [search_url, check_run_url] assert gh.post_data == [] # does not add any label assert gh.post_url == [] assert gh.delete_url == [] # does not delete any label
async def test_pr_reviewed_webhook_ci_passed_pr_is_merged(): sha = "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9" data = { "action": "submitted", "pull_request": { "user": { "login": "******" } }, "review": { "commit_id": sha, "user": { "login": "******" }, "state": "approved" } } event = sansio.Event(data, event='pull_request_review', delivery_id='1') getitem = { f'/repos/python/cpython/commits/{sha}/status': { "state": "success", "statuses": [{ "state": "success", "description": "Issue report skipped", "context": "bedevere/issue-number", }, { "state": "success", "description": "The Travis CI build passed", "target_url": "https://travis-ci.org/python/cpython/builds/340259685?utm_source=github_status&utm_medium=notification", "context": "continuous-integration/travis-ci/pr", }] }, "/teams/42/memberships/Mariatta": True } getiter = { '/repos/miss-islington/cpython/git/refs/heads/': [{ "ref": f"refs/heads/backport-{sha[0:7]}-3.6", "object": { "sha": sha, } }, { "ref": f"refs/heads/backport-{sha[0:7]}-3.6", "object": { "sha": sha, "type": "commit", "url": f"https://api.github.com/repos/miss-islington/cpython/git/commits/{sha}" } }], f'/repos/python/cpython/pulls?state=open&head=miss-islington:backport-{sha[0:7]}-3.6': [ { "number": 5547, "title": "[3.6] bpo-32720: Fixed the replacement field grammar documentation. (GH-5544)", "body": "\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>" }, ], "/orgs/python/teams": [{ "name": "Python core", "id": 42 }], '/repos/python/cpython/pulls/5547/reviews': [{ "user": { "login": "******" }, "state": "APPROVED" }], '/repos/python/cpython/pulls/5547/commits': [{ "sha": "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9", "commit": { "message": "bpo-32720: Fixed the replacement field grammar documentation. (GH-5544)\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>" } }], } gh = FakeGH(getitem=getitem, getiter=getiter) await status_change.router.dispatch(event, gh) assert not hasattr(gh, 'post_data') # does not leave a comment assert gh.put_data["sha"] == sha # is merged assert gh.put_data["merge_method"] == "squash" assert gh.put_data[ "commit_title"] == "bpo-32720: Fixed the replacement field grammar documentation. (GH-5544)"
async def test_check_run_completed_passing_with_label(): rm_labels_url = f"{labels_url}/{urllib.parse.quote(Label.FAILED_TEST)}" data = { "action": "completed", "check_run": { "head_sha": sha, "status": "completed", "conclusion": "action_required", }, "name": "validate-solutions", "repository": { "full_name": repository }, "installation": { "id": MOCK_INSTALLATION_ID }, } event = sansio.Event(data, event="check_run", delivery_id="5") getitem = { search_url: { "total_count": 1, "items": [{ "number": number, "state": "open", "labels": [ { "name": "Status: awaiting reviews" }, { "name": Label.FAILED_TEST }, ], "labels_url": labels_url, }], }, check_run_url: { "total_count": 2, "check_runs": [ { "status": "completed", "conclusion": "action_required", "name": "validate-solutions", }, { "status": "completed", "conclusion": "success", "name": "pre-commit", }, ], }, } delete = {rm_labels_url: [{"name": "Status: awaiting reviews"}]} gh = MockGitHubAPI(getitem=getitem, delete=delete) result = await check_runs.router.dispatch(event, gh) assert result is None assert len(gh.getitem_url) == 2 assert gh.getitem_url == [search_url, check_run_url] assert gh.post_url == [] assert gh.post_data == [] # does not add any label assert gh.delete_url[0] == rm_labels_url
async def test_new_commit_pushed_to_approved_pr(): # There is new commit on approved PR username = "******" sha = "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9" data = {"commits": [{"id": sha}]} event = sansio.Event(data, event="push", delivery_id="12345") teams = [{"name": "python core", "id": 6}] items = { f"https://api.github.com/teams/6/memberships/{username}": "OK", f"https://api.github.com/search/issues?q=type:pr+repo:python/cpython+sha:{sha}": { "total_count": 1, "items": [{ "number": 5547, "title": "[3.6] bpo-32720: Fixed the replacement field grammar documentation. (GH-5544)", "body": "\n\n`arg_name` and `element_index` are defined as `digit`+ instead of `integer`.\n(cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119)\n\nCo-authored-by: Mariatta <*****@*****.**>", "labels": [{ "name": "CLA signed", }, { "name": "awaiting merge", }], "issue_url": "/repos/python/cpython/issues/5547", }], }, "https://api.github.com/repos/python/cpython/issues/5547": { "labels": [{ "name": "awaiting merge" }], "labels_url": "https://api.github.com/repos/python/cpython/issues/5547/labels{/name}", "pull_request": { "url": "https://api.github.com/repos/python/cpython/pulls/5547", }, "comments_url": "https://api.github.com/repos/python/cpython/issues/5547/comments", }, } gh = FakeGH( getiter={ "https://api.github.com/orgs/python/teams": teams, "https://api.github.com/repos/python/cpython/pulls/5547/reviews": [{ "user": { "login": "******" }, "state": "approved" }], }, getitem=items, ) await awaiting.router.dispatch(event, gh) # 3 posts: # - change the label # - leave a comment # - re-request review assert len(gh.post_) == 3 assert (gh.post_[0][0] == "https://api.github.com/repos/python/cpython/issues/5547/labels") assert gh.post_[0][1] == [awaiting.Blocker.core_review.value] assert (gh.post_[1][0] == "https://api.github.com/repos/python/cpython/issues/5547/comments") assert gh.post_[1][1] == { "body": ACK.format( greeting="There's a new commit after the PR has been approved.", core_devs="@brettcannon", ) }
async def test_pr_with_remove_all_require_labels(): # This case will only be true when the action is `synchronize` test_label_url = labels_url + f"/{urllib.parse.quote(Label.REQUIRE_TEST)}" names_label_url = labels_url + f"/{urllib.parse.quote(Label.DESCRIPTIVE_NAMES)}" annotation_label_url = labels_url + f"/{urllib.parse.quote(Label.ANNOTATIONS)}" data = { "action": "synchronize", "number": number, "pull_request": { "number": number, "url": pr_url, "body": CHECKBOX_TICKED, "labels": [ { "name": Label.REQUIRE_TEST }, { "name": Label.DESCRIPTIVE_NAMES }, { "name": Label.ANNOTATIONS }, ], "user": { "login": user }, "author_association": "NONE", "comments_url": comments_url, "issue_url": issue_url, "html_url": html_pr_url, "requested_reviewers": [{ "login": "******" }, { "login": "******" }], "draft": False, }, "repository": { "full_name": repository }, "installation": { "id": MOCK_INSTALLATION_ID }, } event = sansio.Event(data, event="pull_request", delivery_id="1") getiter = { files_url: [ { "filename": "no_errors.py", "contents_url": "", "status": "added" }, { "filename": "algorithm.py", "contents_url": "", "status": "added" }, ], } delete = { test_label_url: {}, names_label_url: {}, annotation_label_url: {} } gh = MockGitHubAPI(getiter=getiter, delete=delete) await pull_requests.router.dispatch(event, gh) assert len(gh.getiter_url) == 1 assert gh.getiter_url[0] == files_url # No labels are added assert gh.post_url == [] assert gh.post_data == [] # All labels are deleted assert gh.delete_url == [ test_label_url, names_label_url, annotation_label_url ] assert gh.delete_data == [{}, {}, {}]
async def test_max_pr_reached(): data = { "action": "opened", "number": number, "pull_request": { "number": number, "url": pr_url, "body": CHECKBOX_TICKED, "head": { "sha": sha }, "labels": [], "user": { "login": user }, "author_association": "NONE", "comments_url": comments_url, "issue_url": issue_url, "html_url": html_pr_url, "requested_reviewers": [{ "login": "******" }, { "login": "******" }], "draft": False, }, "repository": { "full_name": repository }, "installation": { "id": MOCK_INSTALLATION_ID }, } event = sansio.Event(data, event="pull_request", delivery_id="1") getiter = { pr_user_search_url: { "total_count": 2, "items": [ { "number": 1, "state": "opened" }, { "number": 2, "state": "opened" }, ], }, files_url: [], # for check_pr_files function } post = {comments_url: {}} patch = {pr_url: {}} delete = {reviewers_url: {}} gh = MockGitHubAPI(getiter=getiter, post=post, patch=patch, delete=delete) await pull_requests.router.dispatch(event, gh) assert gh.getiter_url[0] == pr_user_search_url assert gh.post_url[0] == comments_url assert gh.post_data[0] == { "body": MAX_PR_REACHED_COMMENT.format(user_login=user, pr_number="#1, #2") } assert gh.patch_url[0] == pr_url assert gh.delete_url[0] == reviewers_url assert gh.delete_data[0] == {"reviewers": ["test1", "test2"]}
async def test_label_on_ready_for_review_pr(): # Open a PR in draft # Convert the draft PR to ready for review PR # Tests are failing on the latest commit, so test that it adds the label data = { "action": "ready_for_review", "number": number, "pull_request": { "number": number, "url": pr_url, "body": CHECKBOX_TICKED, "head": { "sha": sha }, "labels": [], "user": { "login": user }, "author_association": "NONE", "comments_url": comments_url, "issue_url": issue_url, "html_url": html_pr_url, "requested_reviewers": [{ "login": "******" }, { "login": "******" }], "draft": False, }, "repository": { "full_name": repository }, "installation": { "id": MOCK_INSTALLATION_ID }, } event = sansio.Event(data, event="pull_request", delivery_id="1") getitem = { check_run_url: { "total_count": 2, "check_runs": [ { "status": "completed", "conclusion": "success", "name": "validate-solutions", }, { "status": "completed", "conclusion": "failure", "name": "pre-commit", }, ], }, } getiter = { files_url: {}, } post = {labels_url: {}} gh = MockGitHubAPI(getitem=getitem, getiter=getiter, post=post) await pull_requests.router.dispatch(event, gh) assert len(gh.getitem_url) == 1 assert check_run_url in gh.getitem_url assert len(gh.getiter_url) == 1 assert files_url in gh.getiter_url assert labels_url in gh.post_url assert {"labels": [Label.FAILED_TEST]} in gh.post_data assert gh.delete_url == []