forked from openSUSE/openSUSE-release-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sle_submit_request_tests.py
204 lines (165 loc) · 9.43 KB
/
sle_submit_request_tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
from . import OBSLocal
import os
# Needed to configure OriginManager
import yaml
from osclib.core import attribute_value_save
# Needed to mock LegalAuto
from osc.core import change_review_state
from unittest.mock import MagicMock
# Import the involved staging commands
from osclib.freeze_command import FreezeCommand
from osclib.select_command import SelectCommand
from osclib.accept_command import AcceptCommand
# Import the involved bots
from check_source import CheckSource
from check_tags_in_requests import TagChecker
legal_auto = __import__("legal-auto") # Needed because of the dash in the filename
LegalAuto = legal_auto.LegalAuto
origin_manager = __import__("origin-manager") # Same than above, dash in the filename
OriginManager = origin_manager.OriginManager
PROJECT = 'SUSE:SLE-15-SP3:GA'
DEVEL_PROJECT = 'devel:drinking'
STAGING_PROJECT_NAME = 'SUSE:SLE-15-SP3:GA:Staging:A'
HUMAN_REVIEWER = 'release-manager'
FIXTURES = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'fixtures')
class TestSLESubmitRequest(OBSLocal.TestCase):
"""Tests for the whole lifecycle of submit requests in SLE
Similar in purpose and philosophy to TestFactorySubmitRequest, check
factory_submit_request_tests.py for more details
"""
def setUp(self):
super(TestSLESubmitRequest, self).setUp()
# Setup the basic scenario, with manual reviewers, staging projects[...]
self.wf = OBSLocal.SLEWorkflow(PROJECT)
self.__setup_review_teams()
self.__setup_devel_package('wine')
self.__config_origin_manager()
# Setup the different bots typically used for Factory
self.setup_review_bot(self.wf, PROJECT, 'factory-auto', CheckSource)
self.setup_review_bot(self.wf, PROJECT, 'licensedigger', LegalAuto)
self.setup_review_bot(self.wf, PROJECT, 'sle-changelog-checker', TagChecker)
self.setup_review_bot(self.wf, PROJECT, 'origin-manager', OriginManager)
# Simulating the environment to please some of the bots while keeping this test readable
# may be a bit more tricky than it seems. Check the descriptions of __mock_licendigger and
# __mock_changelog_checker for more rationale
self.__mock_licensedigger()
self.__mock_changelog_checker()
# The staging project must be frozen in order to move packages into it
FreezeCommand(self.wf.api).perform(STAGING_PROJECT_NAME)
# Create the submit request
self.request = self.wf.create_submit_request(DEVEL_PROJECT, 'wine', add_commit=False)
def tearDown(self):
super().tearDown()
del self.wf
def project(self):
return self.wf.projects[PROJECT]
def test_happy_path(self):
"""Tests the ideal case in which all bots are happy and the request successfully goes
through staging"""
reqid = self.request.reqid
# Initial state: reviews have been created for...
# ...three human reviewers...
self.assertReview(reqid, by_group=('sle-release-managers', 'new'))
self.assertReview(reqid, by_group=('autobuild-team', 'new'))
self.assertReview(reqid, by_group=('origin-reviewers', 'new'))
# ...for the staging workflow...
self.assertReview(reqid, by_group=('sle-staging-managers', 'new'))
# ...and for the bots.
# So let's first execute the bots and verify their results
self.assertReviewBot(reqid, 'factory-auto', 'new', 'accepted')
self.assertReviewBot(reqid, 'licensedigger', 'new', 'accepted')
self.assertReviewBot(reqid, 'origin-manager', 'new', 'accepted')
self.assertReviewBot(reqid, 'sle-changelog-checker', 'new', 'accepted')
# So now that bots are happy, let's accept the manual reviews
self.osc_user(HUMAN_REVIEWER)
change_review_state(self.wf.apiurl, reqid, 'accepted', by_group='sle-release-managers')
change_review_state(self.wf.apiurl, reqid, 'accepted', by_group='autobuild-team')
change_review_state(self.wf.apiurl, reqid, 'accepted', by_group='origin-reviewers')
self.osc_user_pop()
# Now only the staging workflow is pending
self.assertReview(reqid, by_group=('sle-release-managers', 'accepted'))
self.assertReview(reqid, by_group=('autobuild-team', 'accepted'))
self.assertReview(reqid, by_group=('origin-reviewers', 'accepted'))
self.assertReview(reqid, by_group=('sle-staging-managers', 'new'))
# Before using the staging plugin, we need to force a reload of the configuration
# because assertReviewBot temporarily switches the user and that causes problems
self.wf.load_config()
# One staging manager puts the request into the staging project
SelectCommand(self.wf.api, STAGING_PROJECT_NAME).perform(['wine'])
# The sle-staging-managers review is now accepted and a new review associated to
# the staging project has been created
self.assertReview(reqid, by_group=('sle-staging-managers', 'accepted'))
self.assertReview(reqid, by_project=(STAGING_PROJECT_NAME, 'new'))
# Let's say everything looks good in the staging project, so the staging manager can
# accept that staging
AcceptCommand(self.wf.api).accept_all([STAGING_PROJECT_NAME], True)
# Finally, all the reviews are accepted:
# ...one for each bot,
self.assertReview(reqid, by_user=('factory-auto', 'accepted'))
self.assertReview(reqid, by_user=('licensedigger', 'accepted'))
self.assertReview(reqid, by_user=('sle-changelog-checker', 'accepted'))
self.assertReview(reqid, by_user=('origin-manager', 'accepted'))
# ...one for each manual review
self.assertReview(reqid, by_group=('sle-release-managers', 'accepted'))
self.assertReview(reqid, by_group=('autobuild-team', 'accepted'))
self.assertReview(reqid, by_group=('origin-reviewers', 'accepted'))
# ...and two for the staging project (one as a consequence of selecting the package into a
# staging project and the other as a consequence of accepting the staging)
self.assertReview(reqid, by_group=('sle-staging-managers', 'accepted'))
self.assertReview(reqid, by_project=(STAGING_PROJECT_NAME, 'accepted'))
# So it's time to accept the request
self.request.change_state('accepted')
self.assertRequestState(reqid, name='accepted')
def __setup_devel_package(self, pkg_name):
pkg = self.wf.create_package(DEVEL_PROJECT, pkg_name)
pkg.commit_files(os.path.join(FIXTURES, 'packages', pkg_name))
target_pkg = OBSLocal.Package(pkg_name, project=self.project(), devel_project=DEVEL_PROJECT)
target_pkg.create_commit()
def __setup_review_teams(self):
"""Creates the different review teams for manual reviews.
For simplicity, this uses a common user for all groups.
This also sets those groups as reviewers of the target project, to ensure new reviews are
created for them as soon as the request is created. Note the difference with the Factory
workflow, in which the groups of human reviewers are not initially set as reviewers in the
target project configuration. Instead, in Factory the review targeting the human reviewers
is created by the factory-auto (CheckSource) bot.
"""
self.wf.create_user(HUMAN_REVIEWER)
groups = ['sle-release-managers', 'origin-reviewers', 'autobuild-team']
for group in groups:
self.wf.create_group(group, users=[HUMAN_REVIEWER])
self.project().add_reviewers(groups=[group])
def __config_origin_manager(self):
"""Creates the very minimal configuration needed by origin-manager to work"""
self.wf.create_attribute_type('OSRT', 'OriginConfig', 1)
self.wf.remote_config_set({'originmanager-request-age-min': 0})
config = {
'origins': [{'<devel>': {}}],
'review-user': 'origin-manager',
'fallback-group': 'origin-reviewers'
}
config = yaml.dump(config, default_flow_style=False)
attribute_value_save(self.wf.apiurl, PROJECT, 'OriginConfig', config)
def __mock_changelog_checker(self):
"""Mocks the verification done by the TagChecker.
Normally, the bot checks whether the request references an entry in any of the known
issue trackers or whether the same request has been sent to Factory. Although simulating one
of those scenarios looks easy (and probably is), the whole check is mocked to return True
for simplicity (the rest of the execution of the bot still takes place normally).
"""
bot = self.review_bots['sle-changelog-checker']
bot.checkTagInRequest = MagicMock(return_value=True)
def __mock_licensedigger(self):
"""Mocks the execution of the LegalAuto bot, so it always succeeds and accepts the review
Unfortunatelly, LegalAuto is not written to be testable and it's very dependant on external
components. So just mocking its whole execution looks like the simplest solution for the
time being. Hopefully this whole mock could be removed in the future.
"""
bot = self.review_bots['licensedigger']
bot.check_requests = MagicMock(side_effect=self.__accept_license)
def __accept_license(self):
"""See :func:`__mock_licensedigger`"""
change_review_state(
apiurl=self.wf.apiurl, reqid=self.request.reqid,
newstate='accepted', by_user='licensedigger'
)