leaper: adjust for SLE 15SP1 and SLE12SP4

This commit is contained in:
Ludwig Nussel
2018-06-26 15:18:55 +02:00
parent 07de65b419
commit cc2fa88058
6 changed files with 134 additions and 83 deletions

View File

@@ -47,6 +47,38 @@ import osc.core
import urllib2
from itertools import count
class PackageLookup(object):
""" helper class to manage 00Meta/lookup.yml
"""
def __init__(self, apiurl = None):
self.apiurl = apiurl
# dict[project][package]
self.lookup = {}
def get(self, project, package):
if not project in self.lookup:
self.load(project)
return self.lookup[project].get(package, None)
def reset(self):
self.lookup = {}
def load(self, project):
fh = self._load_lookup_file(project)
self.lookup[project] = yaml.safe_load(fh) if fh else {}
def _load_lookup_file(self, prj):
try:
return osc.core.http_GET(osc.core.makeurl(self.apiurl,
['source', prj, '00Meta', 'lookup.yml']))
except urllib2.HTTPError as e:
# in case the project doesn't exist yet (like sle update)
if e.code != 404:
raise e
return None
class ReviewBot(object):
"""
@@ -91,6 +123,7 @@ class ReviewBot(object):
self.comment_handler = False
self.override_allow = True
self.override_group_key = '{}-override-group'.format(self.bot_name.lower())
self.lookup = PackageLookup(self.apiurl)
self.load_config()

View File

@@ -45,21 +45,10 @@ class FactorySourceChecker(ReviewBot.ReviewBot):
def __init__(self, *args, **kwargs):
ReviewBot.ReviewBot.__init__(self, *args, **kwargs)
self.factory = "openSUSE:Factory"
self.factory = [ "openSUSE:Factory" ]
self.review_messages = { 'accepted' : 'ok', 'declined': 'the package needs to be accepted in Factory first' }
self.lookup = {}
self.history_limit = 5
def reset_lookup(self):
self.lookup = {}
def parse_lookup(self, project):
self.lookup.update(yaml.safe_load(self._load_lookup_file(project)))
def _load_lookup_file(self, prj):
return osc.core.http_GET(osc.core.makeurl(self.apiurl,
['source', prj, '00Meta', 'lookup.yml']))
def check_source_submission(self, src_project, src_package, src_rev, target_project, target_package):
super(FactorySourceChecker, self).check_source_submission(src_project, src_package, src_rev, target_project, target_package)
src_srcinfo = self.get_sourceinfo(src_project, src_package, src_rev)
@@ -93,12 +82,14 @@ class FactorySourceChecker(ReviewBot.ReviewBot):
def _package_get_upstream_projects(self, package):
""" return list of projects where the specified package is supposed to come
from. Either by lookup table or self.factory """
projects = self.factory
if self.lookup and package in self.lookup:
projects = self.lookup[package]
projects = []
for prj in self.factory:
r = self.lookup.get(prj, package)
if r:
projects.append(r)
if isinstance(projects, basestring):
projects = [projects]
if not projects:
projects = self.factory
return projects

View File

@@ -54,7 +54,7 @@ class TagChecker(ReviewBot.ReviewBot):
def __init__(self, *args, **kwargs):
super(TagChecker, self).__init__(*args, **kwargs)
self.factory = "openSUSE:Factory"
self.factory = [ "openSUSE:Factory" ]
self.review_messages['declined'] = """
(This is a script, so report bugs)

145
leaper.py
View File

