예제 #1
0
def test_active_feature():
    sub = subscription.Subscription(
        123,
        True,
        "friend",
        {},
        frozenset(),
    )
    assert sub.has_feature(subscription.Features.PRIORITY_QUEUES) is False
    sub = subscription.Subscription(
        123,
        False,
        "friend",
        {},
        frozenset([subscription.Features.PRIORITY_QUEUES]),
    )
    assert sub.has_feature(subscription.Features.PRIORITY_QUEUES) is False
    sub = subscription.Subscription(
        123,
        True,
        "friend",
        {},
        frozenset([subscription.Features.PRIORITY_QUEUES]),
    )
    assert sub.has_feature(subscription.Features.PRIORITY_QUEUES) is True
예제 #2
0
async def test_disabled(redis_cache):
    action = request_reviews.RequestReviewsAction.get_schema()(
        {
            "random_count": 2,
            "teams": {
                "foobar": 2,
                "foobaz": 1,
            },
            "users": {
                "jd": 2,
                "sileht": 1,
            },
        },
    )
    client = mock.MagicMock()
    client.auth.installation.__getitem__.return_value = 123
    sub = subscription.Subscription(
        redis_cache,
        123,
        False,
        "No sub",
        {},
        frozenset({}),
    )
    installation = context.Installation(123, "Mergifyio", sub, client, redis_cache)
    repository = context.Repository(installation, "demo")
    ctxt = await context.Context.create(
        repository,
        {
            "number": 123,
            "state": None,
            "mergeable_state": "ok",
            "merged_by": None,
            "merged": None,
            "merged_at": None,
            "base": {
                "sha": "sha",
                "ref": "main",
                "user": {
                    "login": {
                        "Mergifyio",
                    },
                },
                "repo": {
                    "name": "demo",
                    "private": False,
                    "owner": {
                        "login": "******",
                    },
                },
            },
        },
    )
    result = await action.run(ctxt, None)
    assert result.conclusion == check_api.Conclusion.ACTION_REQUIRED
    assert result.title == "Random request reviews are disabled"
    assert result.summary == (
        "⚠ The [subscription](https://dashboard.mergify.io/github/Mergifyio/subscription) "
        "needs to be updated to enable this feature."
    )
예제 #3
0
def test_queue_summary_subscription(active, summary):
    ctxt = mock.Mock(subscription=subscription.Subscription(
        123,
        active,
        "We're just testing",
        {},
        frozenset({subscription.Features.PRIORITY_QUEUES}),
    ))
    ctxt.missing_feature_reason = subscription.Subscription.missing_feature_reason
    ctxt.pull = {
        "base": {
            "repo": {
                "owner": {
                    "login": "******",
                },
            },
        },
    }
    q = mock.Mock(installation_id=12345)
    q.get_pulls.return_value = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    q.get_config.side_effect = gen_config(
        [4000, 3000, 3000, 3000, 2000, 2000, 1000, 1000, 1000])
    with mock.patch.object(merge.queue.Queue, "from_context", return_value=q):
        action = merge.MergeAction(
            voluptuous.Schema(merge.MergeAction.validator)({}))
        assert summary == action.get_queue_summary(ctxt, q)
예제 #4
0
async def test_save_sub(features):
    owner_id = 1234
    sub = subscription.Subscription(owner_id, True, "friend", {}, frozenset(features))

    await sub.save_subscription_to_cache()
    rsub = await subscription.Subscription._retrieve_subscription_from_cache(owner_id)
    assert rsub == sub
예제 #5
0
async def test_get_mergify_config_location_from_cache(
    redis_cache: utils.RedisCache, ) -> None:
    client = mock.AsyncMock()
    client.auth.owner = "foo"
    client.item.side_effect = [
        http.HTTPNotFound("Not Found",
                          request=mock.Mock(),
                          response=mock.Mock()),
        http.HTTPNotFound("Not Found",
                          request=mock.Mock(),
                          response=mock.Mock()),
        github_types.GitHubContentFile({
            "content":
            encodebytes("whatever".encode()).decode(),
            "type":
            "file",
            "path":
            ".github/mergify.yml",
            "sha":
            github_types.SHAType("zeazeaze"),
        }),
    ]

    installation = context.Installation(
        github_types.GitHubAccountIdType(0),
        github_types.GitHubLogin("foo"),
        subscription.Subscription(redis_cache, 0, False, "", frozenset()),
        client,
        redis_cache,
    )
    repository = context.Repository(installation,
                                    github_types.GitHubRepositoryName("bar"))

    await repository.get_mergify_config_file()
    assert client.item.call_count == 3
    client.item.assert_has_calls([
        mock.call("/repos/foo/bar/contents/.mergify.yml"),
        mock.call("/repos/foo/bar/contents/.mergify/config.yml"),
        mock.call("/repos/foo/bar/contents/.github/mergify.yml"),
    ])

    client.item.reset_mock()
    client.item.side_effect = [
        github_types.GitHubContentFile({
            "content":
            encodebytes("whatever".encode()).decode(),
            "type":
            "file",
            "path":
            ".github/mergify.yml",
            "sha":
            github_types.SHAType("zeazeaze"),
        }),
    ]
    repository._cache = context.RepositoryCache()
    await repository.get_mergify_config_file()
    assert client.item.call_count == 1
    client.item.assert_has_calls([
        mock.call("/repos/foo/bar/contents/.github/mergify.yml"),
    ])
예제 #6
0
async def test_get_mergify_config_invalid(
        invalid: str, redis_cache: utils.RedisCache) -> None:
    with pytest.raises(InvalidRules):

        async def item(*args, **kwargs):
            return github_types.GitHubContentFile({
                "content":
                encodebytes(invalid.encode()).decode(),
                "path":
                ".mergify.yml",
                "type":
                "file",
                "sha":
                "azertyu",
            })

        client = mock.Mock()
        client.item.return_value = item()
        installation = context.Installation(
            github_types.GitHubAccountIdType(0),
            github_types.GitHubLogin("foobar"),
            subscription.Subscription(redis_cache, 0, False, "", frozenset()),
            client,
            redis_cache,
        )
        repository = context.Repository(
            installation,
            github_types.GitHubRepositoryName("xyz"),
            github_types.GitHubRepositoryIdType(0),
        )

        config_file = await repository.get_mergify_config_file()
        assert config_file is not None
        get_mergify_config(config_file)
