async def test_application_tokens_via_env(monkeypatch, redis_cache): api_access_key1 = "1" * 32 api_secret_key1 = "1" * 32 account_id1 = github_types.GitHubAccountIdType(12345) account_login1 = github_types.GitHubLogin("login1") api_access_key2 = "2" * 32 api_secret_key2 = "2" * 32 account_id2 = github_types.GitHubAccountIdType(67891) account_login2 = github_types.GitHubLogin("login2") with pytest.raises(application.ApplicationUserNotFound): await application.ApplicationOnPremise.get( redis_cache, api_access_key1, api_secret_key1, None ) with pytest.raises(application.ApplicationUserNotFound): await application.ApplicationOnPremise.get( redis_cache, api_access_key2, api_secret_key2, None ) monkeypatch.setattr( config, "APPLICATION_APIKEYS", config.ApplicationAPIKeys( f"{api_access_key1}{api_secret_key1}:{account_id1}:{account_login1},{api_access_key2}{api_secret_key2}:{account_id2}:{account_login2}" ), ) app = await application.ApplicationOnPremise.get( redis_cache, api_access_key1, api_secret_key1, account_login1 ) assert app.account_scope["id"] == account_id1 app = await application.ApplicationOnPremise.get( redis_cache, api_access_key2, api_secret_key2, account_login2 ) assert app.account_scope["id"] == account_id2 app = await application.ApplicationOnPremise.get( redis_cache, api_access_key1, api_secret_key1, None ) assert app.account_scope["id"] == account_id1 app = await application.ApplicationOnPremise.get( redis_cache, api_access_key2, api_secret_key2, None ) assert app.account_scope["id"] == account_id2 # wrong scope with pytest.raises(application.ApplicationUserNotFound): await application.ApplicationOnPremise.get( redis_cache, api_access_key1, api_secret_key1, account_id2 ) with pytest.raises(application.ApplicationUserNotFound): await application.ApplicationOnPremise.get( redis_cache, api_access_key2, api_secret_key2, account_id1 )
async def _refresh( owner: github_types.GitHubLogin, repo: str, action: github_types.GitHubEventRefreshActionType = "user", ref: typing.Optional[github_types.GitHubRefType] = None, pull_request: typing.Optional[github_types.GitHubPullRequest] = None, ) -> responses.Response: data = github_types.GitHubEventRefresh({ "action": action, "organization": { "login": owner, "id": github_types.GitHubAccountIdType(0), "type": "Organization", }, "installation": { "id": 0, "account": { "login": owner, "id": github_types.GitHubAccountIdType(0), "type": "Organization", }, }, "repository": { "default_branch": github_types.GitHubRefType(""), "id": github_types.GitHubRepositoryIdType(0), "private": False, "archived": False, "url": "", "name": repo, "owner": { "login": owner, "id": github_types.GitHubAccountIdType(0), "type": "Organization", }, "full_name": f"{owner}/{repo}", }, "sender": { "login": github_types.GitHubLogin("<internal>"), "id": github_types.GitHubAccountIdType(0), "type": "User", }, "ref": ref, "pull_request": pull_request, }) await github_events.filter_and_dispatch(_AREDIS_STREAM, "refresh", str(uuid.uuid4()), data) return responses.Response("Refresh queued", status_code=202)
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"), ])
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)
async def test_client_installation_token_with_owner_id( httpserver: httpserver.HTTPServer, ) -> None: await _do_test_client_installation_token( httpserver, "/user/12345/installation", owner_id=github_types.GitHubAccountIdType(12345), )
async def test_get_already_merged_summary( merged_by: str, raw_config: str, result: str, context_getter: conftest.ContextGetterFixture, ) -> None: ctxt = await context_getter( github_types.GitHubPullRequestNumber(1), merged=True, merged_by=github_types.GitHubAccount({ "id": github_types.GitHubAccountIdType(1), "login": github_types.GitHubLogin(merged_by), "type": "User", "avatar_url": "", }), ) ctxt.repository._caches.branch_protections[github_types.GitHubRefType( "main")] = None file = context.MergifyConfigFile( type="file", content="whatever", sha=github_types.SHAType("azertyuiop"), path="whatever", decoded_content=raw_config, ) config = rules.get_mergify_config(file) match = await config["pull_request_rules"].get_pull_request_rule(ctxt) assert result == await actions_runner.get_already_merged_summary( ctxt, match)
async def test_save_apikey_scoped(redis_cache): api_access_key = "a" * 32 api_secret_key = "s" * 32 account_id = github_types.GitHubAccountIdType(12345) account_login = github_types.GitHubLogin("login") app = application.Application( redis_cache, 0, "app name", api_access_key, api_secret_key, {"id": account_id, "login": account_login}, ) await app.save_to_cache() rapp = await application.Application._retrieve_from_cache( redis_cache, api_access_key, api_secret_key, account_login ) assert app == rapp # wrong scope app = await application.Application._retrieve_from_cache( redis_cache, api_access_key, api_secret_key, github_types.GitHubLogin("another login"), ) assert app is None app = await application.Application._retrieve_from_cache( redis_cache, api_access_key, api_secret_key, None, ) assert app is None
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)
async def get( cls: typing.Type[ApplicationClassT], redis: redis_utils.RedisCache, api_access_key: str, api_secret_key: str, account_scope: typing.Optional[github_types.GitHubLogin], ) -> ApplicationClassT: data = config.APPLICATION_APIKEYS.get(api_access_key) if data is None or data["api_secret_key"] != api_secret_key: raise ApplicationUserNotFound() if account_scope is not None and account_scope != data["account_login"]: raise ApplicationUserNotFound() return cls( redis, 0, "on-premise-app", api_access_key, api_secret_key, ApplicationAccountScope({ "id": github_types.GitHubAccountIdType(data["account_id"]), "login": github_types.GitHubLogin(data["account_login"]), }), )
async def test_client_user_token(respx_mock: respx.MockRouter) -> None: respx_mock.get("/user/12345/installation").respond( 200, json={ "id": 12345, "target_type": "User", "permissions": { "checks": "write", "contents": "write", "pull_requests": "write", }, "account": { "login": "******", "id": 12345 }, }, ) respx_mock.get("/", headers__contains={ "Authorization": "token <user-token>" }).respond(200, json={"work": True}) installation_json = await github.get_installation_from_account_id( github_types.GitHubAccountIdType(12345)) async with github.AsyncGithubInstallationClient( github.GithubAppInstallationAuth(installation_json)) as client: ret = await client.get( "/", oauth_token=github_types.GitHubOAuthToken("<user-token>"), ) assert ret.json()["work"]
async def test_client_installation_HTTP_404( respx_mock: respx.MockRouter) -> None: respx_mock.get("/user/12345/installation").respond( 404, json={"message": "Repository not found"}) with pytest.raises(exceptions.MergifyNotInstalled): await github.get_installation_from_account_id( github_types.GitHubAccountIdType(12345))
def __init__(self) -> None: self.permissions_need_to_be_updated = False self.installation = { "id": config.ACTION_ID, } # TODO(sileht): To be defined when we handle subscription for GitHub Action self.owner = None self.owner_id = github_types.GitHubAccountIdType(0)
def _extract_owner( self, stream_name: StreamNameType ) -> typing.Tuple[github_types.GitHubLogin, github_types.GitHubAccountIdType]: stream_splitted = stream_name.split("~")[1:] return ( github_types.GitHubLogin(stream_splitted[0]), github_types.GitHubAccountIdType(int(stream_splitted[1])), )
def test_seats_renamed_account_repo() -> None: user1 = count_seats.SeatAccount( github_types.GitHubAccountIdType(123), github_types.GitHubLogin("user1"), ) user1bis = count_seats.SeatAccount( github_types.GitHubAccountIdType(123), github_types.GitHubLogin("user1bis"), ) user2 = count_seats.SeatAccount( github_types.GitHubAccountIdType(456), github_types.GitHubLogin("user2"), ) user2bis = count_seats.SeatAccount( github_types.GitHubAccountIdType(456), github_types.GitHubLogin("user2bis"), ) users = {user1, user2, user2bis, user1bis} assert len(users) == 2 assert list(users)[0].login == "user2" assert list(users)[1].login == "user1" repo1 = count_seats.SeatRepository( github_types.GitHubRepositoryIdType(123), github_types.GitHubRepositoryName("repo1"), ) repo1bis = count_seats.SeatRepository( github_types.GitHubRepositoryIdType(123), github_types.GitHubRepositoryName("repo1bis"), ) repo2 = count_seats.SeatRepository( github_types.GitHubRepositoryIdType(456), github_types.GitHubRepositoryName("repo2"), ) repo2bis = count_seats.SeatRepository( github_types.GitHubRepositoryIdType(456), github_types.GitHubRepositoryName("repo2bis"), ) repos = {repo1, repo2, repo2bis, repo1bis} assert repos == {repo1, repo2}
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)
async def test_client_installation_HTTP_301( respx_mock: respx.MockRouter) -> None: url_prefix = parse.urlparse(config.GITHUB_REST_API_URL).path respx_mock.get("/user/12345/installation").respond( 301, headers={"Location": f"{url_prefix}/repositories/12345/installation"}, ) respx_mock.get("/repositories/12345/installation").respond( 404, json={"message": "Repository not found"}) with pytest.raises(exceptions.MergifyNotInstalled): await github.get_installation_from_account_id( github_types.GitHubAccountIdType(12345))
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), )
async def test_update_apikey(redis_cache): api_access_key = "a" * 32 api_secret_key = "s" * 32 account_id = github_types.GitHubAccountIdType(12345) account_login = github_types.GitHubLogin("login") app = application.Application( redis_cache, 0, "app name", api_access_key, api_secret_key, {"id": account_id, "login": account_login}, ) await app.save_to_cache() rapp = await application.Application._retrieve_from_cache( redis_cache, api_access_key, api_secret_key, account_login ) assert app == rapp await application.Application.update( redis_cache, api_access_key, application.ApplicationDashboardJSON( { "id": 1, "name": "new name", "github_account": { "id": 424242, "login": "******", "type": "User", "avatar_url": "", }, } ), ) rapp = await application.Application._retrieve_from_cache( redis_cache, api_access_key, api_secret_key, account_login ) expected_app = application.Application( redis_cache, 1, "new name", api_access_key, api_secret_key, {"id": 424242, "login": "******"}, ttl=application.Application.RETENTION_SECONDS, ) assert expected_app == rapp
async def send( redis_stream: utils.RedisStream, redis_cache: utils.RedisCache, ) -> None: score = date.utcnow().timestamp() keys = await redis_cache.zrangebyscore(DELAYED_REFRESH_KEY, "-inf", score) if not keys: return pipe = await redis_stream.pipeline() keys_to_delete = set() for subkey in keys: ( owner_id_str, owner_login, repository_id_str, repository_name, pull_request_number_str, ) = subkey.split("~") owner_id = github_types.GitHubAccountIdType(int(owner_id_str)) repository_id = github_types.GitHubRepositoryIdType( int(repository_id_str)) pull_request_number = github_types.GitHubPullRequestNumber( int(pull_request_number_str)) LOG.info( "sending delayed pull request refresh", gh_owner=owner_login, gh_repo=repository_name, action="internal", source="delayed-refresh", ) await worker.push( pipe, owner_id, owner_login, repository_id, repository_name, pull_request_number, "refresh", { "action": "internal", "ref": None, "source": "delayed-refresh", }, # type: ignore[typeddict-item] ) keys_to_delete.add(subkey) await pipe.execute() await redis_cache.zrem(DELAYED_REFRESH_KEY, *keys_to_delete)
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)
async def send_refresh( pull: github_types.GitHubPullRequest, action: github_types.GitHubEventRefreshActionType = "user", ) -> None: data = github_types.GitHubEventRefresh({ "action": action, "ref": None, "repository": pull["base"]["repo"], "pull_request": pull, "ref": None, "sender": { "login": github_types.GitHubLogin("<internal>"), "id": github_types.GitHubAccountIdType(0), "type": "User", }, "organization": pull["base"]["repo"]["owner"], "installation": { "id": 0, "account": { "login": github_types.GitHubLogin(""), "id": github_types.GitHubAccountIdType(0), "type": "User", }, }, }) redis = await utils.create_aredis_for_stream() try: await filter_and_dispatch(redis, "refresh", str(uuid.uuid4()), data) finally: redis.connection_pool.disconnect()
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, )
async def test_client_401_raise_ratelimit( respx_mock: respx.MockRouter) -> None: owner_id = github_types.GitHubAccountIdType(12345) owner_login = github_types.GitHubLogin("owner") repo = "repo" respx_mock.get("/user/12345/installation").respond( 200, json={ "id": 12345, "target_type": "User", "permissions": { "checks": "write", "contents": "write", "pull_requests": "write", }, "account": { "login": "******", "id": 12345 }, }, ) respx_mock.post("/app/installations/12345/access_tokens").respond( 200, json={ "token": "<token>", "expires_at": "2100-12-31T23:59:59Z" }, headers={ "X-RateLimit-Remaining": "5000", "X-RateLimit-Reset": "1234567890", }, ) respx_mock.get("/repos/owner/repo/pull/1").respond( 403, json={"message": "quota !"}, headers={ "X-RateLimit-Remaining": "0", "X-RateLimit-Reset": "1234567890" }, ) installation_json = await github.get_installation_from_account_id(owner_id) async with github.aget_client(installation_json) as client: with pytest.raises(exceptions.RateLimited): await client.item(f"/repos/{owner_login}/{repo}/pull/1")
async def test_run_command_with_user( user_id: int, permission: str, comment: str, result: typing.Optional[str], context_getter: conftest.ContextGetterFixture, ) -> None: user = github_types.GitHubAccount( { "id": github_types.GitHubAccountIdType(user_id), "login": github_types.GitHubLogin("wall-e"), "type": "Bot", "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=4", }, ) client = mock.Mock() client.item = mock.AsyncMock() client.item.return_value = { "permission": permission, "user": user, } client.post = mock.AsyncMock() ctxt = await context_getter(github_types.GitHubPullRequestNumber(1)) ctxt.repository.installation.client = client await commands_runner.handle( ctxt=ctxt, mergify_config=EMPTY_CONFIG, comment="unrelated", user=None, rerun=True, ) assert len(client.post.call_args_list) == 0 await commands_runner.handle( ctxt=ctxt, mergify_config=EMPTY_CONFIG, comment=comment, user=user, ) if result is None: assert len(client.post.call_args_list) == 0 else: assert len(client.post.call_args_list) == 1 assert result in client.post.call_args_list[0][1]["json"]["body"]
async def get(cls: typing.Type[UserTokensT], redis: utils.RedisCache, owner_id: int) -> UserTokensT: return cls( redis, owner_id, [{ "id": github_types.GitHubAccountIdType(_id), "login": github_types.GitHubLogin(login), "oauth_access_token": github_types.GitHubOAuthToken(oauth_access_token), "email": None, "name": None, } for _id, login, oauth_access_token in config.ACCOUNT_TOKENS], )
async def test_client_installation_HTTP_500( respx_mock: respx.MockRouter) -> None: respx_mock.get("/user/12345/installation").mock(side_effect=[ httpx.Response(500, text="This is a 5XX error"), httpx.Response(500, text="This is a 5XX error"), httpx.Response(500, text="This is a 5XX error"), httpx.Response(500, text="This is a 5XX error"), httpx.Response(500, text="This is a 5XX error"), ]) with pytest.raises(http.HTTPServerSideError) as exc_info: await github.get_installation_from_account_id( github_types.GitHubAccountIdType(12345)) assert exc_info.value.message == "This is a 5XX error" assert exc_info.value.status_code == 500 assert exc_info.value.response.status_code == 500 assert (str(exc_info.value.request.url) == f"{config.GITHUB_REST_API_URL}/user/12345/installation")
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)
async def test_client_installation_token_with_owner_id( respx_mock: respx.MockRouter, ) -> None: respx_mock.get("/user/12345/installation").respond( 200, json={ "id": 12345, "target_type": "User", "permissions": { "checks": "write", "contents": "write", "pull_requests": "write", }, "account": { "login": "******", "id": 12345 }, }, ) respx_mock.post("/app/installations/12345/access_tokens").respond( 200, json={ "token": "<installation-token>", "expires_at": "2100-12-31T23:59:59Z" }, ) respx_mock.get("/", headers__contains={ "Authorization": "token <installation-token>" }).respond(200, json={"work": True}) installation_json = await github.get_installation_from_account_id( github_types.GitHubAccountIdType(12345)) async with github.AsyncGithubInstallationClient( github.GithubAppInstallationAuth(installation_json)) as client: ret = await client.get("/") assert ret.json()["work"] assert isinstance(client.auth, github.GithubAppInstallationAuth) assert client.auth._installation is not None assert client.auth._installation["account"]["login"] == "testing" assert client.auth._installation["account"]["id"] == 12345
async def test_client_abuse_403_no_header( respx_mock: respx.MockRouter) -> None: abuse_message = ("You have triggered an abuse detection mechanism. " "Please wait a few minutes before you try again.") respx_mock.get("/user/12345/installation").respond( 200, json={ "id": 12345, "target_type": "User", "permissions": { "checks": "write", "contents": "write", "pull_requests": "write", }, "account": { "login": "******", "id": 12345 }, }, ) respx_mock.post("/app/installations/12345/access_tokens").respond( 200, json={ "token": "<token>", "expires_at": "2100-12-31T23:59:59Z" }) respx_mock.get("/").respond( 403, json={"message": abuse_message}, ) installation_json = await github.get_installation_from_account_id( github_types.GitHubAccountIdType(12345)) async with github.AsyncGithubInstallationClient( github.GithubAppInstallationAuth(installation_json)) as client: with pytest.raises(http.HTTPClientSideError) as exc_info: await client.get("/") assert exc_info.value.message == abuse_message assert exc_info.value.status_code == 403 assert exc_info.value.response.status_code == 403 assert str(exc_info.value.request.url) == f"{config.GITHUB_REST_API_URL}/"
async def test_init(redis_cache): application.Application( redis_cache, 0, "app name", "api_access_key", "api_secret_key", { "id": github_types.GitHubAccountIdType(12345), "login": github_types.GitHubLogin("login"), }, ) application.Application( redis_cache, 0, "app name", "api_access_key", "api_secret_key", None, )