You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
3.3 KiB
84 lines
3.3 KiB
"""
|
|
GitHub source provider implementation
|
|
"""
|
|
import logging
|
|
from github import Github
|
|
from github.GithubException import GithubException
|
|
from typing import List, Dict, Optional
|
|
from ..base import SourceProvider, Repository, ProviderError, ConfigurationError
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class GitHubSourceProvider(SourceProvider):
|
|
"""GitHub source provider implementation"""
|
|
|
|
def _validate_config(self) -> None:
|
|
"""Validate GitHub-specific configuration"""
|
|
required_keys = ['token', 'username']
|
|
missing = [key for key in required_keys if not self.config.get(key)]
|
|
|
|
if missing:
|
|
raise ConfigurationError(f"Missing GitHub configuration: {', '.join(missing)}")
|
|
|
|
self.token = self.config['token']
|
|
self.username = self.config['username']
|
|
|
|
try:
|
|
self.github = Github(self.token)
|
|
self.user = self.github.get_user()
|
|
except GithubException as e:
|
|
raise ConfigurationError(f"Failed to authenticate with GitHub: {e}")
|
|
|
|
def get_user_repositories(self) -> List[Repository]:
|
|
"""Get repositories owned by the authenticated user"""
|
|
repositories = self.get_accessible_repositories()
|
|
return [repo for repo in repositories if repo.owner == self.username]
|
|
|
|
def get_accessible_repositories(self) -> List[Repository]:
|
|
"""Get all repositories accessible to the authenticated user"""
|
|
all_repos = []
|
|
|
|
try:
|
|
# Get user's own repositories
|
|
user_repos = self.user.get_repos()
|
|
all_repos.extend([self._parse_repository(repo) for repo in user_repos])
|
|
|
|
# Get repositories from organizations the user belongs to
|
|
for org in self.user.get_orgs():
|
|
try:
|
|
org_repos = org.get_repos()
|
|
all_repos.extend([self._parse_repository(repo) for repo in org_repos])
|
|
except GithubException as e:
|
|
logger.warning(f"Could not fetch repositories from organization {org.login}: {e}")
|
|
continue
|
|
|
|
except GithubException as e:
|
|
raise ProviderError(f"Failed to fetch repositories from GitHub: {e}")
|
|
|
|
return all_repos
|
|
|
|
def get_repository_info(self, owner: str, name: str) -> Optional[Repository]:
|
|
"""Get information about a specific repository"""
|
|
try:
|
|
repo = self.github.get_repo(f"{owner}/{name}")
|
|
return self._parse_repository(repo)
|
|
except GithubException:
|
|
return None
|
|
|
|
def get_authenticated_clone_url(self, repository: Repository) -> str:
|
|
"""Get authenticated clone URL for a repository"""
|
|
return f"https://{self.token}@github.com/{repository.owner}/{repository.name}.git"
|
|
|
|
def _parse_repository(self, repo) -> Repository:
|
|
"""Parse repository data from GitHub API response"""
|
|
return Repository(
|
|
name=repo.name,
|
|
owner=repo.owner.login,
|
|
description=repo.description or '',
|
|
private=repo.private,
|
|
clone_url=repo.clone_url,
|
|
ssh_url=repo.ssh_url,
|
|
web_url=repo.html_url,
|
|
default_branch=repo.default_branch or 'main'
|
|
) |