Source code for rebasehelper.helpers.bugzilla_helper
# -*- coding: utf-8 -*-
#
# This tool helps you rebase your package to the latest version
# Copyright (C) 2013-2019 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Authors: Petr Hráček <phracek@redhat.com>
# Tomáš Hozza <thozza@redhat.com>
# Nikola Forró <nforro@redhat.com>
# František Nečas <fifinecas@seznam.cz>
import logging
import os
import re
from typing import cast, Optional, Tuple
import git # type: ignore
import requests
from rebasehelper.exceptions import RebaseHelperError
from rebasehelper.logger import CustomLogger
logger: CustomLogger = cast(CustomLogger, logging.getLogger(__name__))
[docs]
class BugzillaHelper:
"""Class for working with Upstream Release Monitoring on bugzilla."""
DIST_GIT_REPO_URL = 'https://src.fedoraproject.org/rpms'
BUGZILLA_REST_API_URL = 'https://bugzilla.redhat.com/rest'
UPSTREAM_RELEASE_MONITORING_USERNAME = 'upstream-release-monitoring'
QUERY_TIMEOUT = 30 # give up after 30 seconds
[docs]
@classmethod
def get_bugzilla_component(cls, bugzilla_id: str) -> str:
"""Gets a component of the bugzilla.
Args:
bugzilla_id: ID of the bugzilla.
Returns:
Component of the bugzilla.
Raises:
RebaseHelperError: If no such bugzilla exists or if the bugzilla
was not created by Upstream Release Monitoring.
"""
r = requests.get('{}/bug/{}'.format(cls.BUGZILLA_REST_API_URL, bugzilla_id),
timeout=cls.QUERY_TIMEOUT)
if not r.ok:
raise RebaseHelperError('Could not obtain data from bugzilla')
response_json = r.json()
if 'error' in response_json:
logger.error('Bugzilla error: %s', response_json['error'])
raise RebaseHelperError('Could not obtain data from bugzilla')
bug = response_json['bugs'][0]
if bug['creator_detail']['email'] != cls.UPSTREAM_RELEASE_MONITORING_USERNAME:
raise RebaseHelperError('The given bugzilla was not created by Upstream Release Monitoring')
return bug['component'][0]
[docs]
@classmethod
def clone_repository(cls, component: str, bugzilla_id: str) -> str:
"""Clones remote dist-git repository of a component.
Args:
component: Package to clone.
bugzilla_id: ID of the bugzilla.
Returns:
Path to the cloned repository.
Raises:
RebaseHelperError: If the directory, that the repository
is supposed to be cloned into, exists.
"""
path = os.path.abspath('{}-{}'.format(bugzilla_id, component))
if os.path.exists(path):
raise RebaseHelperError('Could not clone the repository because the directory '
'{} already exists'.format(path))
url = '{}/{}.git'.format(cls.DIST_GIT_REPO_URL, component)
logger.info("Cloning %s into %s", url, path)
git.Repo.clone_from(url, path)
return path
[docs]
@classmethod
def prepare_rebase_repository(cls, bugzilla_id: str) -> Tuple[str, str]:
"""Clones a repository based on Upstream Release Monitoring bugzilla.
Args:
bugzilla_id: ID of the bugzilla.
Returns:
Path of the cloned repository and version to rebase to.
Raises:
RebaseHelperError: If there was an error while obtaining
data from bugzilla or if there was a problem while cloning
the repository.
"""
component = cls.get_bugzilla_component(bugzilla_id)
version = cls.get_version_from_comments(bugzilla_id)
if not version:
raise RebaseHelperError('Could not obtain version from the bugzilla')
path = cls.clone_repository(component, bugzilla_id)
return path, version