Jimmy Berry b25fda9b47 Provide ignore/unignore request staging commands.
It is not uncommon for a request to be in a pending state which requires
action beyond the scope of the staging workflow, but does not make sense
to deny the request. For lack of a "postponed" or "pending" state on OBS
a sudo-state of "ignore" is provided for the staging workflow. The ignore
state will remove a request from the "list" and "adi" commands so as not
to be accidentally staged. This avoids the need for keeping a context of
what requests should be ignored in one's memory.

It is expected that an ignored request will have comments reflecting what
is to be done or one should be added via the -m option of ignore command.
2017-01-11 18:32:23 -06:00

156 lines
6.7 KiB
Python

import json
from osc import oscerr
from osc.core import delete_project
from osc.core import show_package_meta
from osclib.select_command import SelectCommand
from osclib.request_finder import RequestFinder
from xml.etree import cElementTree as ET
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 query_project, "still building"
return
if len(info['untracked_requests']):
print query_project, "untracked:", ', '.join(['%s[%s]'%(req['package'], req['number']) for req in info['untracked_requests']])
return
if len(info['obsolete_requests']):
print query_project, "obsolete:", ', '.join(['%s[%s]'%(req['package'], req['number']) for req in info['obsolete_requests']])
return
if len(info['broken_packages']):
print query_project, "broken:", ', '.join([p['package'] for p in info['broken_packages']])
return
for review in info['missing_reviews']:
print query_project, "missing review by {} for {}[{}]".format(review['by'], review['package'], review['request'])
return
if self.api.is_user_member_of(self.api.user, 'factory-staging'):
print query_project, "is ready"
for req in info['selected_requests']:
print " - %s [%s]"%(req['package'], req['number'])
self.api.rm_from_prj(project, request_id=req['number'], msg='ready to accept')
delete_project(self.api.apiurl, project)
else:
print query_project, "ready:", ', '.join(['%s[%s]'%(req['package'], req['number']) for req in info['selected_requests']])
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, by_dp=False, split=False):
all_requests = self.api.get_open_requests()
non_ring_packages = []
non_ring_requests = dict()
non_ring_requests_ignored = []
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
if len(wanted_requests):
source_project = 'wanted'
else:
source = action.find('source')
if source is not None:
source_project = source.get('project')
else:
source_project = 'none'
# do not process the rest request type than submit
if action.get('type') != 'submit':
continue
target_package = action.find('target').get('package')
source_package = action.find('source').get('package')
if not self.api.ring_packages.get(target_package):
# Auto-superseding request in adi command
if self.api.update_superseded_request(request):
continue
if not len(wanted_requests) and request_id in self.requests_ignored:
non_ring_requests_ignored.append(request_id)
continue
non_ring_packages.append(target_package)
if split:
# request_id pretended to be index of non_ring_requests
non_ring_requests[request_id] = [request_id]
else:
if by_dp:
devel_project = self.api.get_devel_project(source_project, source_package)
# try target pacakge in Factory
# this is a bit against Leap development in case submissions is from Update,
# or any other project than Factory
if devel_project is None and self.api.project.startswith('openSUSE:'):
devel_project = self.api.get_devel_project('openSUSE:Factory', target_package)
if devel_project is not None:
source_project = devel_project
if source_project not in non_ring_requests:
non_ring_requests[source_project] = []
non_ring_requests[source_project].append(request_id)
if len(non_ring_requests_ignored):
print "Not in a ring, but ignored:"
for request_id in non_ring_requests_ignored:
print "- sr#{}: {}".format(request_id, requests_ignored[request_id])
if len(non_ring_packages):
print "Not in a ring:", ' '.join(sorted(non_ring_packages))
else:
return
for source_project, requests in non_ring_requests.items():
name = self.api.create_adi_project(None)
for request in 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, move=False, by_dp=False, split=False):
"""
Perform the list command
"""
self.requests_ignored = self.api.get_ignored_requests()
if len(packages):
requests = set()
if move:
items = RequestFinder.find_staged_sr(packages, self.api).items()
print items
for request, request_project in items:
staging_project = request_project['staging']
self.api.rm_from_prj(staging_project, request_id=request)
self.api.add_review(request, by_group=self.api.cstaging_group, msg='Please recheck')
else:
items = RequestFinder.find_sr(packages, self.api).items()
for request, request_project in items:
requests.add(request)
self.create_new_adi(requests, split=split)
else:
self.check_adi_projects()
if self.api.is_user_member_of(self.api.user, 'factory-staging'):
self.create_new_adi((), by_dp=by_dp, split=split)