예제 #7
0
async def test_init(redis_cache):
    subscription.Subscription(
        redis_cache,
        123,
        True,
        "friend",
        frozenset({subscription.Features.PRIVATE_REPOSITORY}),
    )
예제 #8
0
async def prepare_context(client, redis_cache, subscribed=True):
    sub = subscription.Subscription(
        redis_cache,
        123,
        subscribed,
        "sub or not to sub",
        frozenset(
            getattr(subscription.Features, f)
            for f in subscription.Features.__members__)
        if subscribed else frozenset(),
    )
    installation = context.Installation(123, "Mergifyio", sub, client,
                                        redis_cache)
    repository = context.Repository(installation, "demo", 123)
    return await context.Context.create(
        repository,
        {
            "id": 12345,
            "number": 123,
            "state": None,
            "mergeable_state": "ok",
            "merged_by": None,
            "merged": None,
            "merged_at": None,
            "user": {
                "login": "******"
            },
            "requested_reviewers": [{
                "login": "******"
            }, {
                "login": "******"
            }],
            "requested_teams": [{
                "slug": "foobar"
            }, {
                "slug": "foobaz"
            }],
            "base": {
                "sha": "sha",
                "ref": "main",
                "user": {
                    "login": {
                        "Mergifyio",
                    },
                },
                "repo": {
                    "full_name": "Mergifyio/demo",
                    "name": "demo",
                    "private": False,
                    "owner": {
                        "login": "******",
                    },
                },
            },
        },
    )
예제 #9
0
 async def fake_retrieve_subscription_from_db(redis_cache, owner_id):
     if owner_id == config.TESTING_ORGANIZATION_ID:
         return self.subscription
     return subscription.Subscription(
         redis_cache,
         owner_id,
         False,
         "We're just testing",
         set(),
     )
예제 #10
0
 async def fake_subscription(redis_cache, owner_id):
     if owner_id == config.TESTING_ORGANIZATION_ID:
         return await real_get_subscription(redis_cache, owner_id)
     return subscription.Subscription(
         redis_cache,
         owner_id,
         False,
         "We're just testing",
         set(),
     )
예제 #11
0
async def _create_context(redis_cache, client):
    sub = subscription.Subscription(
        redis_cache,
        123,
        True,
        "",
        {},
        frozenset({}),
    )

    installation = context.Installation(123, "Mergifyio", sub, client,
                                        redis_cache)

    repository = context.Repository(installation, "demo", 123)

    return await context.Context.create(
        repository,
        {
            "number": 789,
            "state": "open",
            "title": "Amazing new feature",
            "user": {
                "login": "******",
                "id": 1,
            },
            "mergeable_state": "ok",
            "merged_by": None,
            "merged": None,
            "merged_at": None,
            "base": {
                "sha": "sha",
                "ref": "main",
                "user": {
                    "login": {
                        "Mergifyio",
                    },
                },
                "repo": {
                    "name": "demo",
                    "private": False,
                    "owner": {
                        "login": "******",
                        "id": 123,
                    },
                    "permissions": {
                        "admin": False,
                        "push": False,
                        "pull": True,
                    },
                },
            },
        },
        [],
    )
예제 #12
0
def test_dict():
    owner_id = 1234
    sub = subscription.Subscription(
        owner_id,
        True,
        "friend",
        {},
        frozenset({subscription.Features.PRIVATE_REPOSITORY}),
    )

    assert sub.from_dict(owner_id, sub.to_dict()) == sub
예제 #13
0
async def test_dict(redis_cache):
    owner_id = 1234
    sub = subscription.Subscription(
        redis_cache,
        owner_id,
        True,
        "friend",
        frozenset({subscription.Features.PRIVATE_REPOSITORY}),
    )

    assert sub.from_dict(redis_cache, owner_id, sub.to_dict(), -2) == sub
예제 #14
0
async def test_from_dict_unknown_features(redis_cache):
    assert (subscription.Subscription.from_dict(
        redis_cache,
        123,
        {
            "subscription_active": True,
            "subscription_reason": "friend",
            "features": ["unknown feature"],
        },
    ) == subscription.Subscription(redis_cache, 123, True, "friend",
                                   frozenset(), -2))
예제 #15
0
async def test_queue_summary(redis_cache):
    repository = mock.Mock(
        get_pull_request_context=mock.AsyncMock(
            return_value=mock.Mock(pull={"title": "foo"})
        )
    )
    ctxt = mock.Mock(
        repository=repository,
        subscription=subscription.Subscription(
            redis_cache,
            123,
            True,
            "We're just testing",
            frozenset({subscription.Features.PRIORITY_QUEUES}),
        ),
    )
    ctxt.missing_feature_reason = subscription.Subscription.missing_feature_reason
    ctxt.pull = {
        "base": {
            "repo": {
                "owner": {
                    "login": "******",
                },
            },
        },
    }
    q = mock.AsyncMock(installation_id=12345)
    q.get_pulls.return_value = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    q.get_config.side_effect = gen_config(
        [4000, 3000, 3000, 3000, 2000, 2000, 1000, 1000, 1000]
    )
    with mock.patch.object(merge.naive.Queue, "from_context", return_value=q):
        action = merge.MergeAction(voluptuous.Schema(merge.MergeAction.validator)({}))
        assert """**Required conditions for merge:**


**The following pull requests are queued:**
| | Pull request | Priority |
| ---: | :--- | :--- |
| 1 | foo #1 | 4000 |
| 2 | foo #2 | high |
| 3 | foo #3 | high |
| 4 | foo #4 | high |
| 5 | foo #5 | medium |
| 6 | foo #6 | medium |
| 7 | foo #7 | low |
| 8 | foo #8 | low |
| 9 | foo #9 | low |

---

""" + constants.MERGIFY_PULL_REQUEST_DOC == await action._get_queue_summary(
            ctxt, mock.Mock(missing_conditions=[], conditions=[]), q
        )
예제 #16
0
def repository(redis_cache, fake_client):
    installation = context.Installation(
        github_types.GitHubAccountIdType(123),
        github_types.GitHubLogin("user"),
        subscription.Subscription(redis_cache, 0, False, "", frozenset()),
        fake_client,
        redis_cache,
    )
    return context.Repository(
        installation,
        github_types.GitHubRepositoryName("name"),
        github_types.GitHubRepositoryIdType(123),
    )
