Merge pull request #372 from openSUSE/coolo_adi
add adi command to create an ad interim staging prj for all non-ring …
This commit is contained in:
commit
1253661500
@ -35,6 +35,7 @@ from osclib.obslock import OBSLock
|
||||
from osclib.select_command import SelectCommand
|
||||
from osclib.stagingapi import StagingAPI
|
||||
from osclib.unselect_command import UnselectCommand
|
||||
from osclib.adi_command import AdiCommand
|
||||
|
||||
OSC_STAGING_VERSION = '0.0.1'
|
||||
|
||||
@ -121,6 +122,8 @@ def do_staging(self, subcmd, opts, *args):
|
||||
min_args = 2
|
||||
elif cmd == 'unselect':
|
||||
min_args, max_args = 1, None
|
||||
elif cmd == 'adi':
|
||||
min_args, max_args = None, None
|
||||
elif cmd in ('list', 'cleanup_rings'):
|
||||
min_args, max_args = 0, 0
|
||||
else:
|
||||
@ -162,9 +165,11 @@ def do_staging(self, subcmd, opts, *args):
|
||||
if opts.add:
|
||||
api.mark_additional_packages(tprj, [opts.add])
|
||||
else:
|
||||
SelectCommand(api).perform(tprj, args[2:], opts.move,
|
||||
SelectCommand(api, tprj).perform(args[2:], opts.move,
|
||||
opts.from_, opts.no_freeze)
|
||||
elif cmd == 'cleanup_rings':
|
||||
CleanupRings(api).perform()
|
||||
elif cmd == 'list':
|
||||
ListCommand(api).perform()
|
||||
elif cmd == 'adi':
|
||||
AdiCommand(api).perform(args[1:])
|
||||
|
95
osclib/adi_command.py
Normal file
95
osclib/adi_command.py
Normal file
@ -0,0 +1,95 @@
|
||||
import json
|
||||
|
||||
from osc import oscerr
|
||||
from osc.core import delete_project
|
||||
|
||||
from osclib.select_command import SelectCommand
|
||||
from osclib.request_finder import RequestFinder
|
||||
|
||||
class AdiCommand:
|
||||
def __init__(self, api):
|
||||
self.api = api
|
||||
|
||||
def check_adi_project(self, project):
|
||||
query_project = 'adi:' + project.split(':adi:')[1]
|
||||
query = {'format': 'json'}
|
||||
url = self.api.makeurl(('project', 'staging_projects', self.api.project,
|
||||
query_project), query=query)
|
||||
info = json.load(self.api.retried_GET(url))
|
||||
if len(info['building_repositories']):
|
||||
print project, "still building"
|
||||
return
|
||||
if len(info['broken_packages']):
|
||||
print "https://build.opensuse.org/project/show/{}".format(project), "has broken packages"
|
||||
return
|
||||
for review in info['missing_reviews']:
|
||||
print project, "has at least one missing review by", review['by'], "in", review['request']
|
||||
return
|
||||
if len(info['untracked_requests']) or len(info['obsolete_requests']):
|
||||
print project, "has inconsistent requests"
|
||||
return
|
||||
print project, "is ready"
|
||||
for req in info['selected_requests']:
|
||||
print req['id']
|
||||
self.api.rm_from_prj(project, request_id=req['id'], msg='ready to accept')
|
||||
delete_project(self.api.apiurl, project)
|
||||
|
||||
def check_adi_projects(self):
|
||||
for p in self.api.get_adi_projects():
|
||||
self.check_adi_project(p)
|
||||
|
||||
def create_new_adi(self, wanted_requests):
|
||||
all_requests = self.api.get_open_requests()
|
||||
|
||||
non_ring_packages = []
|
||||
non_ring_requests = []
|
||||
|
||||
for request in all_requests:
|
||||
# Consolidate all data from request
|
||||
request_id = int(request.get('id'))
|
||||
if len(wanted_requests) and request_id not in wanted_requests:
|
||||
continue
|
||||
action = request.findall('action')
|
||||
if not action:
|
||||
msg = 'Request {} has no action'.format(request_id)
|
||||
raise oscerr.WrongArgs(msg)
|
||||
# we care only about first action
|
||||
action = action[0]
|
||||
|
||||
# Where are we targeting the package
|
||||
target_package = action.find('target').get('package')
|
||||
|
||||
if not self.api.ring_packages.get(target_package):
|
||||
non_ring_packages.append(target_package)
|
||||
non_ring_requests.append(request_id)
|
||||
|
||||
if len(non_ring_packages):
|
||||
print "Not in a ring:", ' '.join(sorted(non_ring_packages))
|
||||
else:
|
||||
return
|
||||
|
||||
name = self.api.create_adi_project(None)
|
||||
|
||||
sc = SelectCommand(self.api, name)
|
||||
|
||||
for request in non_ring_requests:
|
||||
if not self.api.rq_to_prj(request, name):
|
||||
return False
|
||||
|
||||
# Notify everybody about the changes
|
||||
self.api.update_status_comments(name, 'select')
|
||||
|
||||
|
||||
def perform(self, packages):
|
||||
"""
|
||||
Perform the list command
|
||||
"""
|
||||
if len(packages):
|
||||
requests = set()
|
||||
for request, request_project in RequestFinder.find_sr(packages,
|
||||
self.api).items():
|
||||
requests.add(request)
|
||||
self.create_new_adi(requests)
|
||||
else:
|
||||
self.check_adi_projects()
|
||||
self.create_new_adi(())
|
@ -14,9 +14,10 @@ MOVE = 'move'
|
||||
|
||||
class SelectCommand(object):
|
||||
|
||||
def __init__(self, api):
|
||||
def __init__(self, api, target_project):
|
||||
self.api = api
|
||||
self.affected_projects = set()
|
||||
self.target_project = target_project
|
||||
|
||||
def _package(self, request):
|
||||
"""
|
||||
@ -103,7 +104,7 @@ class SelectCommand(object):
|
||||
else:
|
||||
raise oscerr.WrongArgs('Arguments for select are not correct.')
|
||||
|
||||
def perform(self, target_project, requests, move=False,
|
||||
def perform(self, requests, move=False,
|
||||
from_=None, no_freeze=False):
|
||||
"""
|
||||
Select package and move it accordingly by arguments
|
||||
@ -113,23 +114,25 @@ class SelectCommand(object):
|
||||
:param from_: location where from move the requests
|
||||
"""
|
||||
|
||||
if self.api.is_adi_project(self.target_project):
|
||||
no_freeze = True
|
||||
|
||||
# If the project is not frozen enough yet freeze it
|
||||
if not (no_freeze or self.api.prj_frozen_enough(target_project)):
|
||||
if not (no_freeze or self.api.prj_frozen_enough(self.target_project)):
|
||||
print('Freeze the prj first')
|
||||
return False
|
||||
# FreezeCommand(self.api).perform(target_project)
|
||||
self.target_project = target_project
|
||||
# FreezeCommand(self.api).perform(self.target_project)
|
||||
|
||||
for request in RequestFinder.find_sr(requests, self.api):
|
||||
if not self.select_request(request, move, from_):
|
||||
return False
|
||||
|
||||
# Notify everybody about the changes
|
||||
self.api.update_status_comments(target_project, 'select')
|
||||
self.api.update_status_comments(self.target_project, 'select')
|
||||
for fprj in self.affected_projects:
|
||||
self.api.update_status_comments(fprj, 'select')
|
||||
|
||||
# now make sure we enable the prj if the prj contains any ringed package
|
||||
self.api.build_switch_staging_project(target_project)
|
||||
self.api.build_switch_staging_project(self.target_project)
|
||||
|
||||
return True
|
||||
|
@ -246,14 +246,21 @@ class StagingAPI(object):
|
||||
projects.append(val.get('name'))
|
||||
return projects
|
||||
|
||||
def is_adi_project(self, p):
|
||||
return ':adi:' in p
|
||||
|
||||
# this function will crash if given a non-adi project name
|
||||
def extract_adi_number(self, p):
|
||||
return int(p.split(':adi:')[1])
|
||||
|
||||
def get_adi_projects(self):
|
||||
"""
|
||||
Get all current running ADI projects
|
||||
:return list of known ADI projects
|
||||
"""
|
||||
|
||||
projects = [p for p in self.get_staging_project() if ':adi:' in p]
|
||||
return projects
|
||||
projects = [p for p in self.get_staging_projects() if self.is_adi_project(p) ]
|
||||
return sorted(projects, key=lambda project: self.extract_adi_number(project))
|
||||
|
||||
def do_change_review_state(self, request_id, newstate, message=None,
|
||||
by_group=None, by_user=None, by_project=None):
|
||||
@ -745,7 +752,7 @@ class StagingAPI(object):
|
||||
# The force_enable_build will avoid the
|
||||
# map_ring_package_to_subproject
|
||||
if not force_enable_build:
|
||||
if self.crings and not self.ring_packages.get(tar_pkg):
|
||||
if self.crings and not self.ring_packages.get(tar_pkg) and not self.is_adi_project(project):
|
||||
disable_build = True
|
||||
else:
|
||||
project = self.map_ring_package_to_subject(project, tar_pkg)
|
||||
@ -1092,10 +1099,14 @@ class StagingAPI(object):
|
||||
|
||||
def _candidate_adi_project(self):
|
||||
"""Decide a candidate name for an ADI project."""
|
||||
adi_projects = sorted(self.get_adi_projects())
|
||||
adi_projects = self.get_adi_projects()
|
||||
adi_index = 1
|
||||
for i, project in enumerate(adi_projects):
|
||||
if not project.endswith(i):
|
||||
return self.adi_prj_from_number(i)
|
||||
adi_index = i + 1
|
||||
if not project.endswith(str(adi_index)):
|
||||
return self.adi_prj_from_number(adi_index)
|
||||
adi_index = i + 2
|
||||
return self.adi_prj_from_number(adi_index)
|
||||
|
||||
def create_adi_project(self, name):
|
||||
"""Create an ADI project."""
|
||||
@ -1123,5 +1134,9 @@ class StagingAPI(object):
|
||||
<arch>x86_64</arch>
|
||||
</repository>
|
||||
</project>""".format(name, self.project)
|
||||
url = ""
|
||||
url = make_meta_url('prj', name, self.apiurl)
|
||||
http_PUT(url, data=meta)
|
||||
# put twice because on first put, the API adds useless maintainer
|
||||
http_PUT(url, data=meta)
|
||||
|
||||
return name
|
||||
|
@ -38,7 +38,7 @@ class TestSelect(unittest.TestCase):
|
||||
def test_old_frozen(self):
|
||||
self.assertEqual(self.api.prj_frozen_enough('openSUSE:Factory:Staging:A'), False)
|
||||
# check it won't allow selecting
|
||||
self.assertEqual(False, SelectCommand(self.api).perform('openSUSE:Factory:Staging:A', ['gcc']))
|
||||
self.assertEqual(False, SelectCommand(self.api, 'openSUSE:Factory:Staging:A').perform(['gcc']))
|
||||
|
||||
def test_select_comments(self):
|
||||
c_api = CommentAPI(self.api.apiurl)
|
||||
@ -46,7 +46,7 @@ class TestSelect(unittest.TestCase):
|
||||
comments = c_api.get_comments(project_name=staging_b)
|
||||
|
||||
# First select
|
||||
self.assertEqual(True, SelectCommand(self.api).perform(staging_b, ['gcc', 'wine']))
|
||||
self.assertEqual(True, SelectCommand(self.api, staging_b).perform(['gcc', 'wine']))
|
||||
first_select_comments = c_api.get_comments(project_name=staging_b)
|
||||
last_id = sorted(first_select_comments.keys())[-1]
|
||||
first_select_comment = first_select_comments[last_id]
|
||||
@ -56,7 +56,7 @@ class TestSelect(unittest.TestCase):
|
||||
self.assertTrue('Request#123 for package gcc submitted by @Admin' in first_select_comment['comment'])
|
||||
|
||||
# Second select
|
||||
self.assertEqual(True, SelectCommand(self.api).perform(staging_b, ['puppet']))
|
||||
self.assertEqual(True, SelectCommand(self.api, staging_b).perform(['puppet']))
|
||||
second_select_comments = c_api.get_comments(project_name=staging_b)
|
||||
last_id = sorted(second_select_comments.keys())[-1]
|
||||
second_select_comment = second_select_comments[last_id]
|
||||
@ -70,11 +70,11 @@ class TestSelect(unittest.TestCase):
|
||||
def test_no_matches(self):
|
||||
# search for requests
|
||||
with self.assertRaises(oscerr.WrongArgs) as cm:
|
||||
SelectCommand(self.api).perform('openSUSE:Factory:Staging:B', ['bash'])
|
||||
SelectCommand(self.api, 'openSUSE:Factory:Staging:B').perform(['bash'])
|
||||
self.assertEqual(str(cm.exception), "No SR# found for: bash")
|
||||
|
||||
def test_selected(self):
|
||||
# make sure the project is frozen recently for other tests
|
||||
|
||||
ret = SelectCommand(self.api).perform('openSUSE:Factory:Staging:B', ['wine'])
|
||||
ret = SelectCommand(self.api, 'openSUSE:Factory:Staging:B').perform(['wine'])
|
||||
self.assertEqual(True, ret)
|
||||
|
Loading…
x
Reference in New Issue
Block a user