@@ -78,14 +78,7 @@ class Leaper(ReviewBot.ReviewBot):
def prepare_review(self):
# update lookup information on every run
if self.ibs:
self.factory.parse_lookup('SUSE:SLE-15:GA')
self.lookup_sle15 = self.factory.lookup.copy()
return
self.factory.parse_lookup('openSUSE:Leap:15.1')
self.factory.parse_lookup('openSUSE:Leap:15.1:NonFree')
self.lookup_150 = self.factory.lookup.copy()
self.lookup.reset()
def get_source_packages(self, project, expand=False):
"""Return the list of packages in a project."""
@@ -127,6 +120,9 @@ class Leaper(ReviewBot.ReviewBot):
if origin.startswith('Devel;'):
(dummy, origin, dummy) = origin.split(';')
# FIXME: to make the rest of the code easier this should probably check
# if the srcmd5 matches the origin project. That way it doesn't really
# matter from where something got submitted as long as the sources match.
return project.startswith(origin)
def check_source_submission(self, src_project, src_package, src_rev, target_project, target_package):
@@ -141,7 +137,10 @@ class Leaper(ReviewBot.ReviewBot):
src_srcinfo = self.get_sourceinfo(src_project, src_package, src_rev)
package = target_package
origin = None
origin = self.lookup.get(target_project, package)
origin_same = True
if origin:
origin_same = self._check_same_origin(origin, src_project)
if src_srcinfo is None:
# source package does not exist?
@@ -151,63 +150,80 @@ class Leaper(ReviewBot.ReviewBot):
if self.ibs and target_project.startswith('SUSE:SLE'):
if package in self.lookup_sle15:
origin = self.lookup_sle15[package]
origin_same = True
if origin:
origin_same = self._check_same_origin(origin, src_project)
self.logger.info("expected origin is '%s' (%s)", origin,
"unchanged" if origin_same else "changed")
review_result = None
prj = 'openSUSE.org:openSUSE:Factory'
# True or None (open request) are acceptable for SLE.
self.source_in_factory = self._check_factory(package, src_srcinfo, prj)
if self.source_in_factory is None:
self.pending_factory_submission = True
if self.source_in_factory is not False:
return self.source_in_factory
# got false. could mean package doesn't exist or no match
if self.is_package_in_project(prj, package):
self.logger.info('different sources in {}'.format(self.rdiff_link(src_project, src_package, src_rev, prj, package)))
prj = 'openSUSE.org:openSUSE:Leap:15.0'
# TODO Ugly save for SLE-15-SP1.
if False and self.is_package_in_project(prj, package):
if self._check_factory(package, src_srcinfo, prj) is True:
self.logger.info('found source match in {}'.format(prj))
# True or None (open request) are acceptable for SLE.
in_factory = self._check_factory(package, src_srcinfo, prj)
if in_factory:
review_result = True
self.source_in_factory = True
elif in_factory is None:
self.pending_factory_submission = True
else:
self.logger.info('different sources in {}'.format(self.rdiff_link(src_project, src_package, src_rev, prj, package)))
devel_project, devel_package = devel_project_get(self.apiurl, 'openSUSE.org:openSUSE:Factory', package)
if devel_project is not None:
# specifying devel package is optional
if devel_package is None:
devel_package = package
if self.is_package_in_project(devel_project, devel_package):
if self._check_matching_srcmd5(devel_project, devel_package, src_srcinfo.verifymd5) == True:
self.logger.info('matching sources in {}/{}'.format(devel_project, devel_package))
return True
else:
self.logger.info('different sources in {}'.format(self.rdiff_link(src_project, src_package, src_rev, devel_project, devel_package)))
else:
self.logger.info('no devel project found for {}/{}'.format('openSUSE.org:openSUSE:Factory', package))
self.logger.info('the package is not in Factory, nor submitted there')
#self.logger.info('no matching sources in Factory, Leap:15.0, nor devel project')
self.logger.info('no matching sources in Factory, nor devel project')
if review_result == None:
other_projects_to_check = []
m = re.match('SUSE:SLE-(\d+)(?:-SP(\d+)):', target_project)
if m:
sle_version = int(m.group(1))
sp_version = int(m.group(2))
versions_to_check = []
# yeah, too much harcoding here
if sle_version == 12:
versions_to_check = [ '42.3' ]
elif sle_version == 15:
versions_to_check = [ '15.%d'%i for i in range(sp_version+1) ]
else:
self.logger.error("can't handle %d.%d", sle_version, sp_version)
if origin_same is False:
for version in versions_to_check:
leap = 'openSUSE.org:openSUSE:Leap:%s'%(version)
other_projects_to_check += [ leap, leap + ':Update', leap + ':NonFree', leap + ':NonFree:Update' ]
for prj in other_projects_to_check:
if self.is_package_in_project(prj, package):
self.logger.info('checking {}'.format(prj))
if self._check_factory(package, src_srcinfo, prj) is True:
self.logger.info('found source match in {}'.format(prj))
else:
self.logger.info('different sources in {}'.format(self.rdiff_link(src_project, src_package, src_rev, prj, package)))
devel_project, devel_package = devel_project_get(self.apiurl, 'openSUSE.org:openSUSE:Factory', package)
if devel_project is not None:
# specifying devel package is optional
if devel_package is None:
devel_package = package
if self.is_package_in_project(devel_project, devel_package):
if self._check_matching_srcmd5(devel_project, devel_package, src_srcinfo.verifymd5) == True:
self.logger.info('matching sources in {}/{}'.format(devel_project, devel_package))
return True
else:
self.logger.info('different sources in devel project {}'.format(self.rdiff_link(src_project, src_package, src_rev, devel_project, devel_package)))
else:
self.logger.info('no devel project found for {}/{}'.format('openSUSE.org:openSUSE:Factory', package))
self.logger.info('no matching sources found anywhere. Needs a human to decide whether that is ok. Please provide some justification to help that person.')
if not review_result:
review_result = origin_same
if origin_same:
self.logger.info("ok, origin %s unchanged", origin)
else:
# only log origin state if it's taken into consideration for the review result
self.logger.info("Submitted from a different origin than expected ('%s')", origin)
if not review_result and self.override_allow:
# Rather than decline, leave review open in-case of change and
# ask release manager for input via override comment.
self.logger.info('Comment `(at){} override accept` to force accept.'.format(self.review_user))
self.needs_release_manager = True
return None
review_result = None
return origin_same
if package in self.lookup_150:
origin = self.lookup_150[package]
return review_result
# obviously
if src_project in ('openSUSE:Factory', 'openSUSE:Factory:NonFree'):
@@ -216,9 +232,8 @@ class Leaper(ReviewBot.ReviewBot):
is_fine_if_factory = False
not_in_factory_okish = False
if origin:
origin_same = self._check_same_origin(origin, src_project)
self.logger.info("expected origin is '%s' (%s)", origin,
"unchanged" if origin_same else "changed")
"unchanged" if origin_same else "changed")
if origin.startswith('Devel;'):
if origin_same == False:
self.logger.debug("not submitted from devel project")
@@ -349,13 +364,13 @@ class Leaper(ReviewBot.ReviewBot):
# new package submitted from Factory. Check if it was in
# 42.3 before and skip maintainer review if so.
# commented for reference. Needed again for 16.0 probably
# subprj = src_project[len('openSUSE:Factory'):]
# if self.source_in_factory and target_project.startswith('openSUSE:Leap:15.0') \
# and self.is_package_in_project('openSUSE:Leap:42.3'+subprj, package):
# self.logger.info('package was in 42.3')
# self.do_check_maintainer_review = False
# return True
subprj = src_project[len('openSUSE:Factory'):]
# disabled for reference. Needed again for 16.0 probably
if False and self.source_in_factory and target_project.startswith('openSUSE:Leap:15.0') \
and self.is_package_in_project('openSUSE:Leap:42.3'+subprj, package):
self.logger.info('package was in 42.3')
self.do_check_maintainer_review = False
return True
is_fine_if_factory = True
self.needs_release_manager = True
@@ -457,9 +472,9 @@ class Leaper(ReviewBot.ReviewBot):
if self.automatic_submission and creator != bot_name:
self.logger.info('@{}: this request would have been automatically created by {} after the Factory submission was accepted in order to eleviate the need to manually create requests for packages sourced from Factory'.format(creator, bot_name))
elif self.source_in_factory:
self.logger.info("the submitted sources are in or accepted for Factory")
self.logger.info("perfect. the submitted sources are in or accepted for Factory")
elif self.source_in_factory == False:
self.logger.info("the submitted sources are NOT in Factory")
self.logger.warn("the submitted sources are NOT in Factory")
if request_ok == False:
self.logger.info("NOTE: if you think the automated review was wrong here, please talk to the release team before reopening the request")