예제 #17
0
async def test_active_feature(redis_cache):
    sub = subscription.Subscription(
        redis_cache,
        123,
        True,
        "friend",
        frozenset(),
    )
    assert sub.has_feature(subscription.Features.PRIORITY_QUEUES) is False
    sub = subscription.Subscription(
        redis_cache,
        123,
        False,
        "friend",
        frozenset([subscription.Features.PRIORITY_QUEUES]),
    )
    assert sub.has_feature(subscription.Features.PRIORITY_QUEUES) is False
    sub = subscription.Subscription(
        redis_cache,
        123,
        True,
        "friend",
        frozenset([subscription.Features.PRIORITY_QUEUES]),
    )
    assert sub.has_feature(subscription.Features.PRIORITY_QUEUES) is True

    sub = subscription.Subscription.from_dict(
        redis_cache,
        123,
        {
            "subscription_active": True,
            "subscription_reason": "friend",
            "features": ["private_repository", "large_repository"],
        },
    )
    assert sub.has_feature(subscription.Features.PRIVATE_REPOSITORY) is True
    assert sub.has_feature(subscription.Features.LARGE_REPOSITORY) is True
    assert sub.has_feature(subscription.Features.PRIORITY_QUEUES) is False
예제 #18
0
async def test_save_sub(features, redis_cache):
    owner_id = 1234
    sub = subscription.Subscription(
        redis_cache,
        owner_id,
        True,
        "friend",
        frozenset(features),
    )

    await sub._save_subscription_to_cache()
    rsub = await subscription.Subscription._retrieve_subscription_from_cache(
        redis_cache, owner_id)
    assert rsub == sub
예제 #19
0
def test_queue_summary_subscription(active, summary):
    ctxt = mock.Mock(subscription=subscription.Subscription(
        123,
        active,
        "We're just testing",
        {},
        frozenset({subscription.Features.PRIORITY_QUEUES}),
    ))
    q = mock.Mock(installation_id=12345)
    q.get_pulls.return_value = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    q.get_config.side_effect = gen_config(
        [4000, 3000, 3000, 3000, 2000, 2000, 1000, 1000, 1000])
    with mock.patch.object(helpers.queue.Queue, "from_context",
                           return_value=q):
        assert summary == helpers.get_queue_summary(ctxt)
예제 #20
0
async def test_subscription_db_unavailable(retrieve_subscription_from_db_mock,
                                           redis_cache):
    owner_id = 1234
    sub = subscription.Subscription(redis_cache, owner_id, True, "friend",
                                    frozenset())
    retrieve_subscription_from_db_mock.return_value = sub

    # no cache, no db -> reraise
    retrieve_subscription_from_db_mock.side_effect = http.HTTPServiceUnavailable(
        "boom!", response=mock.Mock(), request=mock.Mock())
    with pytest.raises(http.HTTPServiceUnavailable):
        await subscription.Subscription.get_subscription(redis_cache, owner_id)
        retrieve_subscription_from_db_mock.assert_called_once()

    # no cache, but db -> got db sub
    retrieve_subscription_from_db_mock.reset_mock()
    retrieve_subscription_from_db_mock.side_effect = None
    rsub = await subscription.Subscription.get_subscription(
        redis_cache, owner_id)
    assert sub == rsub
    retrieve_subscription_from_db_mock.assert_called_once()

    # cache not expired and not db -> got cached  sub
    retrieve_subscription_from_db_mock.reset_mock()
    rsub = await subscription.Subscription.get_subscription(
        redis_cache, owner_id)
    sub.ttl = 259200
    assert rsub == sub
    retrieve_subscription_from_db_mock.assert_not_called()

    # cache expired and not db -> got cached  sub
    retrieve_subscription_from_db_mock.reset_mock()
    retrieve_subscription_from_db_mock.side_effect = http.HTTPServiceUnavailable(
        "boom!", response=mock.Mock(), request=mock.Mock())
    await redis_cache.expire(f"subscription-cache-owner-{owner_id}", 7200)
    rsub = await subscription.Subscription.get_subscription(
        redis_cache, owner_id)
    sub.ttl = 7200
    assert rsub == sub
    retrieve_subscription_from_db_mock.assert_called_once()

    # cache expired and unexpected db issue -> reraise
    retrieve_subscription_from_db_mock.reset_mock()
    retrieve_subscription_from_db_mock.side_effect = Exception("WTF")
    await redis_cache.expire(f"subscription-cache-owner-{owner_id}", 7200)
    with pytest.raises(Exception):
        await subscription.Subscription.get_subscription(redis_cache, owner_id)
    retrieve_subscription_from_db_mock.assert_called_once()
예제 #21
0
def test_from_dict_unknown_features():
    assert subscription.Subscription.from_dict(
        123,
        {
            "subscription_active": True,
            "subscription_reason": "friend",
            "tokens": {},
            "features": ["unknown feature"],
        },
    ) == subscription.Subscription(
        123,
        True,
        "friend",
        {},
        frozenset(),
    )
예제 #22
0
    def test_checks_feature_disabled(self):
        self.subscription = subscription.Subscription(
            config.INSTALLATION_ID,
            self.SUBSCRIPTION_ACTIVE,
            "You're not nice",
            {"mergify-test1": config.ORG_ADMIN_GITHUB_APP_OAUTH_TOKEN},
            frozenset(
                getattr(subscription.Features, f)
                for f in subscription.Features.__members__
                if f is not subscription.Features.CUSTOM_CHECKS)
            if self.SUBSCRIPTION_ACTIVE else frozenset(),
        )
        loop = asyncio.get_event_loop()
        loop.run_until_complete(self.subscription.save_subscription_to_cache())

        rules = {
            "pull_request_rules": [{
                "name":
                "body need sentry ticket",
                "conditions": [
                    f"base={self.master_branch_name}",
                    "#title>10",
                    "#title<50",
                    "#body<4096",
                    "#files<100",
                    "body~=(?m)^(Fixes|Related|Closes) (MERGIFY-ENGINE|MRGFY)-",
                    "-label=ignore-guideline",
                ],
                "actions": {
                    "post_check": {}
                },
            }]
        }

        self.setup_repo(yaml.dump(rules))
        p, _ = self.create_pr()
        self.run_engine()
        p.update()

        ctxt = context.Context(self.cli_integration, p.raw_data, {})
        sorted_checks = list(
            sorted(ctxt.pull_engine_check_runs,
                   key=operator.itemgetter("name")))
        assert len(sorted_checks) == 2
        check = sorted_checks[0]
        assert "action_required" == check["conclusion"]
        assert "Custom checks are disabled" == check["output"]["title"]
