Exemple #1
0
async def test_is_core_dev():
    teams = [{"name": "not Python core"}]
    gh = FakeGH(getiter={"https://api.github.com/orgs/python/teams": teams})
    with pytest.raises(ValueError):
        await util.is_core_dev(gh, "brett")

    teams = [{"name": "Python core", "id": 42}]
    getitem = {"https://api.github.com/teams/42/memberships/brett": True}
    gh = FakeGH(getiter={"https://api.github.com/orgs/python/teams": teams},
                getitem=getitem)
    assert await util.is_core_dev(gh, "brett")
    assert gh.getiter_url == "https://api.github.com/orgs/python/teams"

    teams = [{"name": "Python core", "id": 42}]
    getitem = {
        "https://api.github.com/teams/42/memberships/andrea":
        gidgethub.BadRequest(status_code=http.HTTPStatus(404))
    }
    gh = FakeGH(getiter={"https://api.github.com/orgs/python/teams": teams},
                getitem=getitem)
    assert not await util.is_core_dev(gh, "andrea")

    teams = [{"name": "Python core", "id": 42}]
    getitem = {
        "https://api.github.com/teams/42/memberships/andrea":
        gidgethub.BadRequest(status_code=http.HTTPStatus(400))
    }
    gh = FakeGH(getiter={"https://api.github.com/orgs/python/teams": teams},
                getitem=getitem)
    with pytest.raises(gidgethub.BadRequest):
        await util.is_core_dev(gh, "andrea")
Exemple #2
0
async def test_is_core_dev():
    teams = [{"name": "not Python core"}]
    gh = FakeGH(getiter={"/orgs/python/teams": teams})
    with pytest.raises(ValueError):
        await util.is_core_dev(gh, "mariatta")

    teams = [{"name": "python core", "id": 42}]
    getitem = {"/teams/42/memberships/mariatta": True}
    gh = FakeGH(getiter={"/orgs/python/teams": teams}, getitem=getitem)
    assert await util.is_core_dev(gh, "mariatta")
    assert gh.getiter_url == "/orgs/python/teams"

    teams = [{"name": "python core", "id": 42}]
    getitem = {
        "/teams/42/memberships/miss-islington":
        gidgethub.BadRequest(status_code=http.HTTPStatus(404))
    }
    gh = FakeGH(getiter={"/orgs/python/teams": teams}, getitem=getitem)
    assert not await util.is_core_dev(gh, "miss-islington")

    teams = [{"name": "python core", "id": 42}]
    getitem = {
        "/teams/42/memberships/miss-islington":
        gidgethub.BadRequest(status_code=http.HTTPStatus(400))
    }
    gh = FakeGH(getiter={"/orgs/python/teams": teams}, getitem=getitem)
    with pytest.raises(gidgethub.BadRequest):
        await util.is_core_dev(gh, "miss-islington")
Exemple #3
0
async def test_comment_on_pr_failure():
    issue_number = 100
    message = "Thanks for the PR!"
    gh = FakeGH(post=gidgethub.BadRequest(status_code=http.HTTPStatus(400)))

    with pytest.raises(gidgethub.BadRequest):
        await util.comment_on_pr(gh, issue_number, message)
Exemple #4
0
async def test_opened_pr():
    # New PR from a core dev.
    username = "******"
    issue_url = "https://api.github.com/issue/42"
    data = {
        "action": "opened",
        "pull_request": {
            "user": {
                "login": username,
            },
            "issue_url": issue_url,
        },
    }
    event = sansio.Event(data, event="pull_request", delivery_id="12345")
    teams = [{"name": "python core", "id": 6}]
    items = {
        f"https://api.github.com/teams/6/memberships/{username}": "OK",
        issue_url: {
            "labels": [],
            "labels_url": "https://api.github.com/labels"
        },
    }
    gh = FakeGH(getiter={"https://api.github.com/orgs/python/teams": teams},
                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"
    assert post_[1] == [awaiting.Blocker.core_review.value]

    # New PR from a non-core dev.
    username = "******"
    issue_url = "https://api.github.com/issue/42"
    data = {
        "action": "opened",
        "pull_request": {
            "user": {
                "login": username,
            },
            "issue_url": issue_url,
        },
    }
    event = sansio.Event(data, event="pull_request", 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)),
        issue_url: {
            "labels": [],
            "labels_url": "https://api.github.com/labels"
        },
    }
    gh = FakeGH(getiter={"https://api.github.com/orgs/python/teams": teams},
                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"
    assert post_[1] == [awaiting.Blocker.review.value]
Exemple #5
0
async def test_change_requested_for_non_core_dev():
    data = {
        "action": "submitted",
        "review": {
            "user": {
                "login": "******",
            },
            "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")
    teams = [{"name": "python core", "id": 6}]
    items = {
        f"https://api.github.com/teams/6/memberships/gvanrossum":
        True,
        "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",
        },
    }
    iterators = {
        "https://api.github.com/orgs/python/teams":
        teams,
        "https://api.github.com/pr/42/reviews": [{
            "user": {
                "login": "******"
            },
            "state": "changes_requested"
        }],
    }
    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"

    change_requested_message = awaiting.CHANGES_REQUESTED_MESSAGE.replace(
        "{easter_egg}", "").strip()
    assert change_requested_message in message[1]["body"]
Exemple #6
0
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_) == 2
    labeling, comment = 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

    # 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_) == 2
    labeling, comment = 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
Exemple #7
0
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_)
Exemple #8
0
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",
            "state": "open",
        },
    }
    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",
            "state": "open",
        },
    }
    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_
Exemple #9
0
 async def delete(self, url, url_vars={}):
     raise gidgethub.BadRequest(http.HTTPStatus.BAD_REQUEST, "oops")
Exemple #10
0
 async def delete(self, url, url_vars={}):
     raise gidgethub.BadRequest(http.HTTPStatus.BAD_REQUEST,
                                "Label does not exist")
async def test_ci_passed_approved_by_non_core_dev_review_pr_is_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": "******"
            }
        },
        "/teams/42/memberships/Mariatta":
        gidgethub.BadRequest(status_code=http.HTTPStatus(404))
    }

    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, 'put_data')  # is not merged