View File

@@ -213,6 +213,10 @@ Pico text editor while also offering a few enhancements.</description>
match_querystring=True,
body='<collection matches="0"></collection>')
httpretty.register_uri(httpretty.GET,
APIURL + "/source/openSUSE:Factory/00Meta/lookup.yml",
status = 404)
result = {'state_accepted': None}
def change_request(result, method, uri, headers):

View File

@@ -61,6 +61,10 @@ class TestFactorySourceAccept(unittest.TestCase):
def test_accept_request(self):
httpretty.register_uri(httpretty.GET,
rr("/source/openSUSE:Factory/00Meta/lookup.yml"),
status = 404)
httpretty.register_uri(httpretty.GET,
APIURL + "/request/770001",
body = """
@@ -262,6 +266,10 @@ class TestFactorySourceAccept(unittest.TestCase):
</status>
""")
httpretty.register_uri(httpretty.GET,
rr("/source/openSUSE:Factory/00Meta/lookup.yml"),
status = 404)
httpretty.register_uri(httpretty.GET,
rr("/search/request?match=%28state%2F%40name%3D%27new%27+or+state%2F%40name%3D%27review%27%29+and+%28action%2Ftarget%2F%40project%3D%27openSUSE%3AFactory%27+or+submit%2Ftarget%2F%40project%3D%27openSUSE%3AFactory%27+or+action%2Fsource%2F%40project%3D%27openSUSE%3AFactory%27+or+submit%2Fsource%2F%40project%3D%27openSUSE%3AFactory%27%29+and+%28action%2Ftarget%2F%40package%3D%27plan%27+or+submit%2Ftarget%2F%40package%3D%27plan%27+or+action%2Fsource%2F%40package%3D%27plan%27+or+submit%2Fsource%2F%40package%3D%27plan%27%29+and+action%2F%40type%3D%27submit%27"),
match_querystring = True,