예제 #23
0
    async def test_checks_feature_disabled(self):
        self.subscription = subscription.Subscription(
            utils.create_aredis_for_cache(max_idle_time=0),
            config.INSTALLATION_ID,
            self.SUBSCRIPTION_ACTIVE,
            "You're not nice",
            frozenset(
                getattr(subscription.Features, f)
                for f in subscription.Features.__members__
                if f is not subscription.Features.CUSTOM_CHECKS
            )
            if self.SUBSCRIPTION_ACTIVE
            else frozenset(),
        )
        await self.subscription.save_subscription_to_cache()

        rules = {
            "pull_request_rules": [
                {
                    "name": "body need sentry ticket",
                    "conditions": [
                        f"base={self.master_branch_name}",
                        "#title>10",
                        "#title<50",
                        "#body<4096",
                        "#files<100",
                        "body~=(?m)^(Fixes|Related|Closes) (MERGIFY-ENGINE|MRGFY)-",
                        "-label=ignore-guideline",
                    ],
                    "actions": {"post_check": {}},
                }
            ]
        }

        await self.setup_repo(yaml.dump(rules))
        p, _ = await self.create_pr()
        await self.run_engine()
        p = await self.get_pull(p["number"])

        ctxt = await context.Context.create(self.repository_ctxt, p, [])
        sorted_checks = sorted(
            await ctxt.pull_engine_check_runs, key=operator.itemgetter("name")
        )
        assert len(sorted_checks) == 2
        check = sorted_checks[0]
        assert "action_required" == check["conclusion"]
        assert "Custom checks are disabled" == check["output"]["title"]
def test_disabled():
    action = request_reviews.RequestReviewsAction.get_schema()(
        {
            "random_count": 2,
            "teams": {
                "foobar": 2,
                "foobaz": 1,
            },
            "users": {
                "jd": 2,
                "sileht": 1,
            },
        },
    )
    client = mock.MagicMock()
    client.auth.installation.__getitem__.return_value = 123
    sub = subscription.Subscription(
        123,
        False,
        "No sub",
        {},
        frozenset({}),
    )
    ctxt = context.Context(
        client,
        {
            "number": 123,
            "state": None,
            "mergeable_state": "ok",
            "merged_by": None,
            "merged": None,
            "merged_at": None,
        },
        sub,
    )
    assert action.run(ctxt, None, None) == (
        "action_required",
        "Random request reviews are disabled",
        "⚠  The [subscription](https://dashboard.mergify.io/installation/123/subscription) needed to be updated to enable them.",
    )
예제 #25
0
def repository(redis_cache, fake_client):
    gh_owner = github_types.GitHubAccount({
        "login":
        github_types.GitHubLogin("user"),
        "id":
        github_types.GitHubAccountIdType(0),
        "type":
        "User",
        "avatar_url":
        "",
    })

    gh_repo = github_types.GitHubRepository({
        "full_name":
        "user/name",
        "name":
        github_types.GitHubRepositoryName("name"),
        "private":
        False,
        "id":
        github_types.GitHubRepositoryIdType(0),
        "owner":
        gh_owner,
        "archived":
        False,
        "url":
        "",
        "html_url":
        "",
        "default_branch":
        github_types.GitHubRefType("ref"),
    })
    installation = context.Installation(
        github_types.GitHubAccountIdType(123),
        github_types.GitHubLogin("user"),
        subscription.Subscription(redis_cache, 0, False, "", frozenset()),
        fake_client,
        redis_cache,
    )
    return context.Repository(installation, gh_repo)
예제 #26
0
async def test_get_commits_to_cherry_pick_rebase(
    commits: mock.PropertyMock,
    redis_cache: utils.RedisCache,
) -> None:
    gh_owner = github_types.GitHubAccount({
        "login":
        github_types.GitHubLogin("user"),
        "id":
        github_types.GitHubAccountIdType(0),
        "type":
        "User",
        "avatar_url":
        "",
    })

    gh_repo = github_types.GitHubRepository({
        "full_name":
        "user/name",
        "name":
        github_types.GitHubRepositoryName("name"),
        "private":
        False,
        "id":
        github_types.GitHubRepositoryIdType(0),
        "owner":
        gh_owner,
        "archived":
        False,
        "url":
        "",
        "html_url":
        "",
        "default_branch":
        github_types.GitHubRefType("ref"),
    })

    c1 = github_types.GitHubBranchCommit({
        "sha": github_types.SHAType("c1f"),
        "parents": [],
        "commit": {
            "message": "foobar"
        },
    })
    c2 = github_types.GitHubBranchCommit({
        "sha": github_types.SHAType("c2"),
        "parents": [c1],
        "commit": {
            "message": "foobar"
        },
    })
    commits.return_value = [c1, c2]

    client = mock.Mock()
    client.auth.get_access_token.return_value = "<token>"
    client.items.side_effect = fake_get_github_pulls_from_sha

    installation = context.Installation(
        github_types.GitHubAccountIdType(123),
        github_types.GitHubLogin("user"),
        subscription.Subscription(redis_cache, 0, False, "", frozenset()),
        client,
        redis_cache,
    )
    repository = context.Repository(installation, gh_repo)
    ctxt = await context.Context.create(
        repository,
        {
            "labels": [],
            "draft": False,
            "merge_commit_sha": github_types.SHAType(""),
            "title": "",
            "commits": 1,
            "rebaseable": False,
            "maintainer_can_modify": False,
            "id": github_types.GitHubPullRequestId(0),
            "number": github_types.GitHubPullRequestNumber(6),
            "merged": True,
            "state": "closed",
            "html_url": "<html_url>",
            "changed_files": 1,
            "base": {
                "label": "",
                "sha": github_types.SHAType("sha"),
                "user": {
                    "login": github_types.GitHubLogin("user"),
                    "id": github_types.GitHubAccountIdType(0),
                    "type": "User",
                    "avatar_url": "",
                },
                "ref": github_types.GitHubRefType("ref"),
                "repo": {
                    "full_name": "user/ref",
                    "name": github_types.GitHubRepositoryName("name"),
                    "private": False,
                    "id": github_types.GitHubRepositoryIdType(0),
                    "owner": {
                        "login": github_types.GitHubLogin("user"),
                        "id": github_types.GitHubAccountIdType(0),
                        "type": "User",
                        "avatar_url": "",
                    },
                    "archived": False,
                    "url": "",
                    "html_url": "",
                    "default_branch": github_types.GitHubRefType(""),
                },
            },
            "head": {
                "label": "",
                "sha": github_types.SHAType("sha"),
                "ref": github_types.GitHubRefType("fork"),
                "user": {
                    "login": github_types.GitHubLogin("user"),
                    "id": github_types.GitHubAccountIdType(0),
                    "type": "User",
                    "avatar_url": "",
                },
                "repo": {
                    "full_name": "fork/other",
                    "name": github_types.GitHubRepositoryName("other"),
                    "private": False,
                    "archived": False,
                    "url": "",
                    "html_url": "",
                    "default_branch": github_types.GitHubRefType(""),
                    "id": github_types.GitHubRepositoryIdType(0),
                    "owner": {
                        "login": github_types.GitHubLogin("user"),
                        "id": github_types.GitHubAccountIdType(0),
                        "type": "User",
                        "avatar_url": "",
                    },
                },
            },
            "user": {
                "login": github_types.GitHubLogin("user"),
                "id": github_types.GitHubAccountIdType(0),
                "type": "User",
                "avatar_url": "",
            },
            "merged_by": None,
            "merged_at": None,
            "mergeable_state": "clean",
        },
    )

    base_branch = github_types.GitHubBranchCommitParent(
        {"sha": github_types.SHAType("base_branch")})
    rebased_c1 = github_types.GitHubBranchCommit({
        "sha":
        github_types.SHAType("rebased_c1"),
        "parents": [base_branch],
        "commit": {
            "message": "hello c1"
        },
    })
    rebased_c2 = github_types.GitHubBranchCommit({
        "sha":
        github_types.SHAType("rebased_c2"),
        "parents": [rebased_c1],
        "commit": {
            "message": "hello c2"
        },
    })

    async def fake_get_github_commit_from_sha(url, api_version=None):
        if url.endswith("/commits/rebased_c1"):
            return rebased_c1
        if url.endswith("/commits/rebased_c2"):
            return rebased_c2
        raise RuntimeError(f"Unknown URL {url}")

    client.item.side_effect = fake_get_github_commit_from_sha

    assert await duplicate_pull._get_commits_to_cherrypick(ctxt,
                                                           rebased_c2) == [
                                                               rebased_c1,
                                                               rebased_c2,
                                                           ]
