Esempio n. 1
0
async def send_refresh(
    redis_cache: utils.RedisCache,
    redis_stream: utils.RedisStream,
    repository: github_types.GitHubRepository,
    pull_request_number: typing.Optional[
        github_types.GitHubPullRequestNumber] = None,
    ref: typing.Optional[github_types.GitHubRefType] = None,
    action: github_types.GitHubEventRefreshActionType = "user",
) -> None:
    data = github_types.GitHubEventRefresh({
        "action": action,
        "ref": ref,
        "repository": repository,
        "pull_request_number": pull_request_number,
        "sender": {
            "login": github_types.GitHubLogin("<internal>"),
            "id": github_types.GitHubAccountIdType(0),
            "type": "User",
            "avatar_url": "",
        },
        "organization": repository["owner"],
        "installation": {
            "id": github_types.GitHubInstallationIdType(0),
            "account": repository["owner"],
        },
    })
    await filter_and_dispatch(redis_cache, redis_stream, "refresh",
                              str(uuid.uuid4()), data)
Esempio n. 2
0
def fake_repository(
    redis_links: redis_utils.RedisLinks,
    fake_subscription: subscription.Subscription,
) -> context.Repository:
    gh_owner = github_types.GitHubAccount({
        "login":
        github_types.GitHubLogin("Mergifyio"),
        "id":
        github_types.GitHubAccountIdType(0),
        "type":
        "User",
        "avatar_url":
        "",
    })

    gh_repo = github_types.GitHubRepository({
        "full_name":
        "Mergifyio/mergify-engine",
        "name":
        github_types.GitHubRepositoryName("mergify-engine"),
        "private":
        False,
        "id":
        github_types.GitHubRepositoryIdType(0),
        "owner":
        gh_owner,
        "archived":
        False,
        "url":
        "",
        "html_url":
        "",
        "default_branch":
        github_types.GitHubRefType("main"),
    })
    installation_json = github_types.GitHubInstallation({
        "id":
        github_types.GitHubInstallationIdType(12345),
        "target_type":
        gh_owner["type"],
        "permissions": {},
        "account":
        gh_owner,
    })

    fake_client = mock.Mock()
    installation = context.Installation(installation_json, fake_subscription,
                                        fake_client, redis_links)
    return context.Repository(installation, gh_repo)
Esempio n. 3
0
async def _send_refresh(
    redis_stream: "redis_utils.RedisStream",
    repository: github_types.GitHubRepository,
    action: github_types.GitHubEventRefreshActionType,
    source: str,
    pull_request_number: typing.Optional[
        github_types.GitHubPullRequestNumber] = None,
    ref: typing.Optional[github_types.GitHubRefType] = None,
    score: typing.Optional[str] = None,
) -> None:
    # TODO(sileht): move refresh stuff into it's own file
    # Break circular import
    from mergify_engine import github_events
    from mergify_engine import worker

    data = github_types.GitHubEventRefresh({
        "action": action,
        "source": source,
        "ref": ref,
        "pull_request_number": pull_request_number,
        "repository": repository,
        "sender": {
            "login": github_types.GitHubLogin("<internal>"),
            "id": github_types.GitHubAccountIdType(0),
            "type": "User",
            "avatar_url": "",
        },
        "organization": repository["owner"],
        "installation": {
            "id": github_types.GitHubInstallationIdType(0),
            "account": repository["owner"],
            "target_type": repository["owner"]["type"],
            "permissions": {},
        },
    })

    slim_event = github_events._extract_slim_event("refresh", data)
    await worker.push(
        redis_stream,
        repository["owner"]["id"],
        repository["owner"]["login"],
        repository["id"],
        repository["name"],
        pull_request_number,
        "refresh",
        slim_event,
        None,
    )
