Merge pull request #303 from aplanas/master

Add a test for accept command when there are multiple SPECs
This commit is contained in:
Stephan Kulow 2015-03-05 12:54:31 +01:00
commit acb862db43
13 changed files with 112 additions and 17 deletions

View File

@ -109,7 +109,10 @@ def _check_repo_download(self, request):
_errors_printed = set() _errors_printed = set()
def _check_repo_group(self, id_, requests, debug=False): def _check_repo_group(self, id_, requests, skip_cycle=None, debug=False):
if skip_cycle is None:
skip_cycle = []
print '> Check group [%s]' % ', '.join(r.str_compact() for r in requests) print '> Check group [%s]' % ', '.join(r.str_compact() for r in requests)
# XXX TODO - If the requests comes from command line, the group is # XXX TODO - If the requests comes from command line, the group is
@ -198,6 +201,14 @@ def _check_repo_group(self, id_, requests, debug=False):
print print
print ' - New cycle detected:', sorted(cycle) print ' - New cycle detected:', sorted(cycle)
print ' - New edges:', new_edges print ' - New edges:', new_edges
if skip_cycle:
print ' - Skiping this cycle and moving to the next check.'
continue
else:
print ' - If you want to skip this cycle, run manually the ' \
'check repo with -c / --skipcycle option.'
for request in requests: for request in requests:
request.updated = True request.updated = True
@ -428,6 +439,7 @@ def _print_request_and_specs(self, request_and_specs):
@cmdln.option('-p', '--project', dest='project', metavar='PROJECT', default='Factory', @cmdln.option('-p', '--project', dest='project', metavar='PROJECT', default='Factory',
help='select a different project instead of openSUSE:Factory') help='select a different project instead of openSUSE:Factory')
@cmdln.option('-s', '--skip', action='store_true', help='skip review') @cmdln.option('-s', '--skip', action='store_true', help='skip review')
@cmdln.option('-c', '--skipcycle', action='store_true', help='skip cycle check')
@cmdln.option('-n', '--dry', action='store_true', help='dry run, don\'t change review state') @cmdln.option('-n', '--dry', action='store_true', help='dry run, don\'t change review state')
@cmdln.option('-v', '--verbose', action='store_true', help='verbose output') @cmdln.option('-v', '--verbose', action='store_true', help='verbose output')
def do_check_repo(self, subcmd, opts, *args): def do_check_repo(self, subcmd, opts, *args):
@ -542,7 +554,9 @@ def do_check_repo(self, subcmd, opts, *args):
# projects also # projects also
for id_, reqs in sorted(groups.items(), reverse=True): for id_, reqs in sorted(groups.items(), reverse=True):
try: try:
self._check_repo_group(id_, reqs, debug=opts.verbose) self._check_repo_group(id_, reqs,
skip_cycle=opts.skipcycle,
debug=opts.verbose)
except Exception as e: except Exception as e:
print 'ERROR -- An exception happends while checking a group [%s]' % e print 'ERROR -- An exception happends while checking a group [%s]' % e
if conf.config['debug']: if conf.config['debug']:

View File

@ -57,7 +57,7 @@ def _full_project_name(self, project):
return 'SUSE:%s' % project return 'SUSE:%s' % project
# If we can't guess, raise a Warning # If we can't guess, raise a Warning
warnings.warn('% project not recognized.' % project) warnings.warn('%s project not recognized.' % project)
return project return project

View File