예제 #27
0
async def test_get_commits_to_cherry_pick_merge(
    commits: mock.PropertyMock,
    redis_cache: utils.RedisCache,
) -> None:
    c1 = github_types.GitHubBranchCommit({
        "sha": github_types.SHAType("c1f"),
        "parents": [],
        "commit": {
            "message": "foobar"
        },
    })
    c2 = github_types.GitHubBranchCommit({
        "sha": github_types.SHAType("c2"),
        "parents": [c1],
        "commit": {
            "message": "foobar"
        },
    })

    async def fake_commits():
        return [c1, c2]

    commits.return_value = fake_commits()

    client = mock.Mock()
    client.auth.get_access_token.return_value = "<token>"

    gh_owner = github_types.GitHubAccount({
        "login":
        github_types.GitHubLogin("user"),
        "id":
        github_types.GitHubAccountIdType(0),
        "type":
        "User",
        "avatar_url":
        "",
    })
    gh_repo = github_types.GitHubRepository({
        "full_name":
        "user/name",
        "name":
        github_types.GitHubRepositoryName("name"),
        "private":
        False,
        "id":
        github_types.GitHubRepositoryIdType(0),
        "owner":
        gh_owner,
        "archived":
        False,
        "url":
        "",
        "html_url":
        "",
        "default_branch":
        github_types.GitHubRefType("ref"),
    })

    installation = context.Installation(
        github_types.GitHubAccountIdType(123),
        github_types.GitHubLogin("user"),
        subscription.Subscription(redis_cache, 0, False, "", frozenset()),
        client,
        redis_cache,
    )
    repository = context.Repository(installation, gh_repo)
    ctxt = await context.Context.create(
        repository,
        {
            "number": github_types.GitHubPullRequestNumber(6),
            "commits": 1,
            "merged": True,
            "state": "closed",
            "html_url": "<html_url>",
            "id": github_types.GitHubPullRequestId(0),
            "maintainer_can_modify": True,
            "labels": [],
            "rebaseable": True,
            "draft": True,
            "merge_commit_sha": None,
            "title": "foobar",
            "changed_files": 1,
            "base": {
                "label":
                "user:ref",
                "sha":
                github_types.SHAType("sha"),
                "ref":
                github_types.GitHubRefType("ref"),
                "user":
                gh_owner,
                "repo":
                github_types.GitHubRepository(
                    {
                        "full_name": "user/ref",
                        "name": github_types.GitHubRepositoryName("name"),
                        "private": False,
                        "id": github_types.GitHubRepositoryIdType(0),
                        "owner": gh_owner,
                        "archived": False,
                        "url": "",
                        "html_url": "",
                        "default_branch": github_types.GitHubRefType("ref"),
                    }),
            },
            "head": {
                "label":
                "user:ref",
                "sha":
                github_types.SHAType("sha"),
                "user":
                gh_owner,
                "ref":
                github_types.GitHubRefType("fork"),
                "repo":
                github_types.GitHubRepository(
                    {
                        "full_name": "fork/other",
                        "name": github_types.GitHubRepositoryName("name"),
                        "private": False,
                        "id": github_types.GitHubRepositoryIdType(0),
                        "owner": gh_owner,
                        "archived": False,
                        "url": "",
                        "html_url": "",
                        "default_branch": github_types.GitHubRefType("ref"),
                    }),
            },
            "user": gh_owner,
            "merged_at": None,
            "merged_by": None,
            "mergeable_state": "clean",
        },
    )

    base_branch = github_types.GitHubBranchCommit({
        "sha":
        github_types.SHAType("base_branch"),
        "parents": [],
        "commit": {
            "message": "foobar"
        },
    })
    merge_commit = github_types.GitHubBranchCommit({
        "sha":
        github_types.SHAType("merge_commit"),
        "parents": [base_branch, c2],
        "commit": {
            "message": "foobar"
        },
    })

    assert await duplicate_pull._get_commits_to_cherrypick(ctxt,
                                                           merge_commit) == [
                                                               c1,
                                                               c2,
                                                           ]