Esempio n. 4
0
def fake_repository(
    redis_cache: utils.RedisCache,
    fake_subscription: subscription.Subscription,
) -> context.Repository:
    gh_owner = github_types.GitHubAccount(
        {
            "login": github_types.GitHubLogin("Mergifyio"),
            "id": github_types.GitHubAccountIdType(0),
            "type": "User",
            "avatar_url": "",
        }
    )

    gh_repo = github_types.GitHubRepository(
        {
            "full_name": "Mergifyio/mergify-engine",
            "name": github_types.GitHubRepositoryName("mergify-engine"),
            "private": False,
            "id": github_types.GitHubRepositoryIdType(0),
            "owner": gh_owner,
            "archived": False,
            "url": "",
            "html_url": "",
            "default_branch": github_types.GitHubRefType("main"),
        }
    )
    installation_json = github_types.GitHubInstallation(
        {
            "id": github_types.GitHubInstallationIdType(12345),
            "target_type": gh_owner["type"],
            "permissions": {},
            "account": gh_owner,
        }
    )

    fake_client = redis_queue = mock.Mock()
    # NOTE(Syffe): Since redis_queue is not used in fake_repository, we simply mock it,
    # otherwise a fixture is needed for it. This might change with future use of redis_queue.
    installation = context.Installation(
        installation_json, fake_subscription, fake_client, redis_cache, redis_queue
    )
    return context.Repository(installation, gh_repo)
Esempio n. 5
0
async def _do_test_event_to_pull_check_run(
        redis_cache: utils.RedisCache, filename: str,
        expected_pulls: typing.List[int]) -> None:
    with open(
            os.path.join(os.path.dirname(__file__), "events", filename),
            "r",
    ) as f:
        data = json.loads(f.read().replace("https://github.com",
                                           config.GITHUB_URL).replace(
                                               "https://api.github.com",
                                               config.GITHUB_REST_API_URL))

    gh_owner = github_types.GitHubAccount({
        "type":
        "User",
        "id":
        github_types.GitHubAccountIdType(12345),
        "login":
        github_types.GitHubLogin("CytopiaTeam"),
        "avatar_url":
        "",
    })
    installation_json = github_types.GitHubInstallation({
        "id":
        github_types.GitHubInstallationIdType(12345),
        "target_type":
        gh_owner["type"],
        "permissions": {},
        "account":
        gh_owner,
    })
    installation = context.Installation(installation_json, mock.Mock(),
                                        mock.Mock(), redis_cache, mock.Mock())
    pulls = await github_events.extract_pull_numbers_from_event(
        installation,
        "check_run",
        data,
        [],
    )
    assert pulls == expected_pulls
Esempio n. 6
0
async def _send_refresh(
    redis_cache: RedisCache,
    redis_stream: RedisStream,
    repository: github_types.GitHubRepository,
    action: github_types.GitHubEventRefreshActionType,
    source: str,
    pull_request_number: typing.Optional[
        github_types.GitHubPullRequestNumber] = None,
    ref: typing.Optional[github_types.GitHubRefType] = None,
    score: typing.Optional[str] = None,
) -> None:
    # Break circular import
    from mergify_engine import github_events

    data = github_types.GitHubEventRefresh({
        "action": action,
        "source": source,
        "ref": ref,
        "pull_request_number": pull_request_number,
        "repository": repository,
        "sender": {
            "login": github_types.GitHubLogin("<internal>"),
            "id": github_types.GitHubAccountIdType(0),
            "type": "User",
            "avatar_url": "",
        },
        "organization": repository["owner"],
        "installation": {
            "id": github_types.GitHubInstallationIdType(0),
            "account": repository["owner"],
            "target_type": repository["owner"]["type"],
            "permissions": {},
        },
    })

    await github_events.filter_and_dispatch(redis_cache, redis_stream,
                                            "refresh", str(uuid.uuid4()), data)
