Merge pull request #2626 from ancorgs/obslocal_refactor
Small OBSLocal refactoring
This commit is contained in:
commit
57abe5728b
@ -29,6 +29,8 @@ from osclib.memoize import memoize_session_reset
|
|||||||
|
|
||||||
from urllib.error import HTTPError, URLError
|
from urllib.error import HTTPError, URLError
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
# pointing to other docker container
|
# pointing to other docker container
|
||||||
APIURL = 'http://api:3000'
|
APIURL = 'http://api:3000'
|
||||||
PROJECT = 'openSUSE:Factory'
|
PROJECT = 'openSUSE:Factory'
|
||||||
@ -41,6 +43,7 @@ class TestCase(unittest.TestCase):
|
|||||||
script_apiurl = True
|
script_apiurl = True
|
||||||
script_debug = True
|
script_debug = True
|
||||||
script_debug_osc = True
|
script_debug_osc = True
|
||||||
|
review_bots = {}
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
if os.path.exists(OSCCOOKIEJAR):
|
if os.path.exists(OSCCOOKIEJAR):
|
||||||
@ -105,6 +108,14 @@ class TestCase(unittest.TestCase):
|
|||||||
os.environ['OSRT_DISABLE_CACHE'] = 'true'
|
os.environ['OSRT_DISABLE_CACHE'] = 'true'
|
||||||
|
|
||||||
def execute_script(self, args):
|
def execute_script(self, args):
|
||||||
|
"""Executes the script stored in the ``script`` attribute of the current test.
|
||||||
|
|
||||||
|
If the attributes ``script_debug`` or ``script_debug_osc`` are set to true for the current
|
||||||
|
test, the function will add the corresponding ``--debug`` and/or ``--osc-debug`` argument
|
||||||
|
when invoking the script.
|
||||||
|
|
||||||
|
This function ensures the executed code is taken into account for the coverage calculation.
|
||||||
|
"""
|
||||||
if self.script:
|
if self.script:
|
||||||
args.insert(0, self.script)
|
args.insert(0, self.script)
|
||||||
if self.script_debug:
|
if self.script_debug:
|
||||||
@ -117,6 +128,18 @@ class TestCase(unittest.TestCase):
|
|||||||
|
|
||||||
self.execute(args)
|
self.execute(args)
|
||||||
|
|
||||||
|
def execute_review_script(self, request_id, user):
|
||||||
|
"""Executes the review bot that corresponds to the script pointed by the ``script``
|
||||||
|
attribute, targeting the given request and as the given user.
|
||||||
|
|
||||||
|
See :func:`execute_script`.
|
||||||
|
|
||||||
|
The script must follow the commandline syntax of a review bot.
|
||||||
|
"""
|
||||||
|
self.osc_user(user)
|
||||||
|
self.execute_script(['id', request_id])
|
||||||
|
self.osc_user_pop()
|
||||||
|
|
||||||
def execute_osc(self, args):
|
def execute_osc(self, args):
|
||||||
# The wrapper allows this to work properly when osc installed via pip.
|
# The wrapper allows this to work properly when osc installed via pip.
|
||||||
args.insert(0, 'osc-wrapper.py')
|
args.insert(0, 'osc-wrapper.py')
|
||||||
@ -137,6 +160,16 @@ class TestCase(unittest.TestCase):
|
|||||||
self.assertTrue(text in self.output, '[MISSING] ' + text)
|
self.assertTrue(text in self.output, '[MISSING] ' + text)
|
||||||
|
|
||||||
def assertReview(self, rid, **kwargs):
|
def assertReview(self, rid, **kwargs):
|
||||||
|
"""Asserts there is a review for the given request that is assigned to the given target
|
||||||
|
(user, group or project) and that is in the expected state.
|
||||||
|
|
||||||
|
For example, this asserts there is a new review for the user 'jdoe' in the request 20:
|
||||||
|
|
||||||
|
``assertReview(20, by_user=('jdoe', 'new'))``
|
||||||
|
|
||||||
|
:return: the found review, if the assertion succeeds
|
||||||
|
:rtype: Review or None
|
||||||
|
"""
|
||||||
request = get_request(self.apiurl, rid)
|
request = get_request(self.apiurl, rid)
|
||||||
for review in request.reviews:
|
for review in request.reviews:
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
@ -146,12 +179,30 @@ class TestCase(unittest.TestCase):
|
|||||||
|
|
||||||
self.fail('{} not found'.format(kwargs))
|
self.fail('{} not found'.format(kwargs))
|
||||||
|
|
||||||
def assertReviewBot(self, request_id, user, before, after, comment=None):
|
def assertReviewScript(self, request_id, user, before, after, comment=None):
|
||||||
|
"""Asserts the review script pointed by the ``script`` attribute of the current test can
|
||||||
|
be executed and it produces the expected change in the reviews of a request.
|
||||||
|
|
||||||
|
For this assertion to succeed the request must contain initially a review in the original
|
||||||
|
state targeting the given user, then the script will be executed and it will be asserted
|
||||||
|
that the request then has the final expected state (and, optionally, the expected comment).
|
||||||
|
|
||||||
|
See :func:`execute_review_script`.
|
||||||
|
|
||||||
|
:param request_id: request for which the script will be executed
|
||||||
|
:type request_id: int
|
||||||
|
:param user: target of the review, it will also be used to execute the script
|
||||||
|
:type user: str
|
||||||
|
:param before: expected state of the review before executing the script
|
||||||
|
:type before: str
|
||||||
|
:param before: expected state of the review after executing the script
|
||||||
|
:type before: str
|
||||||
|
:param comment: expected message for the review after executing the script
|
||||||
|
:type comment: str
|
||||||
|
"""
|
||||||
self.assertReview(request_id, by_user=(user, before))
|
self.assertReview(request_id, by_user=(user, before))
|
||||||
|
|
||||||
self.osc_user(user)
|
self.execute_review_script(request_id, user)
|
||||||
self.execute_script(['id', request_id])
|
|
||||||
self.osc_user_pop()
|
|
||||||
|
|
||||||
review = self.assertReview(request_id, by_user=(user, after))
|
review = self.assertReview(request_id, by_user=(user, after))
|
||||||
if comment:
|
if comment:
|
||||||
@ -169,11 +220,48 @@ class TestCase(unittest.TestCase):
|
|||||||
length = 2
|
length = 2
|
||||||
return prefix + ''.join([random.choice(string.ascii_letters) for i in range(length)])
|
return prefix + ''.join([random.choice(string.ascii_letters) for i in range(length)])
|
||||||
|
|
||||||
|
def setup_review_bot(self, wf, project, user, bot_class):
|
||||||
|
"""Instantiates a bot for the given project, adding the associated user as reviewer.
|
||||||
|
|
||||||
class StagingWorkflow(object):
|
:param wf: workflow containing the project, users, etc.
|
||||||
"""This class is intended to setup and manipulate the environment (projects, users, etc.) in
|
:type wf: StagingWorkflow
|
||||||
the local OBS instance used to tests the release tools. It makes easy to setup scenarios similar
|
:param project: name of the project the bot will act on
|
||||||
to the ones used during the real (open)SUSE development, with staging projects, rings, etc.
|
:type project: str
|
||||||
|
:param user: user to create for the bot
|
||||||
|
:type user: str
|
||||||
|
:param bot_class: type of bot to setup
|
||||||
|
"""
|
||||||
|
wf.create_user(user)
|
||||||
|
prj = wf.projects[project]
|
||||||
|
prj.add_reviewers(users = [user])
|
||||||
|
|
||||||
|
bot_name = self.generate_bot_name(user)
|
||||||
|
bot = bot_class(wf.apiurl, user=user, logger=logging.getLogger(bot_name))
|
||||||
|
bot.bot_name = bot_name
|
||||||
|
|
||||||
|
self.review_bots[user] = bot
|
||||||
|
|
||||||
|
def execute_review_bot(self, requests, user):
|
||||||
|
"""Checks the given requests using the bot associated to the given user.
|
||||||
|
|
||||||
|
The bot must have been previously configured via :func:`setup_review_bot`.
|
||||||
|
"""
|
||||||
|
bot = self.review_bots[user]
|
||||||
|
bot.set_request_ids(requests)
|
||||||
|
|
||||||
|
self.osc_user(user)
|
||||||
|
bot.check_requests()
|
||||||
|
self.osc_user_pop()
|
||||||
|
|
||||||
|
def generate_bot_name(self, user):
|
||||||
|
"""Used to ensure different test runs operate in unique namespace."""
|
||||||
|
return '::'.join([type(self).__name__, user, str(random.getrandbits(8))])
|
||||||
|
|
||||||
|
class StagingWorkflow(ABC):
|
||||||
|
"""This abstract base class is intended to setup and manipulate the environment (projects,
|
||||||
|
users, etc.) in the local OBS instance used to tests the release tools. Thus, the derivative
|
||||||
|
classes make easy to setup scenarios similar to the ones used during the real (open)SUSE
|
||||||
|
development.
|
||||||
"""
|
"""
|
||||||
def __init__(self, project=PROJECT):
|
def __init__(self, project=PROJECT):
|
||||||
"""Initializes the configuration
|
"""Initializes the configuration
|
||||||
@ -195,7 +283,7 @@ class StagingWorkflow(object):
|
|||||||
self.requests = []
|
self.requests = []
|
||||||
self.groups = []
|
self.groups = []
|
||||||
self.users = []
|
self.users = []
|
||||||
self.attributes = {}
|
self.attr_types = {}
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
|
|
||||||
# clear cache from other tests - otherwise the VCR is replayed depending
|
# clear cache from other tests - otherwise the VCR is replayed depending
|
||||||
@ -215,15 +303,27 @@ class StagingWorkflow(object):
|
|||||||
Cache.CACHE_DIR = None
|
Cache.CACHE_DIR = None
|
||||||
Cache.PATTERNS = {}
|
Cache.PATTERNS = {}
|
||||||
Cache.init()
|
Cache.init()
|
||||||
|
# Note this implicitly calls create_target()
|
||||||
self.setup_remote_config()
|
self.setup_remote_config()
|
||||||
self.load_config()
|
self.load_config()
|
||||||
self.api = StagingAPI(APIURL, project)
|
self.api = StagingAPI(APIURL, project)
|
||||||
# The ProductVersion is required for some actions, for example, when a request is accepted
|
|
||||||
self.create_attribute_type('OSRT', 'ProductVersion', 1)
|
@abstractmethod
|
||||||
|
def initial_config(self):
|
||||||
|
"""Values to use to initialize the 'Config' attribute at :func:`setup_remote_config`"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def staging_group_name(self):
|
||||||
|
"""Name of the group in charge of the staging workflow"""
|
||||||
|
pass
|
||||||
|
|
||||||
def load_config(self, project=None):
|
def load_config(self, project=None):
|
||||||
"""Loads the corresponding :class:`osclib.Config` object into the attribute ``config``
|
"""Loads the corresponding :class:`osclib.Config` object into the attribute ``config``
|
||||||
|
|
||||||
|
Such an object represents the set of values stored on the attribute 'Config' of the
|
||||||
|
target project. See :func:`remote_config_set`.
|
||||||
|
|
||||||
:param project: target project name
|
:param project: target project name
|
||||||
:type project: str
|
:type project: str
|
||||||
"""
|
"""
|
||||||
@ -233,9 +333,11 @@ class StagingWorkflow(object):
|
|||||||
self.config = Config(APIURL, project)
|
self.config = Config(APIURL, project)
|
||||||
|
|
||||||
def create_attribute_type(self, namespace, name, values=None):
|
def create_attribute_type(self, namespace, name, values=None):
|
||||||
if not namespace in self.attributes: self.attributes[namespace] = []
|
"""Creates a new attribute type in the OBS instance."""
|
||||||
|
|
||||||
if not name in self.attributes[namespace]: self.attributes[namespace].append(name)
|
if not namespace in self.attr_types: self.attr_types[namespace] = []
|
||||||
|
|
||||||
|
if not name in self.attr_types[namespace]: self.attr_types[namespace].append(name)
|
||||||
|
|
||||||
meta = """
|
meta = """
|
||||||
<namespace name='{}'>
|
<namespace name='{}'>
|
||||||
@ -252,17 +354,31 @@ class StagingWorkflow(object):
|
|||||||
osc.core.http_PUT(url, data=meta)
|
osc.core.http_PUT(url, data=meta)
|
||||||
|
|
||||||
def setup_remote_config(self):
|
def setup_remote_config(self):
|
||||||
|
"""Creates the attribute 'Config' for the target project, with proper initial content.
|
||||||
|
|
||||||
|
See :func:`remote_config_set` for more information about that attribute.
|
||||||
|
|
||||||
|
Note this calls :func:`create_target` to ensure the target project exists.
|
||||||
|
"""
|
||||||
|
# First ensure the existence of both the target project and the 'Config' attribute type
|
||||||
self.create_target()
|
self.create_target()
|
||||||
self.create_attribute_type('OSRT', 'Config', 1)
|
self.create_attribute_type('OSRT', 'Config', 1)
|
||||||
|
|
||||||
config = {
|
self.remote_config_set(self.initial_config(), replace_all=True)
|
||||||
'overridden-by-local': 'remote-nope',
|
|
||||||
'staging-group': 'factory-staging',
|
|
||||||
'remote-only': 'remote-indeed',
|
|
||||||
}
|
|
||||||
self.remote_config_set(config, replace_all=True)
|
|
||||||
|
|
||||||
def remote_config_set(self, config, replace_all=False):
|
def remote_config_set(self, config, replace_all=False):
|
||||||
|
"""Sets the values of the 'Config' attribute for the target project.
|
||||||
|
|
||||||
|
That attribute stores a set of values that are useful to influence the behavior of several
|
||||||
|
tools and bots in the context of the given project. For convenience, such a collection of
|
||||||
|
values is usually accessed using a :class:`osclib.Config` object. See :func:`load_config`.
|
||||||
|
|
||||||
|
:param config: values to write into the attribute
|
||||||
|
:type config: dict[str, str]
|
||||||
|
:param replace_all: whether the previous content of 'Config' should be cleared up
|
||||||
|
:type replace_all: bool
|
||||||
|
"""
|
||||||
|
|
||||||
if not replace_all:
|
if not replace_all:
|
||||||
config_existing = Config.get(self.apiurl, self.project)
|
config_existing = Config.get(self.apiurl, self.project)
|
||||||
config_existing.update(config)
|
config_existing.update(config)
|
||||||
@ -331,50 +447,31 @@ class StagingWorkflow(object):
|
|||||||
self.projects[home_project] = Project(home_project, create=False)
|
self.projects[home_project] = Project(home_project, create=False)
|
||||||
|
|
||||||
def create_target(self):
|
def create_target(self):
|
||||||
"""Creates
|
"""Creates the main project that represents the product being developed and, as such, is
|
||||||
|
expected to be the target for requests. It also creates all the associated projects, users
|
||||||
|
and groups involved in the development workflow.
|
||||||
|
|
||||||
- target project
|
In the base implementation, that includes:
|
||||||
- "staging-bot" user
|
|
||||||
- "factory-staging" group
|
|
||||||
|
|
||||||
setup staging and also ``*:Staging:A`` and ``*:Staging:B`` projects.
|
- The target project (see :func:`create_target_project`)
|
||||||
|
- A group of staging managers including the "staging-bot" user
|
||||||
|
(see :func:`create_staging_users`)
|
||||||
|
- A couple of staging projects for the target one
|
||||||
|
- The ProductVersion attribute type, that is used by the staging tools
|
||||||
|
|
||||||
After the execution, the target project is indexed in the projects dictionary twice,
|
After the execution, the target project is indexed in the projects dictionary twice,
|
||||||
by its name and as 'target'.
|
by its name and as 'target'.
|
||||||
"""
|
"""
|
||||||
if self.projects.get('target'): return
|
if self.projects.get('target'): return
|
||||||
self.create_user('staging-bot')
|
|
||||||
self.create_group('factory-staging', users=['staging-bot'])
|
|
||||||
p = Project(name=self.project, reviewer={'groups': ['factory-staging']})
|
|
||||||
self.projects['target'] = p
|
|
||||||
self.projects[self.project] = p
|
|
||||||
|
|
||||||
url = osc.core.makeurl(APIURL, ['staging', self.project, 'workflow'])
|
self.create_target_project()
|
||||||
data = "<workflow managers='factory-staging'/>"
|
self.create_staging_users()
|
||||||
osc.core.http_POST(url, data=data)
|
|
||||||
# creates A and B as well
|
|
||||||
self.projects['staging:A'] = Project(self.project + ':Staging:A', create=False)
|
self.projects['staging:A'] = Project(self.project + ':Staging:A', create=False)
|
||||||
self.projects['staging:B'] = Project(self.project + ':Staging:B', create=False)
|
self.projects['staging:B'] = Project(self.project + ':Staging:B', create=False)
|
||||||
|
|
||||||
def setup_rings(self, devel_project=None):
|
# The ProductVersion is required for some actions, like accepting a staging project
|
||||||
"""Creates a typical Factory setup with rings.
|
self.create_attribute_type('OSRT', 'ProductVersion', 1)
|
||||||
|
|
||||||
It creates three projects: 'ring0', 'ring1' and the target (see :func:`create_target`).
|
|
||||||
It also creates a 'wine' package in the target project and a link from it to ring1.
|
|
||||||
It sets the devel project for the package if ``devel_project`` is given.
|
|
||||||
|
|
||||||
:param devel_project: name of devel project. It must exist and contain a 'wine' package,
|
|
||||||
otherwise OBS returns an error code.
|
|
||||||
:type devel_project: str or None
|
|
||||||
"""
|
|
||||||
self.create_target()
|
|
||||||
self.projects['ring0'] = Project(name=self.project + ':Rings:0-Bootstrap')
|
|
||||||
self.projects['ring1'] = Project(name=self.project + ':Rings:1-MinimalX')
|
|
||||||
target_wine = Package(
|
|
||||||
name='wine', project=self.projects['target'], devel_project=devel_project
|
|
||||||
)
|
|
||||||
target_wine.create_commit()
|
|
||||||
self.create_link(target_wine, self.projects['ring1'])
|
|
||||||
|
|
||||||
def create_package(self, project, package):
|
def create_package(self, project, package):
|
||||||
project = self.create_project(project)
|
project = self.create_project(project)
|
||||||
@ -452,32 +549,6 @@ class StagingWorkflow(object):
|
|||||||
package.create_commit(text=text)
|
package.create_commit(text=text)
|
||||||
return self.submit_package(package)
|
return self.submit_package(package)
|
||||||
|
|
||||||
def create_staging(self, suffix, freeze=False, rings=None, with_repo=False):
|
|
||||||
staging_key = 'staging:{}'.format(suffix)
|
|
||||||
# do not reattach if already present
|
|
||||||
if not staging_key in self.projects:
|
|
||||||
staging_name = self.project + ':Staging:' + suffix
|
|
||||||
staging = Project(staging_name, create=False, with_repo=with_repo)
|
|
||||||
url = osc.core.makeurl(APIURL, ['staging', self.project, 'staging_projects'])
|
|
||||||
data = '<workflow><staging_project>{}</staging_project></workflow>'
|
|
||||||
osc.core.http_POST(url, data=data.format(staging_name))
|
|
||||||
self.projects[staging_key] = staging
|
|
||||||
else:
|
|
||||||
staging = self.projects[staging_key]
|
|
||||||
|
|
||||||
project_links = []
|
|
||||||
if rings == 0:
|
|
||||||
project_links.append(self.project + ":Rings:0-Bootstrap")
|
|
||||||
if rings == 1 or rings == 0:
|
|
||||||
project_links.append(self.project + ":Rings:1-MinimalX")
|
|
||||||
staging.update_meta(project_links=project_links, maintainer={'groups': ['factory-staging']},
|
|
||||||
with_repo=with_repo)
|
|
||||||
|
|
||||||
if freeze:
|
|
||||||
FreezeCommand(self.api).perform(staging.name)
|
|
||||||
|
|
||||||
return staging
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if not self.api:
|
if not self.api:
|
||||||
return
|
return
|
||||||
@ -498,8 +569,8 @@ class StagingWorkflow(object):
|
|||||||
request.revoke()
|
request.revoke()
|
||||||
for group in self.groups:
|
for group in self.groups:
|
||||||
self.remove_group(group)
|
self.remove_group(group)
|
||||||
for namespace in self.attributes:
|
for namespace in self.attr_types:
|
||||||
self.remove_attributes(namespace)
|
self.remove_attribute_types(namespace)
|
||||||
|
|
||||||
print('done')
|
print('done')
|
||||||
|
|
||||||
@ -516,14 +587,14 @@ class StagingWorkflow(object):
|
|||||||
url = osc.core.makeurl(APIURL, ['group', group])
|
url = osc.core.makeurl(APIURL, ['group', group])
|
||||||
self._safe_delete(url)
|
self._safe_delete(url)
|
||||||
|
|
||||||
def remove_attributes(self, namespace):
|
def remove_attribute_types(self, namespace):
|
||||||
"""Removes an attributes namespace and all the attributes it contains
|
"""Removes an attributes namespace and all the attribute types it contains
|
||||||
|
|
||||||
:param namespace: attributes namespace to remove
|
:param namespace: attributes namespace to remove
|
||||||
:type namespace: str
|
:type namespace: str
|
||||||
"""
|
"""
|
||||||
for name in self.attributes[namespace]:
|
for name in self.attr_types[namespace]:
|
||||||
print('deleting attribute {}:{}'.format(namespace, name))
|
print('deleting attribute type {}:{}'.format(namespace, name))
|
||||||
url = osc.core.makeurl(APIURL, ['attribute', namespace, name, '_meta'])
|
url = osc.core.makeurl(APIURL, ['attribute', namespace, name, '_meta'])
|
||||||
self._safe_delete(url)
|
self._safe_delete(url)
|
||||||
print('deleting namespace', namespace)
|
print('deleting namespace', namespace)
|
||||||
@ -541,6 +612,88 @@ class StagingWorkflow(object):
|
|||||||
except HTTPError:
|
except HTTPError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def create_target_project(self):
|
||||||
|
"""Creates the main target project (see :func:`create_target`)"""
|
||||||
|
p = Project(name=self.project)
|
||||||
|
self.projects['target'] = p
|
||||||
|
self.projects[self.project] = p
|
||||||
|
|
||||||
|
def create_staging_users(self):
|
||||||
|
"""Creates users and groups for the staging workflow for the target project
|
||||||
|
(see :func:`create_target`)
|
||||||
|
"""
|
||||||
|
group = self.staging_group_name()
|
||||||
|
|
||||||
|
self.create_user('staging-bot')
|
||||||
|
self.create_group(group, users=['staging-bot'])
|
||||||
|
self.projects['target'].add_reviewers(groups = [group])
|
||||||
|
|
||||||
|
url = osc.core.makeurl(APIURL, ['staging', self.project, 'workflow'])
|
||||||
|
data = f"<workflow managers='{group}'/>"
|
||||||
|
osc.core.http_POST(url, data=data)
|
||||||
|
|
||||||
|
class FactoryWorkflow(StagingWorkflow):
|
||||||
|
"""A class that makes easy to setup scenarios similar to the one used during the real
|
||||||
|
openSUSE Factory development, with staging projects, rings, etc.
|
||||||
|
"""
|
||||||
|
def staging_group_name(self):
|
||||||
|
return 'factory-staging'
|
||||||
|
|
||||||
|
def initial_config(self):
|
||||||
|
return {
|
||||||
|
'overridden-by-local': 'remote-nope',
|
||||||
|
'staging-group': 'factory-staging',
|
||||||
|
'remote-only': 'remote-indeed',
|
||||||
|
}
|
||||||
|
|
||||||
|
def setup_rings(self, devel_project=None):
|
||||||
|
"""Creates a typical Factory setup with rings.
|
||||||
|
|
||||||
|
It creates three projects: 'ring0', 'ring1' and the target (see :func:`create_target`).
|
||||||
|
It also creates a 'wine' package in the target project and a link from it to ring1.
|
||||||
|
It sets the devel project for the package if ``devel_project`` is given.
|
||||||
|
|
||||||
|
:param devel_project: name of devel project. It must exist and contain a 'wine' package,
|
||||||
|
otherwise OBS returns an error code.
|
||||||
|
:type devel_project: str or None
|
||||||
|
"""
|
||||||
|
self.create_target()
|
||||||
|
self.projects['ring0'] = Project(name=self.project + ':Rings:0-Bootstrap')
|
||||||
|
self.projects['ring1'] = Project(name=self.project + ':Rings:1-MinimalX')
|
||||||
|
target_wine = Package(
|
||||||
|
name='wine', project=self.projects['target'], devel_project=devel_project
|
||||||
|
)
|
||||||
|
target_wine.create_commit()
|
||||||
|
self.create_link(target_wine, self.projects['ring1'])
|
||||||
|
|
||||||
|
def create_staging(self, suffix, freeze=False, rings=None, with_repo=False):
|
||||||
|
staging_key = 'staging:{}'.format(suffix)
|
||||||
|
# do not reattach if already present
|
||||||
|
if not staging_key in self.projects:
|
||||||
|
staging_name = self.project + ':Staging:' + suffix
|
||||||
|
staging = Project(staging_name, create=False, with_repo=with_repo)
|
||||||
|
url = osc.core.makeurl(APIURL, ['staging', self.project, 'staging_projects'])
|
||||||
|
data = '<workflow><staging_project>{}</staging_project></workflow>'
|
||||||
|
osc.core.http_POST(url, data=data.format(staging_name))
|
||||||
|
self.projects[staging_key] = staging
|
||||||
|
else:
|
||||||
|
staging = self.projects[staging_key]
|
||||||
|
|
||||||
|
project_links = []
|
||||||
|
if rings == 0:
|
||||||
|
project_links.append(self.project + ":Rings:0-Bootstrap")
|
||||||
|
if rings == 1 or rings == 0:
|
||||||
|
project_links.append(self.project + ":Rings:1-MinimalX")
|
||||||
|
|
||||||
|
group = self.staging_group_name()
|
||||||
|
staging.update_meta(project_links=project_links, maintainer={'groups': [group]},
|
||||||
|
with_repo=with_repo)
|
||||||
|
|
||||||
|
if freeze:
|
||||||
|
FreezeCommand(self.api).perform(staging.name)
|
||||||
|
|
||||||
|
return staging
|
||||||
|
|
||||||
class Project(object):
|
class Project(object):
|
||||||
"""This class represents a project in the testing environment of the release tools. It usually
|
"""This class represents a project in the testing environment of the release tools. It usually
|
||||||
corresponds to a project in the local OBS instance that is used by the tests.
|
corresponds to a project in the local OBS instance that is used by the tests.
|
||||||
|
@ -11,7 +11,7 @@ class TestReviewBotComment(OBSLocal.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestReviewBotComment, self).setUp()
|
super(TestReviewBotComment, self).setUp()
|
||||||
self.api = CommentAPI(self.apiurl)
|
self.api = CommentAPI(self.apiurl)
|
||||||
self.wf = OBSLocal.StagingWorkflow()
|
self.wf = OBSLocal.FactoryWorkflow()
|
||||||
self.wf.create_user('factory-auto')
|
self.wf.create_user('factory-auto')
|
||||||
self.project = self.wf.create_project(PROJECT)
|
self.project = self.wf.create_project(PROJECT)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ from . import OBSLocal
|
|||||||
class TestAccept(unittest.TestCase):
|
class TestAccept(unittest.TestCase):
|
||||||
|
|
||||||
def setup_wf(self):
|
def setup_wf(self):
|
||||||
wf = OBSLocal.StagingWorkflow()
|
wf = OBSLocal.FactoryWorkflow()
|
||||||
wf.setup_rings()
|
wf.setup_rings()
|
||||||
|
|
||||||
self.c_api = CommentAPI(wf.api.apiurl)
|
self.c_api = CommentAPI(wf.api.apiurl)
|
||||||
|
@ -17,7 +17,7 @@ class TestApiCalls(OBSLocal.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestApiCalls, self).setUp()
|
super(TestApiCalls, self).setUp()
|
||||||
self.wf = OBSLocal.StagingWorkflow()
|
self.wf = OBSLocal.FactoryWorkflow()
|
||||||
self.wf.setup_rings()
|
self.wf.setup_rings()
|
||||||
self.staging_b = self.wf.create_staging('B')
|
self.staging_b = self.wf.create_staging('B')
|
||||||
prj = self.staging_b.name
|
prj = self.staging_b.name
|
||||||
|
@ -5,7 +5,7 @@ class TestBuildFailReminder(OBSLocal.TestCase):
|
|||||||
script = './build-fail-reminder.py'
|
script = './build-fail-reminder.py'
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
self.wf = OBSLocal.StagingWorkflow()
|
self.wf = OBSLocal.FactoryWorkflow()
|
||||||
self.wf.create_target()
|
self.wf.create_target()
|
||||||
|
|
||||||
self.execute_script(['--relay', 'smtp', '--sender', 'Tester'])
|
self.execute_script(['--relay', 'smtp', '--sender', 'Tester'])
|
||||||
|
@ -23,8 +23,8 @@ class TestCheckSource(OBSLocal.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestCheckSource, self).setUp()
|
super(TestCheckSource, self).setUp()
|
||||||
|
|
||||||
# Using OBSLocal.StagingWorkflow makes it easier to setup testing scenarios
|
# Using OBSLocal.FactoryWorkflow makes it easier to setup testing scenarios
|
||||||
self.wf = OBSLocal.StagingWorkflow(PROJECT)
|
self.wf = OBSLocal.FactoryWorkflow(PROJECT)
|
||||||
self.project = self.wf.projects[PROJECT]
|
self.project = self.wf.projects[PROJECT]
|
||||||
|
|
||||||
# Set up the reviewers team
|
# Set up the reviewers team
|
||||||
|
@ -24,7 +24,7 @@ class TestCheckCommand(unittest.TestCase):
|
|||||||
def test_check_command_single(self):
|
def test_check_command_single(self):
|
||||||
"""Validate json conversion for a single project."""
|
"""Validate json conversion for a single project."""
|
||||||
|
|
||||||
wf = OBSLocal.StagingWorkflow()
|
wf = OBSLocal.FactoryWorkflow()
|
||||||
wf.create_staging('H')
|
wf.create_staging('H')
|
||||||
self.checkcommand = CheckCommand(wf.api)
|
self.checkcommand = CheckCommand(wf.api)
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ handle
|
|||||||
class TestCommentOBS(OBSLocal.TestCase):
|
class TestCommentOBS(OBSLocal.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestCommentOBS, self).setUp()
|
super(TestCommentOBS, self).setUp()
|
||||||
self.wf = OBSLocal.StagingWorkflow()
|
self.wf = OBSLocal.FactoryWorkflow()
|
||||||
self.wf.create_user('factory-auto')
|
self.wf.create_user('factory-auto')
|
||||||
self.wf.create_user('repo-checker')
|
self.wf.create_user('repo-checker')
|
||||||
self.wf.create_user('staging-bot')
|
self.wf.create_user('staging-bot')
|
||||||
|
@ -9,7 +9,7 @@ from . import OBSLocal
|
|||||||
|
|
||||||
class TestConfig(unittest.TestCase):
|
class TestConfig(unittest.TestCase):
|
||||||
def setup_vcr(self):
|
def setup_vcr(self):
|
||||||
return OBSLocal.StagingWorkflow()
|
return OBSLocal.FactoryWorkflow()
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
wf = self.setup_vcr()
|
wf = self.setup_vcr()
|
||||||
|
@ -7,7 +7,7 @@ class TestDevelProject(OBSLocal.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.wf = OBSLocal.StagingWorkflow()
|
self.wf = OBSLocal.FactoryWorkflow()
|
||||||
spa = self.wf.create_project('server:php:applications')
|
spa = self.wf.create_project('server:php:applications')
|
||||||
OBSLocal.Package('drush', project=spa)
|
OBSLocal.Package('drush', project=spa)
|
||||||
OBSLocal.Package('drush', self.wf.projects['target'], devel_project='server:php:applications')
|
OBSLocal.Package('drush', self.wf.projects['target'], devel_project='server:php:applications')
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import logging
|
|
||||||
from . import OBSLocal
|
from . import OBSLocal
|
||||||
import random
|
import random
|
||||||
import os
|
import os
|
||||||
@ -17,7 +16,6 @@ from check_source import CheckSource
|
|||||||
legal_auto = __import__("legal-auto") # Needed because of the dash in the filename
|
legal_auto = __import__("legal-auto") # Needed because of the dash in the filename
|
||||||
LegalAuto = legal_auto.LegalAuto
|
LegalAuto = legal_auto.LegalAuto
|
||||||
|
|
||||||
|
|
||||||
PROJECT = 'openSUSE:Factory'
|
PROJECT = 'openSUSE:Factory'
|
||||||
DEVEL_PROJECT = 'devel:drinking'
|
DEVEL_PROJECT = 'devel:drinking'
|
||||||
STAGING_PROJECT_NAME = 'openSUSE:Factory:Staging:A'
|
STAGING_PROJECT_NAME = 'openSUSE:Factory:Staging:A'
|
||||||
@ -41,8 +39,8 @@ class TestFactorySubmitRequest(OBSLocal.TestCase):
|
|||||||
super(TestFactorySubmitRequest, self).setUp()
|
super(TestFactorySubmitRequest, self).setUp()
|
||||||
|
|
||||||
# Setup the basic scenario, with manual reviewers, staging projects, rings and wine as
|
# Setup the basic scenario, with manual reviewers, staging projects, rings and wine as
|
||||||
# example package (wine is in ring1, see OBSLocal.StagingWorkflow.setup_rings)
|
# example package (wine is in ring1, see OBSLocal.FactoryWorkflow.setup_rings)
|
||||||
self.wf = OBSLocal.StagingWorkflow(PROJECT)
|
self.wf = OBSLocal.FactoryWorkflow(PROJECT)
|
||||||
self.__setup_review_team()
|
self.__setup_review_team()
|
||||||
self.__setup_devel_package('wine')
|
self.__setup_devel_package('wine')
|
||||||
self.wf.setup_rings(devel_project=DEVEL_PROJECT)
|
self.wf.setup_rings(devel_project=DEVEL_PROJECT)
|
||||||
@ -52,9 +50,8 @@ class TestFactorySubmitRequest(OBSLocal.TestCase):
|
|||||||
self.wf.remote_config_set({'required-source-maintainer': ''})
|
self.wf.remote_config_set({'required-source-maintainer': ''})
|
||||||
|
|
||||||
# Setup the different bots typically used for Factory
|
# Setup the different bots typically used for Factory
|
||||||
self.review_bots = {}
|
self.setup_review_bot(self.wf, PROJECT, 'factory-auto', CheckSource)
|
||||||
self.__setup_review_bot('factory-auto', CheckSource)
|
self.setup_review_bot(self.wf, PROJECT, 'licensedigger', LegalAuto)
|
||||||
self.__setup_review_bot('licensedigger', LegalAuto)
|
|
||||||
|
|
||||||
# Sorry, but LegalAuto is simply too hard to test while keeping this test readable,
|
# Sorry, but LegalAuto is simply too hard to test while keeping this test readable,
|
||||||
# see the description of __mock_licendigger for more rationale
|
# see the description of __mock_licendigger for more rationale
|
||||||
@ -70,12 +67,6 @@ class TestFactorySubmitRequest(OBSLocal.TestCase):
|
|||||||
super().tearDown()
|
super().tearDown()
|
||||||
del self.wf
|
del self.wf
|
||||||
|
|
||||||
def project(self):
|
|
||||||
return self.wf.projects[PROJECT]
|
|
||||||
|
|
||||||
def devel_project(self):
|
|
||||||
return self.wf.projects[DEVEL_PROJECT]
|
|
||||||
|
|
||||||
def test_happy_path(self):
|
def test_happy_path(self):
|
||||||
"""Tests the ideal case in which all bots are happy and the request successfully goes
|
"""Tests the ideal case in which all bots are happy and the request successfully goes
|
||||||
through staging"""
|
through staging"""
|
||||||
@ -86,8 +77,8 @@ class TestFactorySubmitRequest(OBSLocal.TestCase):
|
|||||||
self.assertReview(reqid, by_group=('factory-staging', 'new'))
|
self.assertReview(reqid, by_group=('factory-staging', 'new'))
|
||||||
|
|
||||||
# Let bots come into play
|
# Let bots come into play
|
||||||
self.__execute_review_bot('factory-auto', [reqid])
|
self.execute_review_bot([reqid], 'factory-auto')
|
||||||
self.__execute_review_bot('licensedigger', [reqid])
|
self.execute_review_bot([reqid], 'licensedigger')
|
||||||
|
|
||||||
# Bots are happy, now it's time for manual review (requested by the bots) and
|
# Bots are happy, now it's time for manual review (requested by the bots) and
|
||||||
# for the staging work
|
# for the staging work
|
||||||
@ -112,6 +103,10 @@ class TestFactorySubmitRequest(OBSLocal.TestCase):
|
|||||||
self.assertReview(reqid, by_group=('opensuse-review-team', 'accepted'))
|
self.assertReview(reqid, by_group=('opensuse-review-team', 'accepted'))
|
||||||
self.assertReview(reqid, by_group=('factory-staging', 'new'))
|
self.assertReview(reqid, by_group=('factory-staging', 'new'))
|
||||||
|
|
||||||
|
# Before using the staging plugin, we need to force a reload of the configuration
|
||||||
|
# because execute_review_bot temporarily switches the user and that causes problems
|
||||||
|
self.wf.load_config()
|
||||||
|
|
||||||
# The Staging Manager puts the request into a staging project
|
# The Staging Manager puts the request into a staging project
|
||||||
SelectCommand(self.wf.api, STAGING_PROJECT_NAME).perform(['wine'])
|
SelectCommand(self.wf.api, STAGING_PROJECT_NAME).perform(['wine'])
|
||||||
|
|
||||||
@ -152,32 +147,6 @@ class TestFactorySubmitRequest(OBSLocal.TestCase):
|
|||||||
self.wf.create_user(HUMAN_REVIEWER)
|
self.wf.create_user(HUMAN_REVIEWER)
|
||||||
self.wf.create_group('opensuse-review-team', users=[HUMAN_REVIEWER])
|
self.wf.create_group('opensuse-review-team', users=[HUMAN_REVIEWER])
|
||||||
|
|
||||||
def __setup_review_bot(self, user, bot_class):
|
|
||||||
"""Instantiates a bot and adds the associated user as reviewer of PROJECT
|
|
||||||
|
|
||||||
:param user: user to create for the bot
|
|
||||||
:type user: str
|
|
||||||
:param bot_class: type of bot to setup
|
|
||||||
"""
|
|
||||||
self.wf.create_user(user)
|
|
||||||
self.project().add_reviewers(users = [user])
|
|
||||||
|
|
||||||
bot_name = self.__generate_bot_name(user)
|
|
||||||
bot = bot_class(self.wf.apiurl, user=user, logger=logging.getLogger(bot_name))
|
|
||||||
bot.bot_name = bot_name
|
|
||||||
|
|
||||||
self.review_bots[user] = bot
|
|
||||||
|
|
||||||
def __execute_review_bot(self, user, requests):
|
|
||||||
bot = self.review_bots[user]
|
|
||||||
bot.set_request_ids(requests)
|
|
||||||
bot.check_requests()
|
|
||||||
|
|
||||||
def __generate_bot_name(self, user):
|
|
||||||
"""Used to ensure different test runs operate in unique namespace."""
|
|
||||||
|
|
||||||
return '::'.join([type(self).__name__, user, str(random.getrandbits(8))])
|
|
||||||
|
|
||||||
def __mock_licensedigger(self):
|
def __mock_licensedigger(self):
|
||||||
"""Mocks the execution of the LegalAuto bot, so it always succeeds and accepts the review
|
"""Mocks the execution of the LegalAuto bot, so it always succeeds and accepts the review
|
||||||
|
|
@ -24,7 +24,7 @@ class TestFreeze(OBSLocal.TestCase):
|
|||||||
return os.path.join(os.getcwd(), 'tests/fixtures')
|
return os.path.join(os.getcwd(), 'tests/fixtures')
|
||||||
|
|
||||||
def test_bootstrap_copy(self):
|
def test_bootstrap_copy(self):
|
||||||
wf = OBSLocal.StagingWorkflow()
|
wf = OBSLocal.FactoryWorkflow()
|
||||||
|
|
||||||
fc = FreezeCommand(wf.api)
|
fc = FreezeCommand(wf.api)
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ class TestOBSLock(unittest.TestCase):
|
|||||||
self.assertEqual(reason_sub, None, 'does not inherit hold')
|
self.assertEqual(reason_sub, None, 'does not inherit hold')
|
||||||
|
|
||||||
def setup_vcr(self):
|
def setup_vcr(self):
|
||||||
wf = OBSLocal.StagingWorkflow()
|
wf = OBSLocal.FactoryWorkflow()
|
||||||
wf.create_target()
|
wf.create_target()
|
||||||
# we should most likely create this as part of create_target, but
|
# we should most likely create this as part of create_target, but
|
||||||
# it just slows down all other tests
|
# it just slows down all other tests
|
||||||
|
@ -28,7 +28,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
self.target_project = self.randomString('target')
|
self.target_project = self.randomString('target')
|
||||||
self.wf = OBSLocal.StagingWorkflow(self.target_project)
|
self.wf = OBSLocal.FactoryWorkflow(self.target_project)
|
||||||
|
|
||||||
self.wf.create_attribute_type('OSRT', 'OriginConfig', 1)
|
self.wf.create_attribute_type('OSRT', 'OriginConfig', 1)
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
self.origin_config_write([])
|
self.origin_config_write([])
|
||||||
|
|
||||||
request = self.wf.create_submit_request(self.randomString('devel'), self.randomString('package'))
|
request = self.wf.create_submit_request(self.randomString('devel'), self.randomString('package'))
|
||||||
self.assertReviewBot(request.reqid, self.bot_user, 'new', 'new')
|
self.assertReviewScript(request.reqid, self.bot_user, 'new', 'new')
|
||||||
self.assertOutput(f'skipping {request.reqid} of age')
|
self.assertOutput(f'skipping {request.reqid} of age')
|
||||||
self.assertOutput('since it is younger than 1800s')
|
self.assertOutput('since it is younger than 1800s')
|
||||||
|
|
||||||
@ -130,14 +130,14 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
|
|
||||||
def test_no_config(self):
|
def test_no_config(self):
|
||||||
request = self.wf.create_submit_request(self.randomString('devel'), self.randomString('package'))
|
request = self.wf.create_submit_request(self.randomString('devel'), self.randomString('package'))
|
||||||
self.assertReviewBot(request.reqid, self.bot_user, 'new', 'accepted', 'skipping since no OSRT:OriginConfig')
|
self.assertReviewScript(request.reqid, self.bot_user, 'new', 'accepted', 'skipping since no OSRT:OriginConfig')
|
||||||
|
|
||||||
def test_not_allowed_origin(self):
|
def test_not_allowed_origin(self):
|
||||||
self.remote_config_set_age_minimum()
|
self.remote_config_set_age_minimum()
|
||||||
self.origin_config_write([{'fakeProject': {}}], {'unknown_origin_wait': True})
|
self.origin_config_write([{'fakeProject': {}}], {'unknown_origin_wait': True})
|
||||||
|
|
||||||
request = self.wf.create_submit_request(self.randomString('devel'), self.randomString('package'))
|
request = self.wf.create_submit_request(self.randomString('devel'), self.randomString('package'))
|
||||||
self.assertReviewBot(request.reqid, self.bot_user, 'new', 'new')
|
self.assertReviewScript(request.reqid, self.bot_user, 'new', 'new')
|
||||||
|
|
||||||
comment = [
|
comment = [
|
||||||
'<!-- OriginManager state=seen result=None -->',
|
'<!-- OriginManager state=seen result=None -->',
|
||||||
@ -148,7 +148,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
self.assertComment(request.reqid, comment)
|
self.assertComment(request.reqid, comment)
|
||||||
|
|
||||||
self.origin_config_write([{'fakeProject': {}}], {'unknown_origin_wait': False})
|
self.origin_config_write([{'fakeProject': {}}], {'unknown_origin_wait': False})
|
||||||
self.assertReviewBot(request.reqid, self.bot_user, 'new', 'declined', 'review failed')
|
self.assertReviewScript(request.reqid, self.bot_user, 'new', 'declined', 'review failed')
|
||||||
comment.pop()
|
comment.pop()
|
||||||
self.assertComment(request.reqid, comment)
|
self.assertComment(request.reqid, comment)
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
attribute_value_save(self.wf.apiurl, devel_project, 'ApprovedRequestSource', '', 'OBS')
|
attribute_value_save(self.wf.apiurl, devel_project, 'ApprovedRequestSource', '', 'OBS')
|
||||||
|
|
||||||
if not only_devel:
|
if not only_devel:
|
||||||
self.assertReviewBot(request.reqid, self.bot_user, 'new', 'new')
|
self.assertReviewScript(request.reqid, self.bot_user, 'new', 'new')
|
||||||
|
|
||||||
comment = [
|
comment = [
|
||||||
'<!-- OriginManager state=seen result=None -->',
|
'<!-- OriginManager state=seen result=None -->',
|
||||||
@ -190,7 +190,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
else:
|
else:
|
||||||
comment = 'only devel origin allowed'
|
comment = 'only devel origin allowed'
|
||||||
|
|
||||||
self.assertReviewBot(request.reqid, self.bot_user, 'new', 'accepted')
|
self.assertReviewScript(request.reqid, self.bot_user, 'new', 'accepted')
|
||||||
self.assertAnnotation(request.reqid, {
|
self.assertAnnotation(request.reqid, {
|
||||||
'comment': comment,
|
'comment': comment,
|
||||||
'origin': devel_project,
|
'origin': devel_project,
|
||||||
@ -214,7 +214,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
origin_info = origin_find(self.wf.apiurl, self.wf.project, package)
|
origin_info = origin_find(self.wf.apiurl, self.wf.project, package)
|
||||||
self.assertEqual(origin_info, None)
|
self.assertEqual(origin_info, None)
|
||||||
|
|
||||||
self.assertReviewBot(request_id_change_devel, self.bot_user, 'new', 'accepted')
|
self.assertReviewScript(request_id_change_devel, self.bot_user, 'new', 'accepted')
|
||||||
self.assertAnnotation(request_id_change_devel, {
|
self.assertAnnotation(request_id_change_devel, {
|
||||||
'origin': devel_project,
|
'origin': devel_project,
|
||||||
})
|
})
|
||||||
@ -237,7 +237,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
self.assertEqual(request_future, False)
|
self.assertEqual(request_future, False)
|
||||||
self.osc_user_pop()
|
self.osc_user_pop()
|
||||||
|
|
||||||
self.assertReviewBot(request_id_update, self.bot_user, 'new', 'accepted')
|
self.assertReviewScript(request_id_update, self.bot_user, 'new', 'accepted')
|
||||||
self.assertAnnotation(request_id_update, {
|
self.assertAnnotation(request_id_update, {
|
||||||
'origin': devel_project,
|
'origin': devel_project,
|
||||||
})
|
})
|
||||||
@ -271,7 +271,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
if request_future:
|
if request_future:
|
||||||
request_id_change_devel_new = request_future.print_and_create()
|
request_id_change_devel_new = request_future.print_and_create()
|
||||||
|
|
||||||
self.assertReviewBot(request_id_change_devel_new, self.bot_user, 'new', 'accepted')
|
self.assertReviewScript(request_id_change_devel_new, self.bot_user, 'new', 'accepted')
|
||||||
self.assertAnnotation(request_id_change_devel_new, {
|
self.assertAnnotation(request_id_change_devel_new, {
|
||||||
'origin': devel_project_new,
|
'origin': devel_project_new,
|
||||||
'origin_old': devel_project,
|
'origin_old': devel_project,
|
||||||
@ -324,7 +324,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
request_upstream2 = self.wf.submit_package(devel_package, upstream2_project)
|
request_upstream2 = self.wf.submit_package(devel_package, upstream2_project)
|
||||||
request_target = self.wf.submit_package(devel_package, self.target_project)
|
request_target = self.wf.submit_package(devel_package, self.target_project)
|
||||||
|
|
||||||
self.assertReviewBot(request_target.reqid, self.bot_user, 'new', 'new')
|
self.assertReviewScript(request_target.reqid, self.bot_user, 'new', 'new')
|
||||||
comment = [
|
comment = [
|
||||||
'<!-- OriginManager state=seen result=None -->',
|
'<!-- OriginManager state=seen result=None -->',
|
||||||
f'Waiting on acceptance of request#{request_upstream2.reqid}.',
|
f'Waiting on acceptance of request#{request_upstream2.reqid}.',
|
||||||
@ -333,7 +333,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
|
|
||||||
request_upstream2.change_state('accepted')
|
request_upstream2.change_state('accepted')
|
||||||
|
|
||||||
self.assertReviewBot(request_target.reqid, self.bot_user, 'new', 'accepted')
|
self.assertReviewScript(request_target.reqid, self.bot_user, 'new', 'accepted')
|
||||||
self.assertAnnotation(request_target.reqid, {
|
self.assertAnnotation(request_target.reqid, {
|
||||||
'origin': upstream2_project,
|
'origin': upstream2_project,
|
||||||
'origin_old': upstream1_project,
|
'origin_old': upstream1_project,
|
||||||
@ -490,7 +490,7 @@ class TestOrigin(OBSLocal.TestCase):
|
|||||||
self.assertNoUpdate(package1)
|
self.assertNoUpdate(package1)
|
||||||
|
|
||||||
# Accept request and ensure update since no request to supersede.
|
# Accept request and ensure update since no request to supersede.
|
||||||
self.assertReviewBot(request_id_package1_1, self.bot_user, 'new', 'accepted')
|
self.assertReviewScript(request_id_package1_1, self.bot_user, 'new', 'accepted')
|
||||||
request_state_change(self.wf.apiurl, request_id_package1_1, 'accepted')
|
request_state_change(self.wf.apiurl, request_id_package1_1, 'accepted')
|
||||||
|
|
||||||
request_id_package1_2 = self.assertUpdate(package1)
|
request_id_package1_2 = self.assertUpdate(package1)
|
||||||
|
@ -11,7 +11,7 @@ class TestRepository(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestRepository, self).setUp()
|
super(TestRepository, self).setUp()
|
||||||
self.wf = OBSLocal.StagingWorkflow()
|
self.wf = OBSLocal.FactoryWorkflow()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
del self.wf
|
del self.wf
|
||||||
|
@ -25,7 +25,7 @@ class TestSelect(OBSLocal.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
super(TestSelect, self).setUp()
|
super(TestSelect, self).setUp()
|
||||||
self.wf = OBSLocal.StagingWorkflow()
|
self.wf = OBSLocal.FactoryWorkflow()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super(TestSelect, self).tearDown()
|
super(TestSelect, self).tearDown()
|
||||||
|
@ -7,7 +7,7 @@ from . import OBSLocal
|
|||||||
class TestUnselect(OBSLocal.TestCase):
|
class TestUnselect(OBSLocal.TestCase):
|
||||||
|
|
||||||
def test_cleanup_filter(self):
|
def test_cleanup_filter(self):
|
||||||
wf = OBSLocal.StagingWorkflow()
|
wf = OBSLocal.FactoryWorkflow()
|
||||||
UnselectCommand.config_init(wf.api)
|
UnselectCommand.config_init(wf.api)
|
||||||
UnselectCommand.cleanup_days = 1
|
UnselectCommand.cleanup_days = 1
|
||||||
obsolete = wf.api.project_status_requests('obsolete', UnselectCommand.filter_obsolete)
|
obsolete = wf.api.project_status_requests('obsolete', UnselectCommand.filter_obsolete)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user