예제 #28
0
async def test_signals(redis_cache):
    gh_owner = github_types.GitHubAccount({
        "login":
        github_types.GitHubLogin("user"),
        "id":
        github_types.GitHubAccountIdType(0),
        "type":
        "User",
        "avatar_url":
        "",
    })

    gh_repo = github_types.GitHubRepository({
        "archived":
        False,
        "url":
        "",
        "default_branch":
        github_types.GitHubRefType(""),
        "id":
        github_types.GitHubRepositoryIdType(456),
        "full_name":
        "user/ref",
        "name":
        github_types.GitHubRepositoryName("name"),
        "private":
        False,
        "owner":
        gh_owner,
    })

    client = mock.AsyncMock()
    client.auth.get_access_token.return_value = "<token>"

    sub = subscription.Subscription(redis_cache, 0, False, "", frozenset())
    installation = context.Installation(
        gh_owner["id"],
        gh_owner["login"],
        sub,
        client,
        redis_cache,
    )
    repository = context.Repository(installation, gh_repo["name"],
                                    gh_repo["id"])
    ctxt = await context.Context.create(
        repository,
        {
            "title": "",
            "id": github_types.GitHubPullRequestId(0),
            "maintainer_can_modify": False,
            "rebaseable": False,
            "draft": False,
            "merge_commit_sha": None,
            "labels": [],
            "number": github_types.GitHubPullRequestNumber(6),
            "commits": 1,
            "merged": True,
            "state": "closed",
            "changed_files": 1,
            "html_url": "<html_url>",
            "base": {
                "label": "",
                "sha": github_types.SHAType("sha"),
                "user": {
                    "login": github_types.GitHubLogin("user"),
                    "id": github_types.GitHubAccountIdType(0),
                    "type": "User",
                    "avatar_url": "",
                },
                "ref": github_types.GitHubRefType("ref"),
                "label": "",
                "repo": gh_repo,
            },
            "head": {
                "label": "",
                "sha": github_types.SHAType("old-sha-one"),
                "ref": github_types.GitHubRefType("fork"),
                "user": {
                    "login": github_types.GitHubLogin("user"),
                    "id": github_types.GitHubAccountIdType(0),
                    "type": "User",
                    "avatar_url": "",
                },
                "repo": {
                    "archived": False,
                    "url": "",
                    "default_branch": github_types.GitHubRefType(""),
                    "id": github_types.GitHubRepositoryIdType(123),
                    "full_name": "fork/other",
                    "name": github_types.GitHubRepositoryName("other"),
                    "private": False,
                    "owner": {
                        "login": github_types.GitHubLogin("user"),
                        "id": github_types.GitHubAccountIdType(0),
                        "type": "User",
                        "avatar_url": "",
                    },
                },
            },
            "user": {
                "login": github_types.GitHubLogin("user"),
                "id": github_types.GitHubAccountIdType(0),
                "type": "User",
                "avatar_url": "",
            },
            "merged_by": None,
            "merged_at": None,
            "mergeable_state": "clean",
        },
    )

    assert len(signals.SIGNALS) == 0
    signals.setup()
    assert len(signals.SIGNALS) == 1

    with mock.patch(
            "mergify_engine_signals.noop.Signal.__call__") as signal_method:
        await signals.send(ctxt, "action.update")
        signal_method.assert_called_once_with(ctxt, "action.update")