Esempio n. 7
0
async def test_team_permission_cache(redis_cache: utils.RedisCache) -> None:
    class FakeClient(github.AsyncGithubInstallationClient):
        called: int

        def __init__(self, owner: str, repo: str) -> None:
            super().__init__(auth=None)  # type: ignore[arg-type]
            self.owner = owner
            self.repo = repo
            self.called = 0

        async def get(self, url: str, *args: typing.Any, **kwargs: typing.Any) -> typing.Any:  # type: ignore[override]
            self.called += 1
            if (
                url
                == f"/orgs/{self.owner}/teams/team-ok/repos/{self.owner}/{self.repo}"
            ):
                return {}
            elif (
                url
                == f"/orgs/{self.owner}/teams/team-nok/repos/{self.owner}/{self.repo}"
            ):
                raise http.HTTPNotFound(
                    message="Not found", request=mock.ANY, response=mock.ANY
                )
            elif (
                url
                == f"/orgs/{self.owner}/teams/team-also-nok/repos/{self.owner}/{self.repo}"
            ):
                raise http.HTTPNotFound(
                    message="Not found", request=mock.ANY, response=mock.ANY
                )

            raise ValueError(f"Unknown test URL `{url}`")

    gh_owner = github_types.GitHubAccount(
        {
            "id": github_types.GitHubAccountIdType(123),
            "login": github_types.GitHubLogin("jd"),
            "type": "User",
            "avatar_url": "",
        }
    )

    gh_repo = github_types.GitHubRepository(
        {
            "id": github_types.GitHubRepositoryIdType(0),
            "owner": gh_owner,
            "full_name": "",
            "archived": False,
            "url": "",
            "html_url": "",
            "default_branch": github_types.GitHubRefType(""),
            "name": github_types.GitHubRepositoryName("test"),
            "private": False,
        }
    )
    installation_json = github_types.GitHubInstallation(
        {
            "id": github_types.GitHubInstallationIdType(12345),
            "target_type": gh_owner["type"],
            "permissions": {},
            "account": gh_owner,
        }
    )

    team_slug1 = github_types.GitHubTeamSlug("team-ok")
    team_slug2 = github_types.GitHubTeamSlug("team-nok")
    team_slug3 = github_types.GitHubTeamSlug("team-also-nok")

    sub = subscription.Subscription(
        redis_cache, 0, "", frozenset([subscription.Features.PUBLIC_REPOSITORY])
    )
    client = FakeClient(gh_owner["login"], gh_repo["name"])
    installation = context.Installation(
        installation_json, sub, client, redis_cache, mock.Mock()
    )
    repository = context.Repository(installation, gh_repo)
    assert client.called == 0
    assert await repository.team_has_read_permission(team_slug1)
    assert client.called == 1
    assert await repository.team_has_read_permission(team_slug1)
    assert client.called == 1
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 2
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 2
    assert not await repository.team_has_read_permission(team_slug3)
    assert client.called == 3

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

    client = FakeClient(gh_owner["login"], gh_repo["name"])
    installation = context.Installation(
        installation_json, sub, client, redis_cache, mock.Mock()
    )
    repository = context.Repository(installation, gh_repo)
    assert client.called == 0
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 1
    # From local cache
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 1
    # From redis
    repository._caches.team_has_read_permission.clear()
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 1
    assert await repository.team_has_read_permission(team_slug1)
    assert client.called == 2
    await context.Repository.clear_team_permission_cache_for_repo(
        redis_cache, gh_owner, gh_repo
    )
    repository._caches.team_has_read_permission.clear()
    assert await repository.team_has_read_permission(team_slug1)
    assert client.called == 3
    assert not await repository.team_has_read_permission(team_slug3)
    assert client.called == 4
    await context.Repository.clear_team_permission_cache_for_org(redis_cache, gh_owner)
    repository._caches.team_has_read_permission.clear()
    assert not await repository.team_has_read_permission(team_slug3)
    assert client.called == 5
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 6
    # From local cache
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 6
    # From redis
    repository._caches.team_has_read_permission.clear()
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 6
    repository._caches.team_has_read_permission.clear()
    await context.Repository.clear_team_permission_cache_for_team(
        redis_cache, gh_owner, team_slug2
    )
    repository._caches.team_has_read_permission.clear()
    assert not await repository.team_has_read_permission(team_slug2)
    assert client.called == 7
