2019-05-16 06:59:25 +02:00
#!/usr/bin/python3
2016-05-30 18:19:49 +02:00
from pprint import pprint
2016-09-26 11:16:30 +02:00
import os
import sys
import re
2016-05-30 18:19:49 +02:00
import logging
from optparse import OptionParser
import cmdln
try :
from xml . etree import cElementTree as ET
except ImportError :
import cElementTree as ET
import osc . core
2018-08-16 23:35:10 -05:00
from osclib . conf import Config
2018-01-17 18:08:40 -06:00
from osclib . core import devel_project_get
2018-11-16 08:32:25 +01:00
2019-05-16 06:59:25 +02:00
from urllib . error import HTTPError
2018-11-16 08:32:25 +01:00
2016-05-30 18:19:49 +02:00
import yaml
import ReviewBot
from check_source_in_factory import FactorySourceChecker
class Leaper ( ReviewBot . ReviewBot ) :
def __init__ ( self , * args , * * kwargs ) :
ReviewBot . ReviewBot . __init__ ( self , * args , * * kwargs )
2016-09-26 11:16:30 +02:00
2017-06-20 16:25:46 -05:00
# ReviewBot options.
self . request_default_return = True
2017-06-20 16:32:16 -05:00
self . comment_handler = True
2017-06-20 16:25:46 -05:00
2016-09-26 11:16:30 +02:00
self . do_comments = True
2016-05-30 18:19:49 +02:00
# for FactorySourceChecker
self . factory = FactorySourceChecker ( * args , * * kwargs )
2016-07-29 10:55:37 +02:00
2017-04-18 16:36:33 +02:00
self . needs_legal_review = False
2016-07-29 10:55:37 +02:00
self . needs_reviewteam = False
self . pending_factory_submission = False
2016-09-30 11:51:00 +02:00
self . source_in_factory = None
2016-09-26 11:16:30 +02:00
self . needs_release_manager = False
2018-03-07 14:47:03 -06:00
self . release_manager_group = None
self . review_team_group = None
self . legal_review_group = None
2016-10-10 16:20:30 +02:00
self . must_approve_version_updates = False
self . must_approve_maintenance_updates = False
2016-12-29 00:34:56 -06:00
self . needs_check_source = False
self . check_source_group = None
2017-02-15 21:15:27 -06:00
self . automatic_submission = False
2016-09-26 11:16:30 +02:00
2016-12-06 17:00:32 +01:00
# project => package list
self . packages = { }
2016-07-29 10:55:37 +02:00
def prepare_review ( self ) :
2017-01-18 13:50:05 +01:00
# update lookup information on every run
2018-06-26 15:18:55 +02:00
self . lookup . reset ( )
2016-12-06 17:00:32 +01:00
def get_source_packages ( self , project , expand = False ) :
""" Return the list of packages in a project. """
query = { ' expand ' : 1 } if expand else { }
2017-10-04 09:40:20 +02:00
try :
2017-10-20 08:54:37 +02:00
root = ET . parse ( osc . core . http_GET ( osc . core . makeurl ( self . apiurl , [ ' source ' , project ] ,
2017-10-04 09:40:20 +02:00
query = query ) ) ) . getroot ( )
packages = [ i . get ( ' name ' ) for i in root . findall ( ' entry ' ) ]
2018-11-16 08:32:25 +01:00
except HTTPError as e :
2017-10-04 09:40:20 +02:00
# in case the project doesn't exist yet (like sle update)
if e . code != 404 :
raise e
packages = [ ]
2016-12-06 17:00:32 +01:00
return packages
def is_package_in_project ( self , project , package ) :
if not project in self . packages :
self . packages [ project ] = self . get_source_packages ( project )
return True if package in self . packages [ project ] else False
2016-06-26 13:52:56 +02:00
2019-01-16 15:18:15 +01:00
# this is so bad
def _webui_from_api ( self , apiurl ) :
return apiurl . replace ( ' //api. ' , ' //build. ' )
# OBS is not smart enough to redirect to the mapped instance and just
# displays 404 so we have to do it ourselves
def package_link ( self , project , package ) :
apiurl = self . apiurl
for prefix , url , srprefix in self . config . project_namespace_api_map :
if project . startswith ( prefix ) :
apiurl = url
project = project [ len ( prefix ) : ]
break
return ' [ %(project)s / %(package)s ]( %(url)s /package/show/ %(project)s / %(package)s ) ' % {
' url ' : self . _webui_from_api ( apiurl ) ,
' project ' : project ,
' package ' : package ,
}
2017-01-31 17:09:39 +01:00
def rdiff_link ( self , src_project , src_package , src_rev , target_project , target_package = None ) :
if target_package is None :
target_package = src_package
2019-01-16 15:18:15 +01:00
apiurl = self . apiurl
for prefix , url , srprefix in self . config . project_namespace_api_map :
# can't rdiff if both sides are remote
# https://github.com/openSUSE/open-build-service/issues/4601
if target_project . startswith ( prefix ) and src_project . startswith ( prefix ) :
apiurl = url
src_project = src_project [ len ( prefix ) : ]
target_project = target_project [ len ( prefix ) : ]
break
return self . package_link ( target_project , target_package ) + ' ([diff]( %(url)s /package/rdiff/ %(src_project)s / %(src_package)s ?opackage= %(target_package)s &oproject= %(target_project)s &rev= %(src_rev)s )) ' % {
' url ' : self . _webui_from_api ( apiurl ) ,
2017-01-31 17:09:39 +01:00
' src_project ' : src_project ,
' src_package ' : src_package ,
' src_rev ' : src_rev ,
' target_project ' : target_project ,
' target_package ' : target_package ,
}
2017-03-06 16:25:39 +01:00
def _check_same_origin ( self , origin , project ) :
if origin == ' FORK ' :
return True
if origin . startswith ( ' Devel; ' ) :
( dummy , origin , dummy ) = origin . split ( ' ; ' )
2018-06-26 15:18:55 +02:00
# 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.
2017-03-06 16:25:39 +01:00
return project . startswith ( origin )
2016-05-30 18:19:49 +02:00
def check_source_submission ( self , src_project , src_package , src_rev , target_project , target_package ) :
2018-08-21 23:47:58 -05:00
ret = self . check_source_submission_inner ( src_project , src_package , src_rev , target_project , target_package )
# The layout of this code is just plain wrong and awkward. What is
# really desired a "post check source submission" not
# check_one_request() which applies to all action types and all actions
# at once. The follow-ups need the same context that the main method
# determining to flip the switch had. For maintenance incidents the
# ReviewBot code does a fair bit of mangling to the package and project
# values passed in which is not present during check_one_request().
# Currently the only feature used by maintenance is
# do_check_maintainer_review and the rest of the checks apply in the
# single action workflow so this should work fine, but really all the
# processing should be done per-action instead of per-request.
if self . do_check_maintainer_review :
self . devel_project_review_ensure ( self . request , target_project , target_package )
return ret
def check_source_submission_inner ( self , src_project , src_package , src_rev , target_project , target_package ) :
2017-02-10 16:09:51 -06:00
super ( Leaper , self ) . check_source_submission ( src_project , src_package , src_rev , target_project , target_package )
2017-04-10 23:17:09 -05:00
self . automatic_submission = False
2017-03-15 09:34:58 -05:00
if src_project == target_project and src_package == target_package :
self . logger . info ( ' self submission detected ' )
self . needs_release_manager = True
return True
2016-06-26 13:52:56 +02:00
src_srcinfo = self . get_sourceinfo ( src_project , src_package , src_rev )
package = target_package
2018-06-26 15:18:55 +02:00
origin = self . lookup . get ( target_project , package )
origin_same = True
if origin :
origin_same = self . _check_same_origin ( origin , src_project )
2017-01-18 13:50:05 +01:00
2016-06-26 13:52:56 +02:00
if src_srcinfo is None :
# source package does not exist?
# handle here to avoid crashing on the next line
2019-05-11 14:25:02 +02:00
self . logger . warning ( " Could not get source info for %s / %s @ %s " % ( src_project , src_package , src_rev ) )
2016-06-26 13:52:56 +02:00
return False
2017-01-17 22:09:25 -06:00
if self . ibs and target_project . startswith ( ' SUSE:SLE ' ) :
2017-11-20 14:54:49 +01:00
2018-06-26 15:18:55 +02:00
review_result = None
2017-01-19 10:29:39 +01:00
prj = ' openSUSE.org:openSUSE:Factory '
2018-10-01 09:57:15 +02:00
# 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 :
2018-11-19 16:52:53 +01:00
if not self . is_package_in_project ( prj , package ) :
2018-10-01 09:57:15 +02:00
self . logger . info ( ' the package is not in Factory, nor submitted there ' )
2017-01-19 10:29:39 +01:00
else :
2017-01-31 17:09:39 +01:00
self . logger . info ( ' different sources in {} ' . format ( self . rdiff_link ( src_project , src_package , src_rev , prj , package ) ) )
2018-06-26 15:18:55 +02:00
2018-10-01 09:57:15 +02:00
if review_result == None and not self . pending_factory_submission :
2018-06-26 15:18:55 +02:00
other_projects_to_check = [ ]
2018-10-24 16:29:15 -05:00
m = re . match ( r ' SUSE:SLE-( \ d+)(?:-SP( \ d+)): ' , target_project )
2018-06-26 15:18:55 +02:00
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 )
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 ) :
2018-11-19 16:52:02 +01:00
self . logger . debug ( ' checking {} ' . format ( prj ) )
2018-06-26 15:18:55 +02:00
if self . _check_factory ( package , src_srcinfo , prj ) is True :
self . logger . info ( ' found source match in {} ' . format ( prj ) )
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 ) )
2017-01-17 22:09:25 -06:00
2018-06-26 15:18:55 +02:00
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. ' )
2019-01-16 14:17:54 +01:00
else :
leap = ' openSUSE.org:openSUSE:Leap:15.1 '
if not self . is_package_in_project ( target_project , package ) \
and self . is_package_in_project ( leap , package ) \
and self . _check_factory ( package , src_srcinfo , leap ) is False :
self . logger . info ( ' different sources in {} ' . format ( self . rdiff_link ( src_project , src_package , src_rev , leap , package ) ) )
2017-01-17 22:09:25 -06:00
2018-10-01 09:57:15 +02:00
if not review_result and origin is not None :
2018-06-26 15:18:55 +02:00
review_result = origin_same
2019-01-16 14:19:30 +01:00
if origin_same or origin == ' openSUSE.org:openSUSE:Factory ' and self . pending_factory_submission :
2018-06-26 15:18:55 +02:00
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 )
2018-11-19 17:02:09 +01:00
self . needs_release_manager = True
# no result so far and also no factory submission to wait
# for. So just pass to avoid requring too much overrides
if not self . pending_factory_submission :
review_result = True
2018-06-26 15:18:55 +02:00
if not review_result and self . override_allow :
2018-03-07 14:49:06 -06:00
# 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
2018-06-26 15:18:55 +02:00
review_result = None
2018-03-07 14:49:06 -06:00
2018-06-26 15:18:55 +02:00
return review_result
2016-06-26 13:52:56 +02:00
2018-08-03 15:54:30 -05:00
if target_project . endswith ( ' :Update ' ) :
self . logger . info ( " expected origin is ' %s ' ( %s ) " , origin ,
" unchanged " if origin_same else " changed " )
2018-08-21 23:47:58 -05:00
# Only when not from current product should request require maintainer review.
self . do_check_maintainer_review = False
2018-08-03 15:54:30 -05:00
if origin_same :
return True
good = self . _check_matching_srcmd5 ( origin , target_package , src_srcinfo . verifymd5 )
if good :
self . logger . info ( ' submission source found in origin ( {} ) ' . format ( origin ) )
return good
good = self . factory . _check_requests ( origin , target_package , src_srcinfo . verifymd5 )
if good or good == None :
self . logger . info ( ' found pending submission against origin ( {} ) ' . format ( origin ) )
return good
2018-10-15 16:40:26 -05:00
# TODO #1662: Uncomment once maintbot has been superseded and leaper
# is no longer run in comment-only mode.
#self.do_check_maintainer_review = True
2018-08-21 23:47:58 -05:00
2018-08-03 15:54:30 -05:00
return None
elif self . action . type == ' maintenance_incident ' :
self . logger . debug ( ' unhandled incident pattern (targetting non :Update project) ' )
return True
2017-11-20 14:54:49 +01:00
# obviously
if src_project in ( ' openSUSE:Factory ' , ' openSUSE:Factory:NonFree ' ) :
self . source_in_factory = True
2016-09-26 11:16:30 +02:00
is_fine_if_factory = False
2016-09-30 11:51:00 +02:00
not_in_factory_okish = False
2016-06-26 13:52:56 +02:00
if origin :
2017-01-11 14:37:26 -06:00
self . logger . info ( " expected origin is ' %s ' ( %s ) " , origin ,
2018-06-26 15:18:55 +02:00
" unchanged " if origin_same else " changed " )
2016-06-26 13:52:56 +02:00
if origin . startswith ( ' Devel; ' ) :
2017-03-06 16:25:39 +01:00
if origin_same == False :
2016-09-26 11:16:30 +02:00
self . logger . debug ( " not submitted from devel project " )
return False
is_fine_if_factory = True
2016-09-30 11:51:00 +02:00
not_in_factory_okish = True
2016-10-10 16:20:30 +02:00
if self . must_approve_version_updates :
self . needs_release_manager = True
2016-09-26 11:16:30 +02:00
# fall through to check history and requests
2016-06-26 13:52:56 +02:00
elif origin . startswith ( ' openSUSE:Factory ' ) :
2017-02-15 21:15:27 -06:00
# A large number of requests are created by hand that leaper
# would have created via update_crawler.py. This applies to
# other origins, but primary looking to let Factory submitters
# know that there is no need to make manual submissions to both.
# Since it has a lookup entry it is not a new package.
2017-07-03 17:23:00 +02:00
self . automatic_submission = False
2016-10-13 18:08:13 +02:00
if self . must_approve_version_updates :
self . needs_release_manager = True
2016-09-26 11:16:30 +02:00
if origin == src_project :
2016-09-30 11:51:00 +02:00
self . source_in_factory = True
2018-02-09 13:29:43 +01:00
# no need to approve submissions from Factory if
# the lookup file points to Factory. Just causes
2018-03-16 14:58:27 -05:00
# spam for many maintainers #1393
2018-02-09 13:29:43 +01:00
self . do_check_maintainer_review = False
2016-09-26 11:16:30 +02:00
is_fine_if_factory = True
# fall through to check history and requests
elif origin == ' FORK ' :
2017-12-22 11:39:28 +01:00
is_fine_if_factory = True
2017-04-20 22:18:25 -05:00
if not src_project . startswith ( ' SUSE:SLE- ' ) :
not_in_factory_okish = True
self . needs_check_source = True
2016-09-26 11:16:30 +02:00
self . needs_release_manager = True
# fall through to check history and requests
2017-08-01 16:36:18 -05:00
# TODO Ugly save for 15.1 (n-1).
2018-06-25 14:40:52 +02:00
elif origin . startswith ( ' openSUSE:Leap:15.0 ' ) :
2016-10-10 16:20:30 +02:00
if self . must_approve_maintenance_updates :
self . needs_release_manager = True
2018-08-28 18:16:45 +08:00
if src_project . startswith ( ' openSUSE:Leap ' ) :
self . do_check_maintainer_review = False
2016-06-26 13:52:56 +02:00
# submitted from :Update
2017-01-11 14:37:26 -06:00
if origin_same :
2017-08-01 16:36:18 -05:00
self . logger . debug ( " submission from 15.0 ok " )
2016-12-06 17:00:32 +01:00
return True
# switching to sle package might make sense
2017-08-01 16:36:18 -05:00
if src_project . startswith ( ' SUSE:SLE-15 ' ) :
2016-12-06 17:00:32 +01:00
self . needs_release_manager = True
2018-08-28 18:16:45 +08:00
self . do_check_maintainer_review = False
2016-06-26 13:52:56 +02:00
return True
# submitted from elsewhere but is in :Update
else :
2018-05-30 13:55:38 +02:00
good = self . _check_matching_srcmd5 ( ' openSUSE:Leap:15.0:Update ' , target_package , src_srcinfo . verifymd5 )
2016-06-26 13:52:56 +02:00
if good :
2017-08-01 16:36:18 -05:00
self . logger . info ( " submission found in 15.0 " )
2016-06-26 13:52:56 +02:00
return good
# check release requests too
2017-08-01 16:36:18 -05:00
good = self . factory . _check_requests ( ' openSUSE:Leap:15.0:Update ' , target_package , src_srcinfo . verifymd5 )
2016-06-26 13:52:56 +02:00
if good or good == None :
self . logger . debug ( " found request " )
return good
# let's see where it came from before
2018-07-25 18:09:51 +08:00
oldorigin = self . lookup . get ( ' openSUSE:Leap:15.0 ' , target_package )
if oldorigin :
2016-06-26 13:52:56 +02:00
self . logger . debug ( " oldorigin {} " . format ( oldorigin ) )
# Factory. So it's ok to keep upgrading it to Factory
# TODO: whitelist packages where this is ok and block others?
2017-08-01 16:36:18 -05:00
self . logger . info ( " Package was from %s in 15.0 " , oldorigin )
2016-06-26 13:52:56 +02:00
if oldorigin . startswith ( ' openSUSE:Factory ' ) :
2016-09-30 11:51:00 +02:00
# check if an attempt to switch to SLE package is made
2017-08-01 16:36:18 -05:00
for sp in ( ' SP1:GA ' , ' SP1:Update ' ) :
2018-05-30 13:55:38 +02:00
good = self . _check_matching_srcmd5 ( ' SUSE:SLE-15- {} ' . format ( sp ) , target_package , src_srcinfo . verifymd5 )
2016-12-06 17:00:32 +01:00
if good :
self . logger . info ( " request sources come from SLE " )
self . needs_release_manager = True
return good
2017-08-01 16:36:18 -05:00
# TODO Ugly save for 15.2 (n-2).
elif False and oldorigin . startswith ( ' openSUSE:Leap:15.0 ' ) :
2018-07-25 18:09:51 +08:00
self . logger . info ( " Package was from %s in 15.0 " , oldorigin )
2016-09-26 11:16:30 +02:00
# the release manager needs to review attempts to upgrade to Factory
is_fine_if_factory = True
self . needs_release_manager = True
2016-06-26 13:52:56 +02:00
2017-08-01 16:36:18 -05:00
elif origin . startswith ( ' SUSE:SLE-15 ' ) :
2016-10-10 16:20:30 +02:00
if self . must_approve_maintenance_updates :
self . needs_release_manager = True
2018-08-28 18:16:45 +08:00
if src_project . startswith ( ' SUSE:SLE-15 ' ) :
self . do_check_maintainer_review = False
2018-06-25 14:40:52 +02:00
for v in ( ' 15.0 ' , ' 15.1 ' ) :
2016-12-06 17:00:32 +01:00
prj = ' openSUSE:Leap: {} :SLE-workarounds ' . format ( v )
if self . is_package_in_project ( prj , target_package ) :
self . logger . info ( " found package in %s " , prj )
2018-05-30 13:55:38 +02:00
if not self . _check_matching_srcmd5 ( prj ,
2016-12-06 17:00:32 +01:00
target_package ,
src_srcinfo . verifymd5 ) :
2018-04-11 13:26:48 +02:00
self . logger . info ( " sources in %s are NOT identical " ,
2017-05-05 10:57:17 +02:00
self . rdiff_link ( src_project , src_package , src_rev , prj , package ) )
2016-12-06 17:00:32 +01:00
self . needs_release_manager = True
2016-06-26 13:52:56 +02:00
# submitted from :Update
2016-09-30 11:51:00 +02:00
if origin == src_project :
self . logger . debug ( " submission origin ok " )
return True
elif origin . endswith ( ' :GA ' ) \
2016-08-24 16:47:26 +02:00
and src_project == origin [ : - 2 ] + ' Update ' :
self . logger . debug ( " sle update submission " )
2016-06-26 13:52:56 +02:00
return True
2016-12-06 17:00:32 +01:00
# check if submitted from higher SP
2017-08-01 16:36:18 -05:00
priolist = [ ' SUSE:SLE-15: ' , ' SUSE:SLE-15-SP1: ' , ' SUSE:SLE-15-SP2: ' , ' SUSE:SLE-15-SP3: ' ]
2016-12-06 17:00:32 +01:00
for i in range ( len ( priolist ) - 1 ) :
if origin . startswith ( priolist [ i ] ) :
for prj in priolist [ i + 1 : ] :
if src_project . startswith ( prj ) :
self . logger . info ( " submission from higher service pack %s :* ok " , prj )
return True
2016-09-30 11:51:00 +02:00
2017-05-11 23:34:35 -05:00
in_sle_origin = self . _check_factory ( target_package , src_srcinfo , origin )
2017-05-09 20:18:23 -05:00
if in_sle_origin :
self . logger . info ( ' parallel submission, also in {} ' . format ( origin ) )
return True
2016-09-30 11:51:00 +02:00
self . needs_release_manager = True
2016-09-26 11:16:30 +02:00
# the release manager needs to review attempts to upgrade to Factory
is_fine_if_factory = True
else :
self . logger . error ( " unhandled origin %s " , origin )
return False
2016-06-26 13:52:56 +02:00
else : # no origin
2016-09-30 11:51:00 +02:00
# submission from SLE is ok
2017-08-01 16:36:18 -05:00
if src_project . startswith ( ' SUSE:SLE-15 ' ) :
2017-11-20 14:54:49 +01:00
self . do_check_maintainer_review = False
2016-06-26 13:52:56 +02:00
return True
2016-09-30 11:51:00 +02:00
2017-11-20 14:54:49 +01:00
# new package submitted from Factory. Check if it was in
# 42.3 before and skip maintainer review if so.
2018-06-26 15:18:55 +02:00
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 ) :
2019-01-30 16:08:52 +01:00
self . logger . info ( ' package was in 42.3 ' )
self . do_check_maintainer_review = False
return True
2017-11-20 14:54:49 +01:00
2016-09-30 11:51:00 +02:00
is_fine_if_factory = True
self . needs_release_manager = True
2017-02-20 14:53:45 +01:00
if origin is None or not origin . startswith ( ' SUSE:SLE- ' ) :
2017-08-01 16:36:18 -05:00
for p in ( ' :Update ' , ' :GA ' ) :
prj = ' SUSE:SLE-15 ' + p
2017-05-05 10:57:17 +02:00
if self . is_package_in_project ( prj , package ) :
2017-06-27 01:15:25 -05:00
self . logger . info ( ' Package is in {} ' . format (
self . rdiff_link ( src_project , src_package , src_rev , prj , package ) ) )
2017-02-20 14:53:45 +01:00
break
2017-05-05 10:57:17 +02:00
is_in_factory = self . source_in_factory
2016-09-30 11:51:00 +02:00
# we came here because none of the above checks find it good, so
# let's see if the package is in Factory at least
2017-05-05 10:57:17 +02:00
if is_in_factory is None :
is_in_factory = self . _check_factory ( package , src_srcinfo )
2016-09-30 11:51:00 +02:00
if is_in_factory :
self . source_in_factory = True
self . needs_reviewteam = False
2017-04-18 16:36:33 +02:00
self . needs_legal_review = False
2016-09-30 11:51:00 +02:00
elif is_in_factory is None :
self . pending_factory_submission = True
self . needs_reviewteam = False
2017-04-18 16:36:33 +02:00
self . needs_legal_review = False
2016-09-30 11:51:00 +02:00
else :
2017-08-01 16:36:18 -05:00
if src_project . startswith ( ' SUSE:SLE-15 ' ) \
or src_project . startswith ( ' openSUSE:Leap:15. ' ) :
2016-09-30 11:51:00 +02:00
self . needs_reviewteam = False
2017-04-18 16:36:33 +02:00
self . needs_legal_review = False
2016-09-30 11:51:00 +02:00
else :
self . needs_reviewteam = True
2017-04-18 16:36:33 +02:00
self . needs_legal_review = True
2016-10-12 14:33:14 +02:00
self . source_in_factory = False
2016-06-26 13:52:56 +02:00
2016-09-26 11:16:30 +02:00
if is_fine_if_factory :
if self . source_in_factory :
return True
elif self . pending_factory_submission :
return None
2016-09-30 11:51:00 +02:00
elif not_in_factory_okish :
self . needs_reviewteam = True
2017-04-18 16:36:33 +02:00
self . needs_legal_review = True
2016-09-26 11:16:30 +02:00
return True
2018-03-12 14:04:14 +01:00
if self . override_allow :
# Rather than decline, leave review open 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
2016-06-26 13:52:56 +02:00
return False
2017-01-17 22:09:25 -06:00
def _check_factory ( self , target_package , src_srcinfo , target_project = ' openSUSE:Factory ' ) :
2018-03-23 15:27:37 +01:00
for subprj in ( ' ' , ' :NonFree ' , ' :Live ' ) :
prj = ' ' . join ( ( target_project , subprj ) )
2018-05-30 13:55:38 +02:00
good = self . _check_matching_srcmd5 ( prj , target_package , src_srcinfo . verifymd5 )
2016-06-26 13:52:56 +02:00
if good :
return good
2018-03-23 15:27:37 +01:00
good = self . factory . _check_requests ( prj , target_package , src_srcinfo . verifymd5 )
2016-06-26 13:52:56 +02:00
if good or good == None :
2018-03-23 15:27:37 +01:00
self . logger . debug ( " found request to %s " , prj )
2016-06-26 13:52:56 +02:00
return good
2018-03-23 15:27:37 +01:00
return False
2016-05-30 18:19:49 +02:00
2016-09-30 11:51:00 +02:00
def _check_project_and_request ( self , project , target_package , src_srcinfo ) :
2018-05-30 13:55:38 +02:00
good = self . _check_matching_srcmd5 ( project , target_package , src_srcinfo . verifymd5 )
2016-09-30 11:51:00 +02:00
if good :
return good
good = self . factory . _check_requests ( project , target_package , src_srcinfo . verifymd5 )
if good or good == None :
return good
return False
2016-05-30 18:19:49 +02:00
def check_one_request ( self , req ) :
2018-08-16 23:35:10 -05:00
config = Config . get ( self . apiurl , req . actions [ 0 ] . tgt_project )
2017-04-18 16:36:33 +02:00
self . needs_legal_review = False
2016-06-26 13:52:56 +02:00
self . needs_reviewteam = False
2016-09-26 11:16:30 +02:00
self . needs_release_manager = False
2016-06-26 13:52:56 +02:00
self . pending_factory_submission = False
2016-09-30 11:51:00 +02:00
self . source_in_factory = None
2018-03-27 09:28:44 +02:00
self . do_check_maintainer_review = not self . ibs
2016-12-06 17:00:32 +01:00
self . packages = { }
2016-05-30 18:19:49 +02:00
2016-09-26 11:16:30 +02:00
request_ok = ReviewBot . ReviewBot . check_one_request ( self , req )
2016-05-30 18:19:49 +02:00
2016-09-26 11:16:30 +02:00
self . logger . debug ( " review result: %s " , request_ok )
if self . pending_factory_submission :
self . logger . info ( " submission is waiting for a Factory request to complete " )
2017-02-15 21:15:27 -06:00
creator = req . get_creator ( )
bot_name = self . bot_name . lower ( )
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 ) )
2016-09-26 11:16:30 +02:00
elif self . source_in_factory :
2018-06-26 15:18:55 +02:00
self . logger . info ( " perfect. the submitted sources are in or accepted for Factory " )
2016-09-30 11:51:00 +02:00
elif self . source_in_factory == False :
2019-05-11 14:25:02 +02:00
self . logger . warning ( " the submitted sources are NOT in Factory " )
2016-09-26 11:16:30 +02:00
2016-09-30 11:51:00 +02:00
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 " )
2016-09-26 11:16:30 +02:00
2017-02-10 15:41:45 -06:00
if self . do_comments :
2016-09-30 11:51:00 +02:00
result = None
2016-09-26 11:16:30 +02:00
if request_ok is None :
state = ' seen '
elif request_ok :
2016-09-30 11:51:00 +02:00
state = ' done '
result = ' accepted '
2016-09-26 11:16:30 +02:00
else :
2016-09-30 11:51:00 +02:00
state = ' done '
result = ' declined '
2018-08-24 09:44:57 -05:00
2017-02-10 15:41:45 -06:00
self . comment_write ( state , result )
2016-09-26 11:16:30 +02:00
2017-04-18 16:45:03 +02:00
add_review_groups = [ ]
2016-09-30 11:51:00 +02:00
if self . needs_release_manager :
2018-03-07 14:47:03 -06:00
add_review_groups . append ( self . release_manager_group or
config . get ( self . override_group_key ) )
2016-09-30 11:51:00 +02:00
if self . needs_reviewteam :
2018-03-07 14:47:03 -06:00
add_review_groups . append ( self . review_team_group or
config . get ( ' review-team ' ) )
2017-04-18 16:36:33 +02:00
if self . needs_legal_review :
2018-03-07 14:47:03 -06:00
add_review_groups . append ( self . legal_review_group or
config . get ( ' legal-review-group ' ) )
2016-12-29 00:34:56 -06:00
if self . needs_check_source and self . check_source_group is not None :
2017-08-15 22:18:53 -05:00
add_review_groups . append ( self . check_source_group )
2017-04-18 16:45:03 +02:00
2017-08-15 22:18:53 -05:00
for group in add_review_groups :
2017-04-18 16:45:03 +02:00
if group is None :
continue
2017-04-18 16:57:21 +02:00
self . logger . info ( " {0} needs review by [ {1} ](/group/show/ {1} ) " . format ( req . reqid , group ) )
2017-08-25 13:06:28 +02:00
self . add_review ( req , by_group = group )
2016-12-29 00:34:56 -06:00
2016-09-26 11:16:30 +02:00
return request_ok
2016-05-30 18:19:49 +02:00
2016-09-30 11:51:00 +02:00
def check_action__default ( self , req , a ) :
self . needs_release_manager = True
2017-06-20 16:25:46 -05:00
return super ( Leaper , self ) . check_action__default ( req , a )
2016-09-30 11:51:00 +02:00
2016-05-30 18:19:49 +02:00
class CommandLineInterface ( ReviewBot . CommandLineInterface ) :
def __init__ ( self , * args , * * kwargs ) :
ReviewBot . CommandLineInterface . __init__ ( self , args , kwargs )
2017-01-02 02:34:13 -06:00
self . clazz = Leaper
2016-05-30 18:19:49 +02:00
def get_optparser ( self ) :
parser = ReviewBot . CommandLineInterface . get_optparser ( self )
2016-09-26 11:16:30 +02:00
parser . add_option ( " --no-comment " , dest = ' comment ' , action = " store_false " , default = True , help = " don ' t actually post comments to obs " )
2016-10-10 16:20:30 +02:00
parser . add_option ( " --manual-version-updates " , action = " store_true " , help = " release manager must approve version updates " )
parser . add_option ( " --manual-maintenance-updates " , action = " store_true " , help = " release manager must approve maintenance updates " )
2016-12-29 00:34:56 -06:00
parser . add_option ( " --check-source-group " , dest = " check_source_group " , metavar = " GROUP " , help = " group used by check_source.py bot which will be added as a reviewer should leaper checks pass " )
2018-03-07 14:47:03 -06:00
parser . add_option ( " --review-team-group " , dest = " review_team_group " , metavar = " GROUP " , help = " group used for package reviews " )
parser . add_option ( " --release-manager-group " , dest = " release_manager_group " , metavar = " GROUP " , help = " group used for release manager reviews " )
parser . add_option ( " --legal-review-group " , dest = " legal_review_group " , metavar = " GROUP " , help = " group used for legal reviews " )
2016-09-26 11:16:30 +02:00
2016-05-30 18:19:49 +02:00
return parser
def setup_checker ( self ) :
2017-01-02 02:34:13 -06:00
bot = ReviewBot . CommandLineInterface . setup_checker ( self )
2016-05-30 18:19:49 +02:00
2016-10-10 16:20:30 +02:00
if self . options . manual_version_updates :
bot . must_approve_version_updates = True
if self . options . manual_maintenance_updates :
bot . must_approve_maintenance_updates = True
2016-12-29 00:34:56 -06:00
if self . options . check_source_group :
bot . check_source_group = self . options . check_source_group
2017-03-15 17:16:30 +01:00
if self . options . review_team_group :
bot . review_team_group = self . options . review_team_group
2017-04-18 16:36:33 +02:00
if self . options . legal_review_group :
bot . legal_review_group = self . options . legal_review_group
2017-03-15 17:16:30 +01:00
if self . options . release_manager_group :
bot . release_manager_group = self . options . release_manager_group
2016-09-26 11:16:30 +02:00
bot . do_comments = self . options . comment
2016-05-30 18:19:49 +02:00
return bot
if __name__ == " __main__ " :
app = CommandLineInterface ( )
sys . exit ( app . main ( ) )