예제 #29
0
    def setUp(self):
        super(FunctionalTestBase, self).setUp()
        self.existing_labels = []
        self.pr_counter = 0
        self.git_counter = 0
        self.cassette_library_dir = os.path.join(CASSETTE_LIBRARY_DIR_BASE,
                                                 self.__class__.__name__,
                                                 self._testMethodName)

        # Recording stuffs
        if RECORD:
            if os.path.exists(self.cassette_library_dir):
                shutil.rmtree(self.cassette_library_dir)
            os.makedirs(self.cassette_library_dir)

        self.recorder = vcr.VCR(
            cassette_library_dir=self.cassette_library_dir,
            record_mode="all" if RECORD else "none",
            match_on=["method", "uri"],
            filter_headers=[
                ("Authorization", "<TOKEN>"),
                ("X-Hub-Signature", "<SIGNATURE>"),
                ("User-Agent", None),
                ("Accept-Encoding", None),
                ("Connection", None),
            ],
            before_record_response=self.response_filter,
            custom_patches=((pygithub.MainClass, "HTTPSConnection",
                             vcr.stubs.VCRHTTPSConnection), ),
        )

        if RECORD:
            github.CachedToken.STORAGE = {}
        else:
            # Never expire token during replay
            mock.patch.object(github_app,
                              "get_or_create_jwt",
                              return_value="<TOKEN>").start()
            mock.patch.object(
                github.GithubAppInstallationAuth,
                "get_access_token",
                return_value="<TOKEN>",
            ).start()

            # NOTE(sileht): httpx pyvcr stubs does not replay auth_flow as it directly patch client.send()
            # So anything occurring during auth_flow have to be mocked during replay
            def get_auth(owner=None, auth=None):
                if auth is None:
                    auth = github.get_auth(owner)
                    auth.installation = {
                        "id": config.INSTALLATION_ID,
                    }
                    auth.permissions_need_to_be_updated = False
                    auth.owner_id = config.TESTING_ORGANIZATION_ID
                return auth

            async def github_aclient(owner=None, auth=None):
                return github.AsyncGithubInstallationClient(
                    get_auth(owner, auth))

            def github_client(owner=None, auth=None):
                return github.GithubInstallationClient(get_auth(owner, auth))

            mock.patch.object(github, "get_client", github_client).start()
            mock.patch.object(github, "aget_client", github_aclient).start()

        with open(engine.mergify_rule_path, "r") as f:
            engine.MERGIFY_RULE = yaml.safe_load(f.read().replace(
                "mergify[bot]", "mergify-test[bot]"))

        mock.patch.object(branch_updater.utils, "Gitter",
                          self.get_gitter).start()
        mock.patch.object(duplicate_pull.utils, "Gitter",
                          self.get_gitter).start()

        if not RECORD:
            # NOTE(sileht): Don't wait exponentialy during replay
            mock.patch.object(context.Context._ensure_complete.retry, "wait",
                              None).start()

        # Web authentification always pass
        mock.patch("hmac.compare_digest", return_value=True).start()

        branch_prefix_path = os.path.join(self.cassette_library_dir,
                                          "branch_prefix")

        if RECORD:
            self.BRANCH_PREFIX = datetime.datetime.utcnow().strftime(
                "%Y%m%d%H%M%S")
            with open(branch_prefix_path, "w") as f:
                f.write(self.BRANCH_PREFIX)
        else:
            with open(branch_prefix_path, "r") as f:
                self.BRANCH_PREFIX = f.read()

        self.master_branch_name = self.get_full_branch_name("master")

        self.git = self.get_gitter(LOG)
        self.addCleanup(self.git.cleanup)

        self.loop = asyncio.get_event_loop()
        self.loop.run_until_complete(web.startup())
        self.app = testclient.TestClient(web.app)

        # NOTE(sileht): Prepare a fresh redis
        self.redis_stream = redis.StrictRedis.from_url(config.STREAM_URL,
                                                       decode_responses=False)
        self.redis_stream.flushall()
        self.redis_cache = utils.get_redis_for_cache()
        self.redis_cache.flushall()
        self.subscription = subscription.Subscription(
            config.INSTALLATION_ID,
            self.SUBSCRIPTION_ACTIVE,
            "You're not nice",
            {
                "mergify-test1": config.ORG_ADMIN_GITHUB_APP_OAUTH_TOKEN,
                "mergify-test3": config.ORG_USER_PERSONAL_TOKEN,
            },
            frozenset(
                getattr(subscription.Features, f)
                for f in subscription.Features.__members__)
            if self.SUBSCRIPTION_ACTIVE else frozenset(),
        )
        self.loop.run_until_complete(
            self.subscription.save_subscription_to_cache())

        # Let's start recording
        cassette = self.recorder.use_cassette("http.json")
        cassette.__enter__()
        self.addCleanup(cassette.__exit__)

        integration = pygithub.GithubIntegration(config.INTEGRATION_ID,
                                                 config.PRIVATE_KEY)
        self.installation_token = integration.get_access_token(
            config.INSTALLATION_ID).token

        base_url = config.GITHUB_API_URL
        self.g_integration = pygithub.Github(self.installation_token,
                                             base_url=base_url)
        self.g_admin = pygithub.Github(config.ORG_ADMIN_PERSONAL_TOKEN,
                                       base_url=base_url)
        self.g_fork = pygithub.Github(self.FORK_PERSONAL_TOKEN,
                                      base_url=base_url)

        self.o_admin = self.g_admin.get_organization(
            config.TESTING_ORGANIZATION)
        self.o_integration = self.g_integration.get_organization(
            config.TESTING_ORGANIZATION)
        self.u_fork = self.g_fork.get_user()
        assert self.o_admin.login == "mergifyio-testing"
        assert self.o_integration.login == "mergifyio-testing"
        assert self.u_fork.login in ["mergify-test2", "mergify-test3"]

        self.r_o_admin = self.o_admin.get_repo(self.REPO_NAME)
        self.r_o_integration = self.o_integration.get_repo(self.REPO_NAME)
        self.r_fork = self.u_fork.get_repo(self.REPO_NAME)

        self.url_main = f"{config.GITHUB_URL}/{self.r_o_integration.full_name}"
        self.url_fork = (
            f"{config.GITHUB_URL}/{self.u_fork.login}/{self.r_o_integration.name}"
        )

        self.cli_integration = github.get_client(config.TESTING_ORGANIZATION, )

        real_get_subscription = subscription.Subscription.get_subscription

        async def fake_retrieve_subscription_from_db(owner_id):
            if owner_id == config.TESTING_ORGANIZATION_ID:
                return self.subscription
            return subscription.Subscription(
                owner_id,
                False,
                "We're just testing",
                {},
                set(),
            )

        async def fake_subscription(owner_id):
            if owner_id == config.TESTING_ORGANIZATION_ID:
                return await real_get_subscription(owner_id)
            return subscription.Subscription(
                owner_id,
                False,
                "We're just testing",
                {},
                set(),
            )

        mock.patch(
            "mergify_engine.subscription.Subscription._retrieve_subscription_from_db",
            side_effect=fake_retrieve_subscription_from_db,
        ).start()

        mock.patch(
            "mergify_engine.subscription.Subscription.get_subscription",
            side_effect=fake_subscription,
        ).start()

        mock.patch(
            "github.MainClass.Installation.Installation.get_repos",
            return_value=[self.r_o_integration],
        ).start()

        self._event_reader = EventReader(self.app)
        self._event_reader.drain()
        self.redis_stream.flushall()