Esempio n. 8
0
async def test_user_permission_cache(redis_cache: utils.RedisCache) -> None:
    class FakeClient(github.AsyncGithubInstallationClient):
        called: int

        def __init__(self, owner: str, repo: str) -> None:
            super().__init__(auth=None)  # type: ignore[arg-type]
            self.owner = owner
            self.repo = repo
            self.called = 0

        async def item(self, url, *args, **kwargs):
            self.called += 1
            if self.repo == "test":
                if (
                    url
                    == f"/repos/{self.owner}/{self.repo}/collaborators/foo/permission"
                ):
                    return {"permission": "admin"}
                elif url.startswith(f"/repos/{self.owner}/{self.repo}/collaborators/"):
                    return {"permission": "loser"}
            elif self.repo == "test2":
                if (
                    url
                    == f"/repos/{self.owner}/{self.repo}/collaborators/bar/permission"
                ):
                    return {"permission": "admin"}
                elif url.startswith(f"/repos/{self.owner}/{self.repo}/collaborators/"):
                    return {"permission": "loser"}
            raise ValueError(f"Unknown test URL `{url}` for repo {self.repo}")

    gh_owner = github_types.GitHubAccount(
        {
            "id": github_types.GitHubAccountIdType(123),
            "login": github_types.GitHubLogin("jd"),
            "type": "User",
            "avatar_url": "",
        }
    )

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

    user_1 = github_types.GitHubAccount(
        {
            "id": github_types.GitHubAccountIdType(1),
            "login": github_types.GitHubLogin("foo"),
            "type": "User",
            "avatar_url": "",
        }
    )
    user_2 = github_types.GitHubAccount(
        {
            "id": github_types.GitHubAccountIdType(2),
            "login": github_types.GitHubLogin("bar"),
            "type": "User",
            "avatar_url": "",
        }
    )
    user_3 = github_types.GitHubAccount(
        {
            "id": github_types.GitHubAccountIdType(3),
            "login": github_types.GitHubLogin("baz"),
            "type": "User",
            "avatar_url": "",
        }
    )
    installation_json = github_types.GitHubInstallation(
        {
            "id": github_types.GitHubInstallationIdType(12345),
            "target_type": gh_owner["type"],
            "permissions": {},
            "account": gh_owner,
        }
    )

    sub = subscription.Subscription(
        redis_cache, 0, "", frozenset([subscription.Features.PUBLIC_REPOSITORY])
    )
    client = FakeClient(gh_owner["login"], gh_repo["name"])
    installation = context.Installation(
        installation_json, sub, client, redis_cache, mock.Mock()
    )
    repository = context.Repository(installation, gh_repo)
    assert client.called == 0
    assert await repository.has_write_permission(user_1)
    assert client.called == 1
    assert await repository.has_write_permission(user_1)
    assert client.called == 1
    assert not await repository.has_write_permission(user_2)
    assert client.called == 2
    # From local cache
    assert not await repository.has_write_permission(user_2)
    assert client.called == 2
    # From redis
    repository._caches.user_permissions.clear()
    assert not await repository.has_write_permission(user_2)
    assert client.called == 2
    assert not await repository.has_write_permission(user_3)
    assert client.called == 3

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

    client = FakeClient(gh_owner["login"], gh_repo["name"])
    installation = context.Installation(
        installation_json, sub, client, redis_cache, mock.Mock()
    )
    repository = context.Repository(installation, gh_repo)
    assert client.called == 0
    assert await repository.has_write_permission(user_2)
    assert client.called == 1
    # From local cache
    assert await repository.has_write_permission(user_2)
    assert client.called == 1
    # From redis
    repository._caches.user_permissions.clear()
    assert await repository.has_write_permission(user_2)
    assert client.called == 1

    assert not await repository.has_write_permission(user_1)
    assert client.called == 2
    await context.Repository.clear_user_permission_cache_for_repo(
        redis_cache, gh_owner, gh_repo
    )
    repository._caches.user_permissions.clear()
    assert not await repository.has_write_permission(user_1)
    assert client.called == 3
    assert not await repository.has_write_permission(user_3)
    assert client.called == 4
    await context.Repository.clear_user_permission_cache_for_org(redis_cache, gh_owner)
    repository._caches.user_permissions.clear()
    assert not await repository.has_write_permission(user_3)
    assert client.called == 5
    assert await repository.has_write_permission(user_2)
    assert client.called == 6
    # From local cache
    assert await repository.has_write_permission(user_2)
    assert client.called == 6
    # From redis
    repository._caches.user_permissions.clear()
    assert await repository.has_write_permission(user_2)
    assert client.called == 6
    await context.Repository.clear_user_permission_cache_for_user(
        redis_cache, gh_owner, gh_repo, user_2
    )
    repository._caches.user_permissions.clear()
    assert await repository.has_write_permission(user_2)
    assert client.called == 7
