diff --git a/homeassistant/components/github/config_flow.py b/homeassistant/components/github/config_flow.py index f0e27283355..9afbf80297c 100644 --- a/homeassistant/components/github/config_flow.py +++ b/homeassistant/components/github/config_flow.py @@ -10,7 +10,6 @@ from aiogithubapi import ( GitHubException, GitHubLoginDeviceModel, GitHubLoginOauthModel, - GitHubRepositoryModel, ) from aiogithubapi.const import OAUTH_USER_LOGIN import voluptuous as vol @@ -34,11 +33,12 @@ from .const import ( ) -async def starred_repositories(hass: HomeAssistant, access_token: str) -> list[str]: - """Return a list of repositories that the user has starred.""" +async def get_repositories(hass: HomeAssistant, access_token: str) -> list[str]: + """Return a list of repositories that the user owns or has starred.""" client = GitHubAPI(token=access_token, session=async_get_clientsession(hass)) + repositories = set() - async def _get_starred() -> list[GitHubRepositoryModel] | None: + async def _get_starred_repositories() -> None: response = await client.user.starred(**{"params": {"per_page": 100}}) if not response.is_last_page: results = await asyncio.gather( @@ -54,16 +54,44 @@ async def starred_repositories(hass: HomeAssistant, access_token: str) -> list[s for result in results: response.data.extend(result.data) - return response.data + repositories.update(response.data) + + async def _get_personal_repositories() -> None: + response = await client.user.repos(**{"params": {"per_page": 100}}) + if not response.is_last_page: + results = await asyncio.gather( + *( + client.user.repos( + **{"params": {"per_page": 100, "page": page_number}}, + ) + for page_number in range( + response.next_page_number, response.last_page_number + 1 + ) + ) + ) + for result in results: + response.data.extend(result.data) + + repositories.update(response.data) try: - result = await _get_starred() + await asyncio.gather( + *( + _get_starred_repositories(), + _get_personal_repositories(), + ) + ) + except GitHubException: return DEFAULT_REPOSITORIES - if not result or len(result) == 0: + if len(repositories) == 0: return DEFAULT_REPOSITORIES - return sorted((repo.full_name for repo in result), key=str.casefold) + + return sorted( + (repo.full_name for repo in repositories), + key=str.casefold, + ) class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): @@ -153,9 +181,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): assert self._login is not None if not user_input: - repositories = await starred_repositories( - self.hass, self._login.access_token - ) + repositories = await get_repositories(self.hass, self._login.access_token) return self.async_show_form( step_id="repositories", data_schema=vol.Schema( @@ -205,7 +231,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow): configured_repositories: list[str] = self.config_entry.options[ CONF_REPOSITORIES ] - repositories = await starred_repositories( + repositories = await get_repositories( self.hass, self.config_entry.data[CONF_ACCESS_TOKEN] ) diff --git a/homeassistant/components/github/manifest.json b/homeassistant/components/github/manifest.json index 474d08c4b0c..8d63b27117e 100644 --- a/homeassistant/components/github/manifest.json +++ b/homeassistant/components/github/manifest.json @@ -3,7 +3,7 @@ "name": "GitHub", "documentation": "https://www.home-assistant.io/integrations/github", "requirements": [ - "aiogithubapi==22.1.0" + "aiogithubapi==22.2.0" ], "codeowners": [ "@timmo001", diff --git a/requirements_all.txt b/requirements_all.txt index 4d5cd66a184..e4ed0d86319 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -175,7 +175,7 @@ aioflo==2021.11.0 aioftp==0.12.0 # homeassistant.components.github -aiogithubapi==22.1.0 +aiogithubapi==22.2.0 # homeassistant.components.guardian aioguardian==2021.11.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6932cdbcd47..cf75245b5db 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -125,7 +125,7 @@ aioesphomeapi==10.8.1 aioflo==2021.11.0 # homeassistant.components.github -aiogithubapi==22.1.0 +aiogithubapi==22.2.0 # homeassistant.components.guardian aioguardian==2021.11.0 diff --git a/tests/components/github/test_config_flow.py b/tests/components/github/test_config_flow.py index dad97472620..2bf0fac209f 100644 --- a/tests/components/github/test_config_flow.py +++ b/tests/components/github/test_config_flow.py @@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, MagicMock, patch from aiogithubapi import GitHubException from homeassistant import config_entries -from homeassistant.components.github.config_flow import starred_repositories +from homeassistant.components.github.config_flow import get_repositories from homeassistant.components.github.const import ( CONF_ACCESS_TOKEN, CONF_REPOSITORIES, @@ -161,11 +161,19 @@ async def test_starred_pagination_with_paginated_result(hass: HomeAssistant) -> last_page_number=2, data=[MagicMock(full_name="home-assistant/core")], ) - ) + ), + repos=AsyncMock( + return_value=MagicMock( + is_last_page=False, + next_page_number=2, + last_page_number=2, + data=[MagicMock(full_name="awesome/reposiotry")], + ) + ), ) ), ): - repos = await starred_repositories(hass, MOCK_ACCESS_TOKEN) + repos = await get_repositories(hass, MOCK_ACCESS_TOKEN) assert len(repos) == 2 assert repos[-1] == DEFAULT_REPOSITORIES[0] @@ -182,11 +190,17 @@ async def test_starred_pagination_with_no_starred(hass: HomeAssistant) -> None: is_last_page=True, data=[], ) - ) + ), + repos=AsyncMock( + return_value=MagicMock( + is_last_page=True, + data=[], + ) + ), ) ), ): - repos = await starred_repositories(hass, MOCK_ACCESS_TOKEN) + repos = await get_repositories(hass, MOCK_ACCESS_TOKEN) assert len(repos) == 2 assert repos == DEFAULT_REPOSITORIES @@ -200,7 +214,7 @@ async def test_starred_pagination_with_exception(hass: HomeAssistant) -> None: user=MagicMock(starred=AsyncMock(side_effect=GitHubException("Error"))) ), ): - repos = await starred_repositories(hass, MOCK_ACCESS_TOKEN) + repos = await get_repositories(hass, MOCK_ACCESS_TOKEN) assert len(repos) == 2 assert repos == DEFAULT_REPOSITORIES