@ -1,4 +1,5 @@
import re import re
import urllib2
import warnings import warnings
from xml.etree import cElementTree as ET from xml.etree import cElementTree as ET
@ -33,7 +34,7 @@ class AcceptCommand(object):
return rqs return rqs
def perform(self, project): def perform(self, project):
"""Accept the staging LETTER for review and submit to Factory / """Accept the staging project for review and submit to Factory /
openSUSE 13.2 ... openSUSE 13.2 ...
Then disable the build to disabled Then disable the build to disabled
@ -57,15 +58,23 @@ class AcceptCommand(object):
msg = 'Accepting staging review for {}'.format(req['package']) msg = 'Accepting staging review for {}'.format(req['package'])
print(msg) print(msg)
oldspecs = self.api.get_filelist_for_package(pkgname=req['package'], project=self.api.project, extension='spec') oldspecs = self.api.get_filelist_for_package(pkgname=req['package'],
change_request_state(self.api.apiurl, str(req['id']), 'accepted', message='Accept to %s' % self.api.project) project=self.api.project,
extension='spec')
change_request_state(self.api.apiurl,
str(req['id']),
'accepted',
message='Accept to %s' % self.api.project)
self.create_new_links(self.api.project, req['package'], oldspecs) self.create_new_links(self.api.project, req['package'], oldspecs)
# A single comment should be enough to notify everybody, since # A single comment should be enough to notify everybody, since
# they are already mentioned in the comments created by # they are already mentioned in the comments created by
# select/unselect # select/unselect
pkg_list = ", ".join(packages) pkg_list = ", ".join(packages)
cmmt = 'Project "{}" accepted. The following packages have been submitted to {}: {}.'.format(project, self.api.project, pkg_list) cmmt = 'Project "{}" accepted.' \
' The following packages have been submitted to {}: {}.'.format(project,
self.api.project,
pkg_list)
self.comment.add_comment(project_name=project, comment=cmmt) self.comment.add_comment(project_name=project, comment=cmmt)
# XXX CAUTION - AFAIK the 'accept' command is expected to clean the messages here. # XXX CAUTION - AFAIK the 'accept' command is expected to clean the messages here.
@ -113,7 +122,7 @@ class AcceptCommand(object):
# There is more than one .spec file in the package; link package containers as needed # There is more than one .spec file in the package; link package containers as needed
origmeta = self.api.load_file_content(project, pkgname, '_meta') origmeta = self.api.load_file_content(project, pkgname, '_meta')
for specfile in filelist: for specfile in filelist:
package = specfile[:-5] # stripping .spec off the filename gives the packagename package = specfile[:-5] # stripping .spec off the filename gives the packagename
if package == pkgname: if package == pkgname:
# This is the original package and does not need to be linked to itself # This is the original package and does not need to be linked to itself
continue continue
@ -121,10 +130,18 @@ class AcceptCommand(object):
if not self.api.item_exists(project, package): if not self.api.item_exists(project, package):
print "Creating new package %s linked to %s" % (package, pkgname) print "Creating new package %s linked to %s" % (package, pkgname)
# new package does not exist. Let's link it with new metadata # new package does not exist. Let's link it with new metadata
newmeta = re.sub(r'(<package.*name=.){}'.format(pkgname),r'\1{}'.format(package), origmeta) newmeta = re.sub(r'(<package.*name=.){}'.format(pkgname),
newmeta = re.sub(r'<devel.*>\$',r'<devel package=\'{}\'/>'.format(pkgname), newmeta) r'\1{}'.format(package),
newmeta = re.sub(r'<bcntsynctag>.*</bcntsynctag>',r'', newmeta) origmeta)
newmeta = re.sub(r'</package>',r'<bcntsynctag>{}</bcntsynctag></package>'.format(pkgname), newmeta) newmeta = re.sub(r'<devel.*>\$',
r'<devel package=\'{}\'/>'.format(pkgname),
newmeta)
newmeta = re.sub(r'<bcntsynctag>.*</bcntsynctag>',
r'',
newmeta)
newmeta = re.sub(r'</package>',
r'<bcntsynctag>{}</bcntsynctag></package>'.format(pkgname),
newmeta)
self.api.save_file_content(project, package, '_meta', newmeta) self.api.save_file_content(project, package, '_meta', newmeta)
link = "<link package=\"{}\" cicount=\"copy\" />".format(pkgname) link = "<link package=\"{}\" cicount=\"copy\" />".format(pkgname)
self.api.save_file_content(project, package, '_link', link) self.api.save_file_content(project, package, '_link', link)

View File

@ -51,7 +51,7 @@ DEFAULT = {
'openqa': None, 'openqa': None,
'lock': None, 'lock': None,
'lock-ns': 'OBS', 'lock-ns': 'OBS',
} },
} }
# #

View File

@ -293,7 +293,7 @@ class CycleDetector(object):
# #
# To do that, we store in `project_cycles_pkgs` all the # To do that, we store in `project_cycles_pkgs` all the
# project (i.e Factory) cycles as a set of packages, so we can # project (i.e Factory) cycles as a set of packages, so we can
# check in the new cycle (also as a set of package) is # check if the new cycle (also as a set of packages) is
# included here. # included here.
project_cycles_pkgs = [set(cycle) for cycle in project_cycles] project_cycles_pkgs = [set(cycle) for cycle in project_cycles]
for cycle in current_graph.cycles(): for cycle in current_graph.cycles():

View File