Esempio n. 9
0
async def test_team_members_cache(redis_cache: utils.RedisCache) -> None:
    class FakeClient(github.AsyncGithubInstallationClient):
        called: int

        def __init__(self, owner: str) -> None:
            super().__init__(auth=None)  # type: ignore[arg-type]
            self.owner = owner
            self.called = 0

        async def items(self, url, *args, **kwargs):
            self.called += 1
            if url == f"/orgs/{self.owner}/teams/team1/members":
                yield {"login": "******"}
                yield {"login": "******"}
            elif url == f"/orgs/{self.owner}/teams/team2/members":
                yield {"login": "******"}
                yield {"login": "******"}
            elif url == f"/orgs/{self.owner}/teams/team3/members":
                return
            else:
                raise ValueError(f"Unknown test URL `{url}` for repo {self.repo}")

    gh_owner = github_types.GitHubAccount(
        {
            "id": github_types.GitHubAccountIdType(123),
            "login": github_types.GitHubLogin("jd"),
            "type": "User",
            "avatar_url": "",
        }
    )
    installation_json = github_types.GitHubInstallation(
        {
            "id": github_types.GitHubInstallationIdType(12345),
            "target_type": gh_owner["type"],
            "permissions": {},
            "account": gh_owner,
        }
    )

    team_slug1 = github_types.GitHubTeamSlug("team1")
    team_slug2 = github_types.GitHubTeamSlug("team2")
    team_slug3 = github_types.GitHubTeamSlug("team3")

    sub = subscription.Subscription(
        redis_cache, 0, "", frozenset([subscription.Features.PUBLIC_REPOSITORY])
    )
    client = FakeClient(gh_owner["login"])
    installation = context.Installation(
        installation_json, sub, client, redis_cache, mock.Mock()
    )
    assert client.called == 0
    assert (await installation.get_team_members(team_slug1)) == ["member1", "member2"]
    assert client.called == 1
    assert (await installation.get_team_members(team_slug1)) == ["member1", "member2"]
    assert client.called == 1
    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 2
    # From local cache
    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 2
    # From redis
    installation._caches.team_members.clear()
    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 2

    assert (await installation.get_team_members(team_slug3)) == []
    assert client.called == 3
    # From local cache
    assert (await installation.get_team_members(team_slug3)) == []
    assert client.called == 3
    # From redis
    installation._caches.team_members.clear()
    assert (await installation.get_team_members(team_slug3)) == []
    assert client.called == 3

    await installation.clear_team_members_cache_for_team(
        redis_cache, gh_owner, github_types.GitHubTeamSlug(team_slug2)
    )
    installation._caches.team_members.clear()

    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 4
    # From local cache
    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 4
    # From redis
    installation._caches.team_members.clear()
    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 4

    await installation.clear_team_members_cache_for_org(redis_cache, gh_owner)
    installation._caches.team_members.clear()

    assert (await installation.get_team_members(team_slug1)) == ["member1", "member2"]
    assert client.called == 5
    # From local cache
    assert (await installation.get_team_members(team_slug1)) == ["member1", "member2"]
    assert client.called == 5
    # From redis
    installation._caches.team_members.clear()
    assert (await installation.get_team_members(team_slug1)) == ["member1", "member2"]
    assert client.called == 5

    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 6
    # From local cache
    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 6
    # From redis
    installation._caches.team_members.clear()
    assert (await installation.get_team_members(team_slug2)) == ["member3", "member4"]
    assert client.called == 6
    assert (await installation.get_team_members(team_slug3)) == []
    assert client.called == 7
    # From local cache
    assert (await installation.get_team_members(team_slug3)) == []
    assert client.called == 7
    # From redis
    installation._caches.team_members.clear()
    assert (await installation.get_team_members(team_slug3)) == []
    assert client.called == 7