fix(backend): repository search is not working in the production environment (#11386)

This commit is contained in:
Hiep Le
2025-10-15 23:24:27 +07:00
committed by GitHub
parent 72179f45d3
commit 58d67a2480
8 changed files with 86 additions and 14 deletions

View File

@@ -13,7 +13,13 @@ class BitBucketReposMixin(BitBucketMixinBase):
"""
async def search_repositories(
self, query: str, per_page: int, sort: str, order: str, public: bool
self,
query: str,
per_page: int,
sort: str,
order: str,
public: bool,
app_mode: AppMode,
) -> list[Repository]:
"""Search for repositories."""
repositories = []

View File

@@ -161,6 +161,29 @@ class GitHubReposMixin(GitHubMixinBase):
logger.warning(f'Failed to get user organizations: {e}')
return []
async def get_organizations_from_installations(self) -> list[str]:
"""Get list of organization logins from GitHub App installations.
This method provides a more reliable way to get organizations that the
GitHub App has access to, regardless of user membership context.
"""
try:
# Get installations with account details
url = f'{self.BASE_URL}/user/installations'
response, _ = await self._make_request(url)
installations = response.get('installations', [])
orgs = []
for installation in installations:
account = installation.get('account', {})
if account.get('type') == 'Organization':
orgs.append(account.get('login'))
return orgs
except Exception as e:
logger.warning(f'Failed to get organizations from installations: {e}')
return []
def _fuzzy_match_org_name(self, query: str, org_name: str) -> bool:
"""Check if query fuzzy matches organization name."""
query_lower = query.lower().replace('-', '').replace('_', '').replace(' ', '')
@@ -181,7 +204,13 @@ class GitHubReposMixin(GitHubMixinBase):
return False
async def search_repositories(
self, query: str, per_page: int, sort: str, order: str, public: bool
self,
query: str,
per_page: int,
sort: str,
order: str,
public: bool,
app_mode: AppMode,
) -> list[Repository]:
url = f'{self.BASE_URL}/search/repositories'
params = {
@@ -206,9 +235,12 @@ class GitHubReposMixin(GitHubMixinBase):
query_with_user = f'org:{org} in:name {repo_query}'
params['q'] = query_with_user
elif not public:
# Expand search scope to include user's repositories and organizations they're a member of
# Expand search scope to include user's repositories and organizations the app has access to
user = await self.get_user()
user_orgs = await self.get_user_organizations()
if app_mode == AppMode.SAAS:
user_orgs = await self.get_organizations_from_installations()
else:
user_orgs = await self.get_user_organizations()
# Search in user repos and org repos separately
all_repos = []

View File

@@ -75,6 +75,7 @@ class GitLabReposMixin(GitLabMixinBase):
sort: str = 'updated',
order: str = 'desc',
public: bool = False,
app_mode: AppMode = AppMode.OSS,
) -> list[Repository]:
if public:
# When public=True, query is a GitLab URL that we need to parse

View File

@@ -294,12 +294,13 @@ class ProviderHandler:
per_page: int,
sort: str,
order: str,
app_mode: AppMode,
) -> list[Repository]:
if selected_provider:
service = self.get_service(selected_provider)
public = self._is_repository_url(query, selected_provider)
user_repos = await service.search_repositories(
query, per_page, sort, order, public
query, per_page, sort, order, public, app_mode
)
return self._deduplicate_repositories(user_repos)
@@ -309,7 +310,7 @@ class ProviderHandler:
service = self.get_service(provider)
public = self._is_repository_url(query, provider)
service_repos = await service.search_repositories(
query, per_page, sort, order, public
query, per_page, sort, order, public, app_mode
)
all_repos.extend(service_repos)
except Exception as e:

View File

@@ -458,7 +458,13 @@ class GitService(Protocol):
...
async def search_repositories(
self, query: str, per_page: int, sort: str, order: str, public: bool
self,
query: str,
per_page: int,
sort: str,
order: str,
public: bool,
app_mode: AppMode,
) -> list[Repository]:
"""Search for public repositories"""
...

View File

@@ -148,7 +148,7 @@ async def search_repositories(
)
try:
repos: list[Repository] = await client.search_repositories(
selected_provider, query, per_page, sort, order
selected_provider, query, per_page, sort, order, server_config.app_mode
)
return repos