@ -84,7 +84,7 @@ class OBSLock(object):
now = datetime.utcnow() now = datetime.utcnow()
if now < ts: if now < ts:
raise Exception('Lock acquired from the future [%s] by [%s]. Try later.' % (ts, user)) raise Exception('Lock acquired from the future [%s] by [%s]. Try later.' % (ts, user))
if user != self.user and (now - ts).seconds < self.ttl: if (now - ts).seconds < self.ttl:
print 'Lock acquired by [%s]. Try later.' % user print 'Lock acquired by [%s]. Try later.' % user
exit(-1) exit(-1)
# raise Exception('Lock acquired by [%s]. Try later.' % user) # raise Exception('Lock acquired by [%s]. Try later.' % user)

View File

@ -58,6 +58,7 @@ class StagingAPI(object):
self.copenqa = conf.config[project]['openqa'] self.copenqa = conf.config[project]['openqa']
# If the project support rings, inititialize some variables. # If the project support rings, inititialize some variables.
self.ring_packages = {}
if self.crings: if self.crings:
self.rings = ( self.rings = (
'{}:0-Bootstrap'.format(self.crings), '{}:0-Bootstrap'.format(self.crings),

View File

@ -0,0 +1,11 @@
<package name="apparmor-doc" project="openSUSE:Factory">
<title>AppArmor userlevel parser utility</title>
<description>
The AppArmor Parser is a userlevel program that is used to load in
program profiles to the AppArmor Security kernel module.
This package is part of a suite of tools that used to be named
SubDomain.
</description>
<devel project="security:apparmor" package="apparmor-doc"/>
</package>

View File

@ -0,0 +1 @@
<entry name="${spec}" md5="84ae6c8586c7e12b44d835af641d6a74" size="27360" mtime="1423765380"/>

View File

@ -0,0 +1,11 @@
<package name="apparmor" project="openSUSE:Factory">
<title>AppArmor userlevel parser utility</title>
<description>
The AppArmor Parser is a userlevel program that is used to load in
program profiles to the AppArmor Security kernel module.
This package is part of a suite of tools that used to be named
SubDomain.
</description>
<devel project="security:apparmor" package="apparmor"/>
</package>

View File

@ -0,0 +1,3 @@
<directory name="apparmor" rev="82" vrev="4" srcmd5="4120eb2ba3d265f7dceb65bbd5923d76">
${entries}
</directory>

View File

@ -0,0 +1,3 @@
<directory name="emacs" rev="113" vrev="4" srcmd5="e894cd3965cf1d930a5c058a82a6040e">
<entry name="emacs.spec" md5="320973b1eb3eaee437e0f882163c2819" size="237405" mtime="1423338472"/>
</directory>

View File

@ -367,10 +367,20 @@ class OBS(object):
'openSUSE:Factory:Staging:J': [], 'openSUSE:Factory:Staging:J': [],
} }
# To track comments created during test execution, even if they have # To track comments created during test execution, even if
# been deleted afterward # they have been deleted afterward
self.comment_bodies = [] self.comment_bodies = []
# Different spec files stored in some openSUSE:Factory
# projects
self.spec_list = {
'openSUSE:Factory/apparmor': [
{
'spec': 'apparmor.spec',
}
],
}
# #
# /request/ # /request/
# #
@ -560,6 +570,30 @@ class OBS(object):
return response return response
@GET(re.compile(r'/source/openSUSE:Factory/apparmor$'))
def source_project_apparmor(self, request, uri, headers):
"""Return apparmor spec list."""
package = re.search(r'/source/([\w:]+/\w+)', uri).group(1)
response = (404, headers, '<result>Not found</result>')
try:
template = string.Template(self._fixture(uri, filename='apparmor.xml'))
entry_template = string.Template(self._fixture(uri, filename='_entry.xml'))
entries = ''.join(entry_template.substitute(entry) for entry in self.spec_list[package])
response = (200, headers, template.substitute({'entries': entries}))
# The next call len() will be 2
if len(self.spec_list[package]) == 1:
self.spec_list[package].append({'spec': 'apparmor-doc.spec'})
except Exception as e:
if DEBUG:
print uri, e
if DEBUG:
print 'SOURCE APPARMOR', uri, response
return response
@GET(re.compile(r'/source/home:Admin/\w+')) @GET(re.compile(r'/source/home:Admin/\w+'))
def source_project(self, request, uri, headers): def source_project(self, request, uri, headers):
"""Return information of a source package.""" """Return information of a source package."""