chdsbd / kodiak

🔮 A bot to automatically update and merge GitHub PRs
https://kodiakhq.com
GNU Affero General Public License v3.0
1.03k stars 65 forks source link

fix(bot): parsing pr without author #828

Closed sbdchd closed 1 year ago

sbdchd commented 1 year ago

When a GitHub account is deleted, the account id on the pull request is nulled out, so we should handle that when parsing a PR.

We could probably ignore any PR without an author, but not sure.

Copy pasted one of the existing fixtures with a minor change.

Also had to update evaluation & the tests to account for pull_request.author now being nullable.

sbdchd commented 1 year ago

Ugh CI is broken:

======================================== FAILURES =========================================
______________________________ test_get_event_info_no_author ______________________________

api_client = <kodiak.queries.Client object at 0x103b48308>
mocker = <pytest_mock.plugin.MockerFixture object at 0x102b942c8>
block_event = EventInfoResponse(config=V1(version=1, app_id=None, merge=Merge(automerge_label='automerge', automerge_dependencies=Au...nclusion=<CheckConclusionState.SUCCESS: 'SUCCESS'>)], valid_merge_methods=[<MergeMethod.squash: 'squash'>], commits=[])
setup_redis = None, caplog = <_pytest.logging.LogCaptureFixture object at 0x103e1ec88>

    @requires_redis
    @pytest.mark.asyncio
    async def test_get_event_info_no_author(
        api_client: Client,
        mocker: MockFixture,
        block_event: EventInfoResponse,
        setup_redis: object,
        caplog: Any,
    ) -> None:
        """
        When a PR account author is deleted, the PR's author becomes null, so we
        need to handle that.
        """
        caplog.set_level(logging.WARNING)
        blocked_response = json.loads(
            (
                Path(__file__).parent
                / "test"
                / "fixtures"
                / "api"
                / "get_event"
                / "no_author.json"
            ).read_text()
        )
        block_event.pull_request.author = None
        mocker.patch.object(
            api_client,
            "send_query",
            return_value=wrap_future(
                GraphQLResponse(
                    data=blocked_response.get("data"), errors=blocked_response.get("errors")
                )
            ),
        )
>       res = await api_client.get_event_info(pr_number=100)

kodiak/test_queries.py:333: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
kodiak/queries/__init__.py:1031: in get_event_info
    await self.get_subscription() if conf.SUBSCRIPTIONS_ENABLED else None
kodiak/queries/__init__.py:1278: in get_subscription
    f"kodiak:subscription:{self.installation_id}".encode()
.venv/lib/python3.7/site-packages/asyncio_redis/protocol.py:733: in wrapper
    result = yield from method(protocol_self, _NoTransaction, *a, **kw)
.venv/lib/python3.7/site-packages/asyncio_redis/protocol.py:1231: in _query
    transaction, answer_f, _bypass=_bypass, call=call
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <asyncio_redis.protocol.RedisProtocol object at 0x103c40508>
transaction = <asyncio_redis.protocol._NoTransactionType object at 0x102bfe908>
answer_f = <Future pending>, _bypass = False
call = <asyncio_redis.protocol.PipelinedCall object at 0x103e050c8>

    @asyncio.coroutine
    def _get_answer(
        self, transaction, answer_f, _bypass=False, call=None
    ):  # XXX: rename _bypass to not_queued
        """
        Return an answer to the pipelined query.
        (Or when we are in a transaction, return a future for the answer.)
        """
        # Wait for the answer to come in
>       result = yield from answer_f
E       RuntimeError: Task <Task pending coro=<test_get_event_info_no_author() running at ~/projects/kodiak/bot/kodiak/test_queries.py:333> cb=[_run_until_complete_cb() at ~/.pyenv/versions/3.7.13/lib/python3.7/asyncio/base_events.py:157]> got Future <Future pending> attached to a different loop

.venv/lib/python3.7/site-packages/asyncio_redis/protocol.py:1155: RuntimeError
------------------------------------ Captured log call ------------------------------------
WARNING  kodiak.queries:__init__.py:906 owner='foo' repo='foo' install='8912353' event='problem parsing api features' exception='Traceback (most recent call last):\n  File "~/projects/kodiak/bot/kodiak/queries/__init__.py", line 904, in get_api_features\n    fields = data["__type"]["fields"]\nKeyError: \'__type\''
---------------------------------- Captured log teardown ----------------------------------
ERROR    asyncio:base_events.py:1619 Task was destroyed but it is pending!
task: <Task cancelling coro=<RedisProtocol._reader_coroutine() running at ~/projects/kodiak/bot/.venv/lib/python3.7/site-packages/asyncio_redis/protocol.py:1021> wait_for=<Future finished result=None>>
================================= short test summary info =================================
FAILED kodiak/test_queries.py::test_get_event_info_no_author - RuntimeError: Task <Task ...
============================== 1 failed, 17 passed in 0.43s ===============================
sbdchd commented 1 year ago

If I run one of the two async tests, it works:

❯ s/test kodiak/test_queries.py -k test_get_event_info_no_author
+ '[' '' ']'
+ ./.venv/bin/pytest kodiak/test_queries.py -k test_get_event_info_no_author
=================================== test session starts ===================================
platform darwin -- Python 3.7.13, pytest-6.0.1, py-1.10.0, pluggy-0.13.1
rootdir: /Users/steve/projects/kodiak/bot, configfile: tox.ini
plugins: cov-2.12.1, anyio-3.6.1, asyncio-0.12.0, kodiak-0.1.0, mock-3.3.1
collected 18 items / 17 deselected / 1 selected                                           

kodiak/test_queries.py .                                                            [100%]

============================ 1 passed, 17 deselected in 0.20s =============================
❯ s/test kodiak/test_queries.py -k test_get_event_info_blocked                       0.03s
+ '[' '' ']'
+ ./.venv/bin/pytest kodiak/test_queries.py -k test_get_event_info_blocked
=================================== test session starts ===================================
platform darwin -- Python 3.7.13, pytest-6.0.1, py-1.10.0, pluggy-0.13.1
rootdir: /Users/steve/projects/kodiak/bot, configfile: tox.ini
plugins: cov-2.12.1, anyio-3.6.1, asyncio-0.12.0, kodiak-0.1.0, mock-3.3.1
collected 18 items / 17 deselected / 1 selected                                           

kodiak/test_queries.py .                                                            [100%]

============================ 1 passed, 17 deselected in 0.25s =============================