class GitHubRepository: """Wrapper around GitHub API. Used to access public data.""" def __init__(self, owner, repo_name, token=""): """Build the GitHub API URL which points to the definition of the repository. Args: owner (str): the owner's GitHub username repo_name (str): the name of the repository token (str): the GitHub API token Returns: dict: a representation of the repo definition """ self._github_repository = GitHub(token=token).repository( owner, repo_name) @property def definition(self): """Fetch the definition of the repository, exposed by the GitHub API. Returns: dict: a representation of the repo definition """ return self._github_repository.as_dict() @retry_async_decorator(retry_exceptions=GitHubException) async def get_commit(self, commit_hash): """Fetch the definition of the commit, exposed by the GitHub API. Args: commit_hash (str): the hash of the git commit Returns: dict: a representation of the commit """ return self._github_repository.commit(commit_hash).as_dict() @retry_async_decorator(retry_exceptions=GitHubException) async def get_pull_request(self, pull_request_number): """Fetch the definition of the pull request, exposed by the GitHub API. Args: pull_request_number (int): the ID of the pull request Returns: dict: a representation of the pull request """ return self._github_repository.pull_request( pull_request_number).as_dict() @retry_async_decorator(retry_exceptions=GitHubException) async def get_release(self, tag_name): """Fetch the definition of the release matching the tag name. Args: tag_name (str): the tag linked to the release Returns: dict: a representation of the tag """ return self._github_repository.release_from_tag(tag_name).as_dict() @retry_async_decorator(retry_exceptions=GitHubException) async def get_tag_hash(self, tag_name): """Fetch the commit hash that was tagged with ``tag_name``. Args: tag_name (str): the name of the tag Returns: str: the commit hash linked by the tag """ tag_object = get_single_item_from_sequence( sequence=self._github_repository.tags(), condition=lambda tag: tag.name == tag_name, no_item_error_message='No tag "{}" exist'.format(tag_name), too_many_item_error_message='Too many tags "{}" found'.format( tag_name), ) return tag_object.commit.sha async def has_commit_landed_on_repository(self, context, revision): """Tell if a commit was landed on the repository or if it just comes from a pull request. Args: context (scriptworker.context.Context): the scriptworker context. revision (str): the commit hash or the tag name. Returns: bool: True if the commit is present in one of the branches of the main repository """ if any( vcs_rule.get("require_secret") for vcs_rule in context.config["trusted_vcs_rules"]): # This check uses unofficial API on github, which we can't easily # check for private repos, assume its true in the private case. log.info( "has_commit_landed_on_repository() not implemented for private" "repositories, assume True") return True # Revision may be a tag name. `branch_commits` doesn't work on tags if not _is_git_full_hash(revision): revision = await self.get_tag_hash(tag_name=revision) html_text = await _fetch_github_branch_commits_data( context, self._github_repository.html_url, revision) # https://github.com/{repo_owner}/{repo_name}/branch_commits/{revision} just returns some \n # when the commit hasn't landed on the origin repo. Otherwise, some HTML data is returned - it # represents the branches on which the given revision is present. return html_text != ""
class GitHubRepository(): """Wrapper around GitHub API. Used to access public data.""" def __init__(self, owner, repo_name, token=''): """Build the GitHub API URL which points to the definition of the repository. Args: owner (str): the owner's GitHub username repo_name (str): the name of the repository token (str): the GitHub API token Returns: dict: a representation of the repo definition """ self._github_repository = GitHub(token=token).repository(owner, repo_name) @property def definition(self): """Fetch the definition of the repository, exposed by the GitHub API. Returns: dict: a representation of the repo definition """ return self._github_repository.as_dict() def get_commit(self, commit_hash): """Fetch the definition of the commit, exposed by the GitHub API. Args: commit_hash (str): the hash of the git commit Returns: dict: a representation of the commit """ return self._github_repository.commit(commit_hash).as_dict() def get_pull_request(self, pull_request_number): """Fetch the definition of the pull request, exposed by the GitHub API. Args: pull_request_number (int): the ID of the pull request Returns: dict: a representation of the pull request """ return self._github_repository.pull_request(pull_request_number).as_dict() def get_release(self, tag_name): """Fetch the definition of the release matching the tag name. Args: tag_name (str): the tag linked to the release Returns: dict: a representation of the tag """ return self._github_repository.release_from_tag(tag_name).as_dict() def get_tag_hash(self, tag_name): """Fetch the commit hash that was tagged with ``tag_name``. Args: tag_name (str): the name of the tag Returns: str: the commit hash linked by the tag """ tag_object = get_single_item_from_sequence( sequence=self._github_repository.tags(), condition=lambda tag: tag.name == tag_name, no_item_error_message='No tag "{}" exist'.format(tag_name), too_many_item_error_message='Too many tags "{}" found'.format(tag_name), ) return tag_object.commit.sha async def has_commit_landed_on_repository(self, context, revision): """Tell if a commit was landed on the repository or if it just comes from a pull request. Args: context (scriptworker.context.Context): the scriptworker context. revision (str): the commit hash or the tag name. Returns: bool: True if the commit is present in one of the branches of the main repository """ # Revision may be a tag name. `branch_commits` doesn't work on tags if not _is_git_full_hash(revision): revision = self.get_tag_hash(tag_name=revision) repo = self._github_repository.html_url url = '/'.join([repo.rstrip('/'), 'branch_commits', revision]) html_data = await retry_request(context, url) html_text = html_data.strip() # https://github.com/{repo_owner}/{repo_name}/branch_commits/{revision} just returns some \n # when the commit hasn't landed on the origin repo. Otherwise, some HTML data is returned - it # represents the branches on which the given revision is present. return html_text != ''
class GitHubRepository(): """Wrapper around GitHub API. Used to access public data.""" def __init__(self, owner, repo_name, token=''): """Build the GitHub API URL which points to the definition of the repository. Args: owner (str): the owner's GitHub username repo_name (str): the name of the repository token (str): the GitHub API token Returns: dict: a representation of the repo definition """ self._github_repository = GitHub(token=token).repository( owner, repo_name) @property def definition(self): """Fetch the definition of the repository, exposed by the GitHub API. Returns: dict: a representation of the repo definition """ return self._github_repository.as_dict() def get_commit(self, commit_hash): """Fetch the definition of the commit, exposed by the GitHub API. Args: commit_hash (str): the hash of the git commit Returns: dict: a representation of the commit """ return self._github_repository.commit(commit_hash).as_dict() def get_pull_request(self, pull_request_number): """Fetch the definition of the pull request, exposed by the GitHub API. Args: pull_request_number (int): the ID of the pull request Returns: dict: a representation of the pull request """ return self._github_repository.pull_request( pull_request_number).as_dict() def get_release(self, tag_name): """Fetch the definition of the release matching the tag name. Args: tag_name (str): the tag linked to the release Returns: dict: a representation of the tag """ return self._github_repository.release_from_tag(tag_name).as_dict() def get_tag_hash(self, tag_name): """Fetch the commit hash that was tagged with ``tag_name``. Args: tag_name (str): the name of the tag Returns: str: the commit hash linked by the tag """ tag_object = get_single_item_from_sequence( sequence=self._github_repository.tags(), condition=lambda tag: tag.name == tag_name, no_item_error_message='No tag "{}" exist'.format(tag_name), too_many_item_error_message='Too many tags "{}" found'.format( tag_name), ) return tag_object.commit.sha async def has_commit_landed_on_repository(self, context, revision): """Tell if a commit was landed on the repository or if it just comes from a pull request. Args: context (scriptworker.context.Context): the scriptworker context. revision (str): the commit hash or the tag name. Returns: bool: True if the commit is present in one of the branches of the main repository """ # Revision may be a tag name. `branch_commits` doesn't work on tags if not _is_git_full_hash(revision): revision = self.get_tag_hash(tag_name=revision) repo = self._github_repository.html_url url = '/'.join([repo.rstrip('/'), 'branch_commits', revision]) from scriptworker.task import get_decision_task_id cache_key = '{}-{}'.format(get_decision_task_id(context.task), url) async with _branch_commits_cache_lock: if cache_key in _branch_commits_cache: html_text = _branch_commits_cache[cache_key] else: html_data = await retry_request(context, url) html_text = html_data.strip() _branch_commits_cache[cache_key] = html_text # https://github.com/{repo_owner}/{repo_name}/branch_commits/{revision} just returns some \n # when the commit hasn't landed on the origin repo. Otherwise, some HTML data is returned - it # represents the branches on which the given revision is present. return html_text != ''