예제 #30
0
    async def asyncSetUp(self):
        super(FunctionalTestBase, self).setUp()
        self.existing_labels: typing.List[str] = []
        self.protected_branches: typing.Set[str] = set()
        self.pr_counter: int = 0
        self.git_counter: int = 0
        self.cassette_library_dir = os.path.join(CASSETTE_LIBRARY_DIR_BASE,
                                                 self.__class__.__name__,
                                                 self._testMethodName)

        # Recording stuffs
        if RECORD:
            if os.path.exists(self.cassette_library_dir):
                shutil.rmtree(self.cassette_library_dir)
            os.makedirs(self.cassette_library_dir)

        self.recorder = vcr.VCR(
            cassette_library_dir=self.cassette_library_dir,
            record_mode="all" if RECORD else "none",
            match_on=["method", "uri"],
            ignore_localhost=True,
            filter_headers=[
                ("Authorization", "<TOKEN>"),
                ("X-Hub-Signature", "<SIGNATURE>"),
                ("User-Agent", None),
                ("Accept-Encoding", None),
                ("Connection", None),
            ],
            before_record_response=self.response_filter,
        )

        if RECORD:
            github.CachedToken.STORAGE = {}
        else:
            # Never expire token during replay
            mock.patch.object(github_app,
                              "get_or_create_jwt",
                              return_value="<TOKEN>").start()
            mock.patch.object(
                github.GithubAppInstallationAuth,
                "get_access_token",
                return_value="<TOKEN>",
            ).start()

            # NOTE(sileht): httpx pyvcr stubs does not replay auth_flow as it directly patch client.send()
            # So anything occurring during auth_flow have to be mocked during replay
            def get_auth(owner_name=None, owner_id=None, auth=None):
                if auth is None:
                    auth = github.get_auth(owner_name, owner_id)
                    auth.installation = {
                        "id": config.INSTALLATION_ID,
                    }
                    auth.permissions_need_to_be_updated = False
                    auth.owner_id = config.TESTING_ORGANIZATION_ID
                    auth.owner = config.TESTING_ORGANIZATION
                return auth

            def github_aclient(owner_name=None, owner_id=None, auth=None):
                return github.AsyncGithubInstallationClient(
                    get_auth(owner_name, owner_id, auth))

            mock.patch.object(github, "aget_client", github_aclient).start()

        mock.patch.object(branch_updater.gitter, "Gitter",
                          self.get_gitter).start()
        mock.patch.object(duplicate_pull.gitter, "Gitter",
                          self.get_gitter).start()

        if not RECORD:
            # NOTE(sileht): Don't wait exponentialy during replay
            mock.patch.object(context.Context._ensure_complete.retry, "wait",
                              None).start()

        # Web authentification always pass
        mock.patch("hmac.compare_digest", return_value=True).start()

        branch_prefix_path = os.path.join(self.cassette_library_dir,
                                          "branch_prefix")

        if RECORD:
            self.BRANCH_PREFIX = datetime.datetime.utcnow().strftime(
                "%Y%m%d%H%M%S")
            with open(branch_prefix_path, "w") as f:
                f.write(self.BRANCH_PREFIX)
        else:
            with open(branch_prefix_path, "r") as f:
                self.BRANCH_PREFIX = f.read()

        self.master_branch_name = self.get_full_branch_name("master")

        self.git = self.get_gitter(LOG)
        await self.git.init()
        self.addAsyncCleanup(self.git.cleanup)

        await root.startup()
        self.app = httpx.AsyncClient(app=root.app, base_url="http://localhost")

        await self.clear_redis_cache()
        self.redis_cache = utils.create_aredis_for_cache(max_idle_time=0)
        self.subscription = subscription.Subscription(
            self.redis_cache,
            config.TESTING_ORGANIZATION_ID,
            self.SUBSCRIPTION_ACTIVE,
            "You're not nice",
            frozenset(
                getattr(subscription.Features, f)
                for f in subscription.Features.__members__)
            if self.SUBSCRIPTION_ACTIVE else frozenset(),
        )
        await self.subscription._save_subscription_to_cache()
        self.user_tokens = user_tokens.UserTokens(
            self.redis_cache,
            config.TESTING_ORGANIZATION_ID,
            {
                "mergify-test1": config.ORG_ADMIN_GITHUB_APP_OAUTH_TOKEN,
                "mergify-test3": config.ORG_USER_PERSONAL_TOKEN,
            },
        )
        await self.user_tokens.save_to_cache()

        # Let's start recording
        cassette = self.recorder.use_cassette("http.json")
        cassette.__enter__()
        self.addCleanup(cassette.__exit__)

        self.client_integration = github.aget_client(
            config.TESTING_ORGANIZATION, config.TESTING_ORGANIZATION_ID)
        self.client_admin = github.AsyncGithubInstallationClient(
            auth=github.GithubTokenAuth(token=config.ORG_ADMIN_PERSONAL_TOKEN))
        self.client_fork = github.AsyncGithubInstallationClient(
            auth=github.GithubTokenAuth(token=self.FORK_PERSONAL_TOKEN))
        self.addAsyncCleanup(self.client_integration.aclose)
        self.addAsyncCleanup(self.client_admin.aclose)
        self.addAsyncCleanup(self.client_fork.aclose)

        await self.client_admin.item("/user")
        await self.client_fork.item("/user")
        if RECORD:
            assert self.client_admin.auth.owner == "mergify-test1"
            assert self.client_fork.auth.owner == "mergify-test2"
        else:
            self.client_admin.auth.owner = "mergify-test1"
            self.client_fork.auth.owner = "mergify-test2"

        self.url_main = f"/repos/mergifyio-testing/{self.REPO_NAME}"
        self.url_fork = f"/repos/{self.client_fork.auth.owner}/{self.REPO_NAME}"
        self.git_main = f"{config.GITHUB_URL}/mergifyio-testing/{self.REPO_NAME}"
        self.git_fork = (
            f"{config.GITHUB_URL}/{self.client_fork.auth.owner}/{self.REPO_NAME}"
        )

        self.installation_ctxt = context.Installation(
            config.TESTING_ORGANIZATION_ID,
            config.TESTING_ORGANIZATION,
            self.subscription,
            self.client_integration,
            self.redis_cache,
        )
        self.repository_ctxt = context.Repository(self.installation_ctxt,
                                                  self.REPO_NAME, self.REPO_ID)

        real_get_subscription = subscription.Subscription.get_subscription

        async def fake_retrieve_subscription_from_db(redis_cache, owner_id):
            if owner_id == config.TESTING_ORGANIZATION_ID:
                return self.subscription
            return subscription.Subscription(
                redis_cache,
                owner_id,
                False,
                "We're just testing",
                set(),
            )

        async def fake_subscription(redis_cache, owner_id):
            if owner_id == config.TESTING_ORGANIZATION_ID:
                return await real_get_subscription(redis_cache, owner_id)
            return subscription.Subscription(
                redis_cache,
                owner_id,
                False,
                "We're just testing",
                set(),
            )

        mock.patch(
            "mergify_engine.subscription.Subscription._retrieve_subscription_from_db",
            side_effect=fake_retrieve_subscription_from_db,
        ).start()

        mock.patch(
            "mergify_engine.subscription.Subscription.get_subscription",
            side_effect=fake_subscription,
        ).start()

        async def fake_retrieve_user_tokens_from_db(redis_cache, owner_id):
            if owner_id == config.TESTING_ORGANIZATION_ID:
                return self.user_tokens
            return user_tokens.UserTokens(redis_cache, owner_id, {})

        real_get_user_tokens = user_tokens.UserTokens.get

        async def fake_user_tokens(redis_cache, owner_id):
            if owner_id == config.TESTING_ORGANIZATION_ID:
                return await real_get_user_tokens(redis_cache, owner_id)
            return user_tokens.UserTokens(redis_cache, owner_id, {})

        mock.patch(
            "mergify_engine.user_tokens.UserTokens._retrieve_from_db",
            side_effect=fake_retrieve_user_tokens_from_db,
        ).start()

        mock.patch(
            "mergify_engine.user_tokens.UserTokens.get",
            side_effect=fake_user_tokens,
        ).start()

        self._event_reader = EventReader(self.app)
        await self._event_reader.drain()

        # NOTE(sileht): Prepare a fresh redis
        await self.clear_redis_stream()