Merge ~mitya57/britney:remove-source-ppa-policy into ~ubuntu-release/britney/+git/britney2-ubuntu:master
- Git
- lp:~mitya57/britney
- remove-source-ppa-policy
- Merge into master
Proposed by
Dmitry Shachnev
Status: | Needs review |
---|---|
Proposed branch: | ~mitya57/britney:remove-source-ppa-policy |
Merge into: | ~ubuntu-release/britney/+git/britney2-ubuntu:master |
Diff against target: |
876 lines (+19/-478) 8 files modified
britney.py (+0/-2) dev/null (+0/-404) tests/__init__.py (+7/-0) tests/test_autopkgtest.py (+10/-34) tests/test_email.py (+1/-11) tests/test_lpexcusebugs.py (+0/-11) tests/test_sruadtregression.py (+1/-2) tests/test_yaml.py (+0/-14) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Release Team | Pending | ||
Review via email: mp+464245@code.launchpad.net |
Commit message
Description of the change
Remove SourcePPAPolicy
It did not always detect the PPA packages correctly, and it did not show which exactly package which is blocking all the other ones.
After discussing on #ubuntu-release, we decided to remove it:
https:/
To post a comment you must log in.
Unmerged commits
- be5d181... by Dmitry Shachnev
-
Remove SourcePPAPolicy
It did not always detect the PPA packages correctly, and it did not
show which exactly package which is blocking all the other ones.After discussing on #ubuntu-release, we decided to remove it:
https://irclogs. ubuntu. com/2024/ 04/13/% 23ubuntu- release. html#t16: 33
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/britney.py b/britney.py |
2 | index 8d8f427..2ca3a24 100755 |
3 | --- a/britney.py |
4 | +++ b/britney.py |
5 | @@ -220,7 +220,6 @@ from britney2.policies.policy import (AgePolicy, |
6 | LPBlockBugPolicy, |
7 | ) |
8 | from britney2.policies.autopkgtest import AutopkgtestPolicy |
9 | -from britney2.policies.sourceppa import SourcePPAPolicy |
10 | from britney2.policies.sruadtregression import SRUADTRegressionPolicy |
11 | from britney2.policies.email import EmailPolicy |
12 | from britney2.policies.lpexcusebugs import LPExcuseBugsPolicy |
13 | @@ -549,7 +548,6 @@ class Britney(object): |
14 | self._policy_engine.add_policy(BuiltOnBuilddPolicy(self.options, self.suite_info)) |
15 | self._policy_engine.add_policy(LPBlockBugPolicy(self.options, self.suite_info)) |
16 | self._policy_engine.add_policy(LPExcuseBugsPolicy(self.options, self.suite_info)) |
17 | - self._policy_engine.add_policy(SourcePPAPolicy(self.options, self.suite_info)) |
18 | self._policy_engine.add_policy(LinuxPolicy(self.options, self.suite_info)) |
19 | add_sruregression_policy = getattr(self.options, 'sruregressionemail_enable', 'no') |
20 | if add_sruregression_policy in ('yes', 'dry-run'): |
21 | diff --git a/britney2/policies/sourceppa.py b/britney2/policies/sourceppa.py |
22 | deleted file mode 100644 |
23 | index bbef00d..0000000 |
24 | --- a/britney2/policies/sourceppa.py |
25 | +++ /dev/null |
26 | @@ -1,185 +0,0 @@ |
27 | -import os |
28 | -import json |
29 | -import socket |
30 | -import urllib.request |
31 | -import urllib.parse |
32 | - |
33 | -from collections import defaultdict |
34 | -from urllib.error import HTTPError |
35 | - |
36 | -from britney2 import SuiteClass |
37 | -from britney2.policies.rest import Rest |
38 | -from britney2.policies.policy import BasePolicy, PolicyVerdict |
39 | - |
40 | - |
41 | -LAUNCHPAD_URL = "https://api.launchpad.net/1.0/" |
42 | -PRIMARY = LAUNCHPAD_URL + "ubuntu/+archive/primary" |
43 | -INCLUDE = ["~bileto-ppa-service/", "~ci-train-ppa-service/"] |
44 | -EXCLUDE = ["~ci-train-ppa-service/+archive/ubuntu/4810", "~ci-train-ppa-service/+archive/ubuntu/4813", "~ci-train-ppa-service/+archive/ubuntu/4815", "~ci-train-ppa-service/+archive/ubuntu/4816"] |
45 | - |
46 | - |
47 | -class SourcePPAPolicy(BasePolicy, Rest): |
48 | - """Migrate packages copied from same source PPA together |
49 | - |
50 | - This policy will query launchpad to determine what source PPA packages |
51 | - were copied from, and ensure that all packages from the same PPA migrate |
52 | - together. |
53 | - """ |
54 | - |
55 | - def __init__(self, options, suite_info): |
56 | - super().__init__( |
57 | - "source-ppa", options, suite_info, {SuiteClass.PRIMARY_SOURCE_SUITE} |
58 | - ) |
59 | - self.filename = os.path.join(options.unstable, "SourcePPA") |
60 | - # Dict of dicts; maps pkg name -> pkg version -> source PPA URL |
61 | - self.source_ppas_by_pkg = defaultdict(dict) |
62 | - # Dict of sets; maps source PPA URL -> (set of source names, set of |
63 | - # friends; collected excuses for this ppa) |
64 | - self.excuses_by_source_ppa = defaultdict(set) |
65 | - self.source_ppa_info_by_source_ppa = defaultdict(set) |
66 | - self.britney = None |
67 | - # self.cache contains self.source_ppas_by_pkg from previous run |
68 | - self.cache = {} |
69 | - |
70 | - def lp_get_source_ppa(self, pkg, version): |
71 | - """Ask LP what source PPA pkg was copied from""" |
72 | - cached = self.cache.get(pkg, {}).get(version) |
73 | - if cached is not None: |
74 | - return cached |
75 | - |
76 | - data = self.query_lp_rest_api( |
77 | - "%s/+archive/primary" % self.options.distribution, |
78 | - { |
79 | - "ws.op": "getPublishedSources", |
80 | - "pocket": "Proposed", |
81 | - "source_name": pkg, |
82 | - "version": version, |
83 | - "exact_match": "true", |
84 | - "distro_series": "/%s/%s" |
85 | - % (self.options.distribution, self.options.series), |
86 | - }, |
87 | - ) |
88 | - try: |
89 | - sourcepub = data["entries"][0]["self_link"] |
90 | - # IndexError means no packages in -proposed matched this name/version, |
91 | - # which is expected to happen when bileto runs britney. |
92 | - except IndexError: |
93 | - self.logger.info( |
94 | - "SourcePPA getPackageUploads IndexError (%s %s)" |
95 | - % (pkg, version) |
96 | - ) |
97 | - return "IndexError" |
98 | - data = self.query_lp_rest_api( |
99 | - sourcepub, {"ws.op": "getPublishedBinaries"} |
100 | - ) |
101 | - for binary in data["entries"]: |
102 | - link = binary["build_link"] or "" |
103 | - if "/+archive/" in link: |
104 | - ppa, _, buildid = link.partition("/+build/") |
105 | - return ppa |
106 | - return "" |
107 | - |
108 | - def initialise(self, britney): |
109 | - """Load cached source ppa data""" |
110 | - super().initialise(britney) |
111 | - self.britney = britney |
112 | - |
113 | - if os.path.exists(self.filename): |
114 | - with open(self.filename, encoding="utf-8") as data: |
115 | - self.cache = json.load(data) |
116 | - self.logger.info( |
117 | - "Loaded cached source ppa data from %s", self.filename |
118 | - ) |
119 | - |
120 | - def apply_src_policy_impl( |
121 | - self, |
122 | - sourceppa_info, |
123 | - item, |
124 | - source_data_tdist, |
125 | - source_data_srcdist, |
126 | - excuse, |
127 | - ): |
128 | - """Reject package if any other package copied from same PPA is invalid""" |
129 | - source_name = item.package |
130 | - accept = excuse.is_valid |
131 | - version = source_data_srcdist.version |
132 | - sourceppa = self.lp_get_source_ppa(source_name, version) or "" |
133 | - verdict = excuse.policy_verdict |
134 | - self.source_ppas_by_pkg[source_name][version] = sourceppa |
135 | - if [team for team in EXCLUDE if team in sourceppa]: |
136 | - return PolicyVerdict.PASS |
137 | - if not [team for team in INCLUDE if team in sourceppa]: |
138 | - return PolicyVerdict.PASS |
139 | - |
140 | - # check for a force hint; we have to check here in addition to |
141 | - # checking in britney.py, otherwise /this/ package will later be |
142 | - # considered valid candidate but all the /others/ from the ppa will |
143 | - # be invalidated via this policy and not fixed by the force hint. |
144 | - forces = self.hints.search( |
145 | - "force", package=source_name, version=source_data_srcdist.version |
146 | - ) |
147 | - if forces: |
148 | - excuse.dontinvalidate = True |
149 | - changed_state = excuse.force() |
150 | - if changed_state: |
151 | - excuse.addhtml( |
152 | - "Should ignore, but forced by %s" % (forces[0].user) |
153 | - ) |
154 | - accept = True |
155 | - |
156 | - shortppa = sourceppa.replace(LAUNCHPAD_URL, "") |
157 | - sourceppa_info[source_name] = shortppa |
158 | - |
159 | - if not excuse.is_valid: |
160 | - self.logger.info( |
161 | - "sourceppa: processing %s, which is invalid, will invalidate set", |
162 | - source_name, |
163 | - ) |
164 | - else: |
165 | - # Check for other packages that might invalidate this one |
166 | - for friend_exc in self.excuses_by_source_ppa[sourceppa]: |
167 | - sourceppa_info[friend_exc.item.package] = shortppa |
168 | - if not friend_exc.is_valid: |
169 | - self.logger.info( |
170 | - "sourceppa: processing %s, found invalid grouped package %s, will invalidate set" |
171 | - % (source_name, friend_exc.name) |
172 | - ) |
173 | - accept = False |
174 | - break |
175 | - |
176 | - self.excuses_by_source_ppa[sourceppa].add(excuse) |
177 | - |
178 | - if not accept: |
179 | - # Invalidate all packages in this source ppa |
180 | - for friend_exc in self.excuses_by_source_ppa[sourceppa]: |
181 | - self.logger.info("friend: %s", friend_exc.name) |
182 | - sourceppa_info[friend_exc.item.package] = shortppa |
183 | - if friend_exc.is_valid: |
184 | - if friend_exc == excuse: |
185 | - verdict = PolicyVerdict.REJECTED_WAITING_FOR_ANOTHER_ITEM |
186 | - else: |
187 | - friend_exc.invalidate_externally( |
188 | - PolicyVerdict.REJECTED_WAITING_FOR_ANOTHER_ITEM |
189 | - ) |
190 | - friend_exc.addreason("source-ppa") |
191 | - self.logger.info( |
192 | - "sourceppa: ... invalidating %s due to the above (ppa: %s), %s" |
193 | - % (friend_exc.name, shortppa, sourceppa_info) |
194 | - ) |
195 | - friend_exc.addinfo("Grouped with PPA %s" % shortppa) |
196 | - |
197 | - for friend_exc in self.excuses_by_source_ppa[sourceppa]: |
198 | - try: |
199 | - friend_exc.policy_info["source-ppa"].update(sourceppa_info) |
200 | - except KeyError: |
201 | - friend_exc.policy_info["source-ppa"] = sourceppa_info.copy() |
202 | - |
203 | - return verdict |
204 | - |
205 | - def save_state(self, britney): |
206 | - """Write source ppa data to disk""" |
207 | - tmp = self.filename + ".tmp" |
208 | - with open(tmp, "w", encoding="utf-8") as data: |
209 | - json.dump(self.source_ppas_by_pkg, data) |
210 | - os.rename(tmp, self.filename) |
211 | - self.logger.info("Wrote source ppa data to %s" % self.filename) |
212 | diff --git a/tests/__init__.py b/tests/__init__.py |
213 | index eaa9436..2d7af51 100644 |
214 | --- a/tests/__init__.py |
215 | +++ b/tests/__init__.py |
216 | @@ -445,3 +445,10 @@ EMAIL_ENABLE = yes |
217 | with open(hints_path, 'a') as fd: |
218 | fd.write(content) |
219 | fd.write('\n') |
220 | + |
221 | + |
222 | +class FakeOptions: |
223 | + distribution = "testbuntu" |
224 | + series = "zazzy" |
225 | + unstable = "/tmp" |
226 | + verbose = False |
227 | diff --git a/tests/test_autopkgtest.py b/tests/test_autopkgtest.py |
228 | index 5c7bb72..36eef3a 100644 |
229 | --- a/tests/test_autopkgtest.py |
230 | +++ b/tests/test_autopkgtest.py |
231 | @@ -56,31 +56,18 @@ class TestAutopkgtestBase(TestBase): |
232 | else: |
233 | sys.stdout.write(line) |
234 | |
235 | - # Set up sourceppa cache for testing |
236 | - self.sourceppa_cache = { |
237 | - 'gcc-5': {'2': ''}, |
238 | - 'gcc-snapshot': {'2': ''}, |
239 | - 'green': {'2': '', '1.1': '', '3': ''}, |
240 | - 'lightgreen': {'2': '', '1.1~beta': '', '3': ''}, |
241 | - 'linux-meta-64only': {'1': ''}, |
242 | - 'linux-meta-lts-grumpy': {'1': ''}, |
243 | - 'linux-meta': {'0.2': '', '1': '', '2': ''}, |
244 | - 'linux': {'2': ''}, |
245 | - 'newgreen': {'2': ''}, |
246 | + self.email_cache = { |
247 | + 'gcc-5': {'2': True}, |
248 | + 'gcc-snapshot': {'2': True}, |
249 | + 'green': {'1.1': True, '2': True, '3': True}, |
250 | + 'lightgreen': {'1.1~beta': True, '2': True, '3': True}, |
251 | + 'linux': {'2': True}, |
252 | + 'linux-meta': {'0.2': True, '1': True, '2': True}, |
253 | + 'linux-meta-64only': {'1': True}, |
254 | + 'linux-meta-lts-grumpy': {'1': True}, |
255 | + 'newgreen': {'2': True}, |
256 | } |
257 | |
258 | - self.email_cache = {} |
259 | - for pkg, vals in self.sourceppa_cache.items(): |
260 | - for version, empty in vals.items(): |
261 | - self.email_cache.setdefault(pkg, {}) |
262 | - self.email_cache[pkg][version] = True |
263 | - |
264 | - self.email_cache = {} |
265 | - for pkg, vals in self.sourceppa_cache.items(): |
266 | - for version, empty in vals.items(): |
267 | - self.email_cache.setdefault(pkg, {}) |
268 | - self.email_cache[pkg][version] = True |
269 | - |
270 | # create mock Swift server (but don't start it yet, as tests first need |
271 | # to poke in results) |
272 | self.swift = mock_swift.AutoPkgTestSwiftServer(port=18085) |
273 | @@ -199,17 +186,9 @@ class TestAutopkgtestBase(TestBase): |
274 | ''' |
275 | for (pkg, fields, testsuite) in unstable_add: |
276 | self.data.add(pkg, True, fields, True, testsuite) |
277 | - self.sourceppa_cache.setdefault(pkg, {}) |
278 | - if fields['Version'] not in self.sourceppa_cache[pkg]: |
279 | - self.sourceppa_cache[pkg][fields['Version']] = '' |
280 | self.email_cache.setdefault(pkg, {}) |
281 | self.email_cache[pkg][fields['Version']] = True |
282 | |
283 | - # Set up sourceppa cache for testing |
284 | - sourceppa_path = os.path.join(self.data.dirs[True], 'SourcePPA') |
285 | - with open(sourceppa_path, 'w', encoding='utf-8') as sourceppa: |
286 | - sourceppa.write(json.dumps(self.sourceppa_cache)) |
287 | - |
288 | email_path = os.path.join(self.data.dirs[True], 'EmailCache') |
289 | with open(email_path, 'w', encoding='utf-8') as email: |
290 | email.write(json.dumps(self.email_cache)) |
291 | @@ -333,7 +312,6 @@ class AT(TestAutopkgtestBase): |
292 | ''' |
293 | |
294 | self.data.add_default_packages() |
295 | - self.sourceppa_cache['purple'] = {'2': ''} |
296 | |
297 | # The package has passed before on i386 |
298 | self.set_results({'autopkgtest-testing': { |
299 | @@ -854,8 +832,6 @@ class AT(TestAutopkgtestBase): |
300 | |
301 | self.data.add_default_packages(green=False) |
302 | |
303 | - self.sourceppa_cache['lime'] = {'1': ''} |
304 | - |
305 | self.data.add_src('lime', True, {'Version': '1', 'Testsuite': 'autopkgtest'}) |
306 | exc = self.run_it( |
307 | # unbuilt unstable version |
308 | diff --git a/tests/test_email.py b/tests/test_email.py |
309 | index 03d4305..1f21e0e 100755 |
310 | --- a/tests/test_email.py |
311 | +++ b/tests/test_email.py |
312 | @@ -23,8 +23,7 @@ sys.path.insert(0, PROJECT_DIR) |
313 | from britney2.policies.policy import PolicyVerdict |
314 | from britney2.policies.email import EmailPolicy, person_chooser, address_chooser |
315 | |
316 | -from tests.test_sourceppa import FakeOptions |
317 | -from tests import TestBase |
318 | +from tests import FakeOptions, TestBase |
319 | from tests.mock_smtpd import FakeSMTPServer |
320 | |
321 | # Example of a direct upload by core dev: openstack-doc-tools 1.5.0-0ubuntu1 |
322 | @@ -396,7 +395,6 @@ class ET(TestBase): |
323 | self.age_file = os.path.join(self.data.dirs[False], "Dates") |
324 | self.urgency_file = os.path.join(self.data.dirs[False], "Urgency") |
325 | self.email_cache_file = os.path.join(self.data.dirs[True], "EmailCache") |
326 | - self.sourceppa_cache = {} |
327 | self.email_cache = {} |
328 | |
329 | self.data.add("libc6", False) |
330 | @@ -414,9 +412,6 @@ class ET(TestBase): |
331 | ET.smtpd.emails.clear() |
332 | for (pkg, fields, daysold, emails) in unstable_add: |
333 | self.data.add(pkg, True, fields, True, None) |
334 | - self.sourceppa_cache.setdefault(pkg, {}) |
335 | - if fields["Version"] not in self.sourceppa_cache[pkg]: |
336 | - self.sourceppa_cache[pkg][fields["Version"]] = "" |
337 | with open(self.age_file, "w") as f: |
338 | import time |
339 | |
340 | @@ -428,11 +423,6 @@ class ET(TestBase): |
341 | d[pkg][fields["Version"]] = (emails, 0) |
342 | f.write(json.dumps(d)) |
343 | |
344 | - # Set up sourceppa cache for testing |
345 | - sourceppa_path = os.path.join(self.data.dirs[True], "SourcePPA") |
346 | - with open(sourceppa_path, "w", encoding="utf-8") as sourceppa: |
347 | - sourceppa.write(json.dumps(self.sourceppa_cache)) |
348 | - |
349 | (excuses_yaml, excuses_html, out) = self.run_britney() |
350 | |
351 | # convert excuses to source indexed dict |
352 | diff --git a/tests/test_lpexcusebugs.py b/tests/test_lpexcusebugs.py |
353 | index e6bce78..1b14014 100755 |
354 | --- a/tests/test_lpexcusebugs.py |
355 | +++ b/tests/test_lpexcusebugs.py |
356 | @@ -10,7 +10,6 @@ from collections import defaultdict |
357 | |
358 | import calendar |
359 | import fileinput |
360 | -import json |
361 | import os |
362 | import pprint |
363 | import sys |
364 | @@ -25,7 +24,6 @@ sys.path.insert(0, PROJECT_DIR) |
365 | from britney2.policies.policy import PolicyVerdict |
366 | from britney2.policies.email import EmailPolicy, person_chooser, address_chooser |
367 | |
368 | -from tests.test_sourceppa import FakeOptions |
369 | from tests import TestBase |
370 | |
371 | |
372 | @@ -63,7 +61,6 @@ class ET(TestBase): |
373 | ): |
374 | sys.stdout.write(line) |
375 | self.excuse_bugs_file = os.path.join(self.data.dirs[True], "ExcuseBugs") |
376 | - self.sourceppa_cache = {} |
377 | |
378 | self.data.add("libc6", False) |
379 | |
380 | @@ -80,19 +77,11 @@ class ET(TestBase): |
381 | """ |
382 | for (pkg, fields, bugs) in unstable_add: |
383 | self.data.add(pkg, True, fields, True, None) |
384 | - self.sourceppa_cache.setdefault(pkg, {}) |
385 | - if fields["Version"] not in self.sourceppa_cache[pkg]: |
386 | - self.sourceppa_cache[pkg][fields["Version"]] = "" |
387 | print("Writing to %s" % self.excuse_bugs_file) |
388 | with open(self.excuse_bugs_file, "w") as f: |
389 | for (bug, ts) in bugs: |
390 | f.write("%s %s %s" % (pkg, bug, ts)) |
391 | |
392 | - # Set up sourceppa cache for testing |
393 | - sourceppa_path = os.path.join(self.data.dirs[True], "SourcePPA") |
394 | - with open(sourceppa_path, "w", encoding="utf-8") as sourceppa: |
395 | - sourceppa.write(json.dumps(self.sourceppa_cache)) |
396 | - |
397 | (excuses_yaml, excuses_html, out) = self.run_britney() |
398 | |
399 | bugs_blocked_by = [] |
400 | diff --git a/tests/test_sourceppa.py b/tests/test_sourceppa.py |
401 | deleted file mode 100755 |
402 | index 61c6c5a..0000000 |
403 | --- a/tests/test_sourceppa.py |
404 | +++ /dev/null |
405 | @@ -1,404 +0,0 @@ |
406 | -#!/usr/bin/python3 |
407 | -# (C) 2016 Canonical Ltd. |
408 | -# |
409 | -# This program is free software; you can redistribute it and/or modify |
410 | -# it under the terms of the GNU General Public License as published by |
411 | -# the Free Software Foundation; either version 2 of the License, or |
412 | -# (at your option) any later version. |
413 | - |
414 | -import json |
415 | -import os |
416 | -import sys |
417 | -import unittest |
418 | -from unittest.mock import DEFAULT, patch |
419 | - |
420 | -PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
421 | -sys.path.insert(0, PROJECT_DIR) |
422 | - |
423 | -from britney2 import Suite, SuiteClass |
424 | -from britney2.excuse import Excuse |
425 | -from britney2.hints import HintCollection |
426 | -from britney2.migrationitem import MigrationItem |
427 | -from britney2.policies.policy import PolicyEngine, PolicyVerdict |
428 | -from britney2.policies.sourceppa import LAUNCHPAD_URL, SourcePPAPolicy |
429 | - |
430 | -# We want to reuse run_it |
431 | -from tests.test_autopkgtest import TestAutopkgtestBase, tr |
432 | - |
433 | - |
434 | -CACHE_FILE = os.path.join(PROJECT_DIR, "tests", "data", "sourceppa.json") |
435 | - |
436 | - |
437 | -class FakeOptions: |
438 | - distribution = "testbuntu" |
439 | - series = "zazzy" |
440 | - unstable = "/tmp" |
441 | - verbose = False |
442 | - |
443 | - |
444 | -class FakeExcuse(Excuse): |
445 | - def __init__(self, name, suite): |
446 | - self.item = MigrationItem(package=name, version="2.0", suite=suite) |
447 | - Excuse.__init__(self, self.item) |
448 | - self.policy_verdict = PolicyVerdict.PASS |
449 | - |
450 | - |
451 | -SOURCE_SUITE = Suite(SuiteClass.PRIMARY_SOURCE_SUITE, "fakename", "fakepath") |
452 | - |
453 | -PAL = FakeExcuse("pal", SOURCE_SUITE) |
454 | -BUDDY = FakeExcuse("buddy", SOURCE_SUITE) |
455 | -FRIEND = FakeExcuse("friend", SOURCE_SUITE) |
456 | -NOPPA = FakeExcuse("noppa", SOURCE_SUITE) |
457 | - |
458 | - |
459 | -class FakeBritney: |
460 | - def __init__(self): |
461 | - self._policy = SourcePPAPolicy(FakeOptions, {}) |
462 | - self._policy.filename = CACHE_FILE |
463 | - self._policy_engine = PolicyEngine() |
464 | - self._policy_engine.add_policy(self._policy) |
465 | - self._policy_engine.initialise(self, HintCollection()) |
466 | - |
467 | - |
468 | -class FakeData: |
469 | - version = "2.0" |
470 | - |
471 | - |
472 | -class T(unittest.TestCase): |
473 | - maxDiff = None |
474 | - |
475 | - @patch("britney2.policies.sourceppa.urllib.request.urlopen") |
476 | - def test_lp_rest_api_no_entries(self, urlopen): |
477 | - """Don't explode if LP reports no entries match pkg/version""" |
478 | - context = urlopen.return_value.__enter__.return_value |
479 | - context.getcode.return_value = 200 |
480 | - context.read.return_value = b'{"entries": []}' |
481 | - pol = SourcePPAPolicy(FakeOptions, {}) |
482 | - self.assertEqual(pol.lp_get_source_ppa("hello", "1.0"), "IndexError") |
483 | - |
484 | - @patch("britney2.policies.sourceppa.urllib.request.urlopen") |
485 | - def test_lp_rest_api_no_source_ppa(self, urlopen): |
486 | - """Identify when package has no source PPA""" |
487 | - context = urlopen.return_value.__enter__.return_value |
488 | - context.getcode.return_value = 200 |
489 | - context.read.return_value = b'{"entries": [{"self_link": "https://api.launchpad.net/1.0/ubuntu/+archive/primary/+sourcepub/12345", "build_link": "https://api.launchpad.net/1.0/ubuntu/+source/gcc-5/5.4.1-7ubuntu1/+build/12066956", "other_stuff": "ignored"}]}' |
490 | - pol = SourcePPAPolicy(FakeOptions, {}) |
491 | - self.assertEqual(pol.lp_get_source_ppa("hello", "1.0"), "") |
492 | - |
493 | - @patch("britney2.policies.sourceppa.urllib.request.urlopen") |
494 | - def test_lp_rest_api_with_source_ppa(self, urlopen): |
495 | - """Identify source PPA""" |
496 | - context = urlopen.return_value.__enter__.return_value |
497 | - context.getcode.return_value = 200 |
498 | - context.read.return_value = b'{"entries": [{"self_link": "https://api.launchpad.net/1.0/ubuntu/+archive/primary/+sourcepub/12345", "build_link": "https://api.launchpad.net/1.0/~ci-train-ppa-service/+archive/ubuntu/2516/+build/12063031", "other_stuff": "ignored"}]}' |
499 | - pol = SourcePPAPolicy(FakeOptions, {}) |
500 | - self.assertEqual( |
501 | - pol.lp_get_source_ppa("hello", "1.0"), |
502 | - "https://api.launchpad.net/1.0/~ci-train-ppa-service/+archive/ubuntu/2516", |
503 | - ) |
504 | - |
505 | - @patch("britney2.policies.sourceppa.urllib.request.urlopen") |
506 | - def test_lp_rest_api_errors(self, urlopen): |
507 | - """Report errors instead of swallowing them""" |
508 | - context = urlopen.return_value.__enter__.return_value |
509 | - context.getcode.return_value = 500 |
510 | - context.read.return_value = b"" |
511 | - pol = SourcePPAPolicy(FakeOptions, {}) |
512 | - with self.assertRaisesRegex(ConnectionError, "HTTP 500"): |
513 | - pol.lp_get_source_ppa("hello", "1.0") |
514 | - # Yes, I have really seen "success with no json returned" in the wild |
515 | - context.getcode.return_value = 200 |
516 | - context.read.return_value = b"" |
517 | - with self.assertRaisesRegex(ValueError, "Expecting value"): |
518 | - pol.lp_get_source_ppa("hello", "1.0") |
519 | - |
520 | - @patch("britney2.policies.sourceppa.urllib.request.urlopen") |
521 | - def test_lp_rest_api_timeout(self, urlopen): |
522 | - """If we get a timeout connecting to LP, we try 5 times""" |
523 | - import socket |
524 | - |
525 | - # test that we're retried 5 times on timeout |
526 | - urlopen.side_effect = socket.timeout |
527 | - pol = SourcePPAPolicy(FakeOptions, {}) |
528 | - with self.assertRaises(socket.timeout): |
529 | - pol.lp_get_source_ppa("hello", "1.0") |
530 | - self.assertEqual(urlopen.call_count, 5) |
531 | - |
532 | - @patch("britney2.policies.sourceppa.urllib.request.urlopen") |
533 | - def test_lp_rest_api_unavailable(self, urlopen): |
534 | - """If we get a 503 connecting to LP, we try 5 times""" |
535 | - from urllib.error import HTTPError |
536 | - |
537 | - # test that we're retried 5 times on 503 |
538 | - urlopen.side_effect = HTTPError( |
539 | - None, 503, "Service Temporarily Unavailable", None, None |
540 | - ) |
541 | - pol = SourcePPAPolicy(FakeOptions, {}) |
542 | - with self.assertRaises(HTTPError): |
543 | - pol.lp_get_source_ppa("hello", "1.0") |
544 | - self.assertEqual(urlopen.call_count, 5) |
545 | - |
546 | - @patch("britney2.policies.sourceppa.urllib.request.urlopen") |
547 | - def test_lp_rest_api_flaky(self, urlopen): |
548 | - """If we get a 503, then a 200, we get the right result""" |
549 | - from urllib.error import HTTPError |
550 | - |
551 | - def fail_for_a_bit(): |
552 | - for i in range(3): |
553 | - yield HTTPError( |
554 | - None, 503, "Service Temporarily Unavailable", None, None |
555 | - ) |
556 | - while True: |
557 | - yield DEFAULT |
558 | - |
559 | - context = urlopen.return_value.__enter__.return_value |
560 | - context.getcode.return_value = 200 |
561 | - context.read.return_value = b'{"entries": [{"self_link": "https://api.launchpad.net/1.0/ubuntu/+archive/primary/+sourcepub/12345", "build_link": "https://api.launchpad.net/1.0/~ci-train-ppa-service/+archive/ubuntu/2516/+build/12063031", "other_stuff": "ignored"}]}' |
562 | - urlopen.side_effect = fail_for_a_bit() |
563 | - pol = SourcePPAPolicy(FakeOptions, {}) |
564 | - pol.lp_get_source_ppa("hello", "1.0") |
565 | - self.assertEqual(urlopen.call_count, 5) |
566 | - self.assertEqual( |
567 | - pol.lp_get_source_ppa("hello", "1.0"), |
568 | - "https://api.launchpad.net/1.0/~ci-train-ppa-service/+archive/ubuntu/2516", |
569 | - ) |
570 | - |
571 | - def test_approve_ppa(self): |
572 | - """Approve packages by their PPA.""" |
573 | - shortppa = "~ci-train-ppa-service/+archive/NNNN" |
574 | - brit = FakeBritney() |
575 | - for excuse in (PAL, BUDDY, FRIEND, NOPPA): |
576 | - brit._policy_engine.apply_src_policies( |
577 | - excuse.item, FakeData, FakeData, excuse |
578 | - ) |
579 | - self.assertEqual(excuse.policy_verdict, PolicyVerdict.PASS) |
580 | - output = FRIEND.policy_info["source-ppa"] |
581 | - self.assertDictContainsSubset( |
582 | - dict(pal=shortppa, buddy=shortppa, friend=shortppa), output |
583 | - ) |
584 | - |
585 | - def test_ignore_ppa(self): |
586 | - """Ignore packages in non-bileto PPAs.""" |
587 | - shortppa = "~kernel-or-whatever/+archive/ppa" |
588 | - brit = FakeBritney() |
589 | - for name, versions in brit._policy.cache.items(): |
590 | - for version in versions: |
591 | - brit._policy.cache[name][version] = shortppa |
592 | - for excuse in (PAL, BUDDY, FRIEND, NOPPA): |
593 | - brit._policy_engine.apply_src_policies( |
594 | - excuse.item, FakeData, FakeData, excuse |
595 | - ) |
596 | - self.assertEqual(excuse.policy_verdict, PolicyVerdict.PASS) |
597 | - output = FRIEND.policy_info["source-ppa"] |
598 | - self.assertEqual(output, {"verdict": "PASS"}) |
599 | - |
600 | - def test_reject_ppa(self): |
601 | - """Reject packages by their PPA.""" |
602 | - shortppa = "~ci-train-ppa-service/+archive/NNNN" |
603 | - brit = FakeBritney() |
604 | - excuse = BUDDY |
605 | - excuse.policy_verdict = PolicyVerdict.REJECTED_PERMANENTLY |
606 | - # Just buddy is invalid but whole ppa fails |
607 | - |
608 | - # This one passes because the rejection isn't known yet |
609 | - excuse = PAL |
610 | - brit._policy_engine.apply_src_policies( |
611 | - excuse.item, FakeData, FakeData, excuse |
612 | - ) |
613 | - self.assertEqual(excuse.policy_verdict, PolicyVerdict.PASS) |
614 | - # This one fails because it is itself invalid. |
615 | - excuse = BUDDY |
616 | - brit._policy_engine.apply_src_policies( |
617 | - excuse.item, FakeData, FakeData, excuse |
618 | - ) |
619 | - self.assertEqual( |
620 | - excuse.policy_verdict, PolicyVerdict.REJECTED_PERMANENTLY |
621 | - ) |
622 | - # This one fails because buddy failed before it. |
623 | - excuse = FRIEND |
624 | - brit._policy_engine.apply_src_policies( |
625 | - excuse.item, FakeData, FakeData, excuse |
626 | - ) |
627 | - self.assertEqual( |
628 | - excuse.policy_verdict, |
629 | - PolicyVerdict.REJECTED_WAITING_FOR_ANOTHER_ITEM, |
630 | - ) |
631 | - # 'noppa' not from PPA so not rejected |
632 | - excuse = NOPPA |
633 | - brit._policy_engine.apply_src_policies( |
634 | - excuse.item, FakeData, FakeData, excuse |
635 | - ) |
636 | - self.assertEqual(excuse.policy_verdict, PolicyVerdict.PASS) |
637 | - # All are rejected however |
638 | - for excuse in (PAL, BUDDY, FRIEND): |
639 | - self.assertFalse(excuse.is_valid) |
640 | - self.assertDictEqual( |
641 | - brit._policy.excuses_by_source_ppa, |
642 | - {LAUNCHPAD_URL + shortppa: {PAL, BUDDY, FRIEND}}, |
643 | - ) |
644 | - output = FRIEND.policy_info["source-ppa"] |
645 | - self.assertDictEqual( |
646 | - dict( |
647 | - pal=shortppa, |
648 | - buddy=shortppa, |
649 | - friend=shortppa, |
650 | - verdict="REJECTED_WAITING_FOR_ANOTHER_ITEM", |
651 | - ), |
652 | - output, |
653 | - ) |
654 | - |
655 | - output = BUDDY.policy_info["source-ppa"] |
656 | - self.assertDictEqual( |
657 | - dict( |
658 | - pal=shortppa, |
659 | - buddy=shortppa, |
660 | - friend=shortppa, |
661 | - verdict="REJECTED_PERMANENTLY" |
662 | - ), |
663 | - output, |
664 | - ) |
665 | - |
666 | - |
667 | -class AT(TestAutopkgtestBase): |
668 | - """ Integration tests for source ppa grouping """ |
669 | - |
670 | - def test_sourceppa_policy(self): |
671 | - """Packages from same source PPA get rejected for failed peer policy""" |
672 | - |
673 | - self.data.add_default_packages(green=False) |
674 | - |
675 | - ppa = "devel/~ci-train-ppa-service/+archive/NNNN" |
676 | - self.sourceppa_cache["green"] = {"2": ppa} |
677 | - self.sourceppa_cache["red"] = {"2": ppa} |
678 | - with open( |
679 | - os.path.join(self.data.path, "data/unstable/Blocks"), "w" |
680 | - ) as f: |
681 | - f.write("green 12345 1471505000\ndarkgreen 98765 1471500000\n") |
682 | - |
683 | - exc = self.run_it( |
684 | - [ |
685 | - ("green", {"Version": "2"}, "autopkgtest"), |
686 | - ("red", {"Version": "2"}, "autopkgtest"), |
687 | - ("gcc-5", {}, "autopkgtest"), |
688 | - ], |
689 | - { |
690 | - "green": ( |
691 | - False, |
692 | - { |
693 | - "green": { |
694 | - "i386": "RUNNING-ALWAYSFAIL", |
695 | - "amd64": "RUNNING-ALWAYSFAIL", |
696 | - } |
697 | - }, |
698 | - ), |
699 | - "red": ( |
700 | - False, |
701 | - { |
702 | - "red": { |
703 | - "i386": "RUNNING-ALWAYSFAIL", |
704 | - "amd64": "RUNNING-ALWAYSFAIL", |
705 | - } |
706 | - }, |
707 | - ), |
708 | - "gcc-5": (True, {}), |
709 | - }, |
710 | - {"green": [("reason", "block")], "red": [("reason", "source-ppa")]}, |
711 | - )[1] |
712 | - self.assertEqual( |
713 | - exc["red"]["policy_info"]["source-ppa"], |
714 | - { |
715 | - "red": ppa, |
716 | - "green": ppa, |
717 | - "verdict": "REJECTED_WAITING_FOR_ANOTHER_ITEM", |
718 | - }, |
719 | - ) |
720 | - |
721 | - with open(os.path.join(self.data.path, "data/unstable/SourcePPA")) as f: |
722 | - res = json.load(f) |
723 | - self.assertEqual( |
724 | - res, |
725 | - {"red": {"2": ppa}, "green": {"2": ppa}, "gcc-5": {"1": ""}}, |
726 | - ) |
727 | - |
728 | - def test_sourceppa_missingbuild(self): |
729 | - """Packages from same source PPA get rejected for failed peer FTBFS""" |
730 | - |
731 | - self.data.add_default_packages(green=False) |
732 | - |
733 | - ppa = "devel/~ci-train-ppa-service/+archive/ZZZZ" |
734 | - self.sourceppa_cache["green"] = {"2": ppa} |
735 | - self.sourceppa_cache["red"] = {"2": ppa} |
736 | - |
737 | - self.data.add_src( |
738 | - "green", True, {"Version": "2", "Testsuite": "autopkgtest"} |
739 | - ) |
740 | - self.data.add( |
741 | - "libgreen1", |
742 | - True, |
743 | - {"Version": "2", "Source": "green", "Architecture": "i386"}, |
744 | - add_src=False, |
745 | - ) |
746 | - self.data.add( |
747 | - "green", |
748 | - True, |
749 | - {"Depends": "libc6 (>= 0.9), libgreen1", "Conflicts": "blue"}, |
750 | - testsuite="autopkgtest", |
751 | - add_src=False, |
752 | - ) |
753 | - |
754 | - self.swift.set_results( |
755 | - { |
756 | - "autopkgtest-testing": { |
757 | - "testing/i386/d/darkgreen/20150101_100000@": ( |
758 | - 0, |
759 | - "darkgreen 1", |
760 | - tr("green/2"), |
761 | - ), |
762 | - "testing/i386/l/lightgreen/20150101_100100@": ( |
763 | - 0, |
764 | - "lightgreen 1", |
765 | - tr("green/2"), |
766 | - ), |
767 | - "testing/i386/g/green/20150101_100200@": ( |
768 | - 0, |
769 | - "green 2", |
770 | - tr("green/2"), |
771 | - ), |
772 | - } |
773 | - } |
774 | - ) |
775 | - |
776 | - exc = self.run_it( |
777 | - [("red", {"Version": "2"}, "autopkgtest")], |
778 | - {"green": (False, {}), "red": (False, {})}, |
779 | - { |
780 | - "green": [ |
781 | - ( |
782 | - "missing-builds", |
783 | - { |
784 | - "on-architectures": [ |
785 | - "amd64", |
786 | - "arm64", |
787 | - "armhf", |
788 | - "powerpc", |
789 | - "ppc64el", |
790 | - ], |
791 | - "on-unimportant-architectures": [], |
792 | - }, |
793 | - ) |
794 | - ], |
795 | - "red": [("reason", "source-ppa")], |
796 | - }, |
797 | - )[1] |
798 | - self.assertEqual( |
799 | - exc["red"]["policy_info"]["source-ppa"], |
800 | - { |
801 | - "red": ppa, |
802 | - "green": ppa, |
803 | - "verdict": "REJECTED_WAITING_FOR_ANOTHER_ITEM", |
804 | - }, |
805 | - ) |
806 | - |
807 | - |
808 | -if __name__ == "__main__": |
809 | - unittest.main() |
810 | diff --git a/tests/test_sruadtregression.py b/tests/test_sruadtregression.py |
811 | index 121bacf..2e1dc80 100755 |
812 | --- a/tests/test_sruadtregression.py |
813 | +++ b/tests/test_sruadtregression.py |
814 | @@ -20,7 +20,6 @@ sys.path.insert(0, PROJECT_DIR) |
815 | |
816 | from britney2.policies.policy import PolicyVerdict |
817 | from britney2.policies.sruadtregression import SRUADTRegressionPolicy |
818 | -from tests.test_sourceppa import FakeBritney |
819 | |
820 | |
821 | FAKE_CHANGES = b"""Format: 1.8 |
822 | @@ -501,7 +500,7 @@ class T(unittest.TestCase): |
823 | with open(state_path, "w") as f: |
824 | json.dump(state, f) |
825 | pol = SRUADTRegressionPolicy(options, {}) |
826 | - pol.initialise(FakeBritney()) |
827 | + pol.initialise(None) |
828 | # Check if the stale packages got purged and others not |
829 | expected_state = { |
830 | "testbuntu": { |
831 | diff --git a/tests/test_yaml.py b/tests/test_yaml.py |
832 | index d27d6e0..796eba6 100755 |
833 | --- a/tests/test_yaml.py |
834 | +++ b/tests/test_yaml.py |
835 | @@ -7,7 +7,6 @@ |
836 | # (at your option) any later version. |
837 | |
838 | import fileinput |
839 | -import json |
840 | import os |
841 | import pprint |
842 | import sys |
843 | @@ -42,13 +41,8 @@ class YamlTest(TestBase): |
844 | sys.stdout.write(line) |
845 | |
846 | self.data.add('libc6', False) |
847 | - self.sourceppa_cache = {} |
848 | |
849 | self.email_cache = {} |
850 | - for pkg, vals in self.sourceppa_cache.items(): |
851 | - for version, empty in vals.items(): |
852 | - self.email_cache.setdefault(pkg, {}) |
853 | - self.email_cache[pkg][version] = True |
854 | |
855 | # create mock Swift server (but don't start it yet, as tests first need |
856 | # to poke in results) |
857 | @@ -72,19 +66,11 @@ class YamlTest(TestBase): |
858 | 'age-policy-dates') |
859 | for (pkg, fields, daysold) in unstable_add: |
860 | self.data.add(pkg, True, fields, True, None) |
861 | - self.sourceppa_cache.setdefault(pkg, {}) |
862 | - if fields['Version'] not in self.sourceppa_cache[pkg]: |
863 | - self.sourceppa_cache[pkg][fields['Version']] = '' |
864 | with open(age_file, 'w') as f: |
865 | import time |
866 | do = time.time() - (60 * 60 * 24 * daysold) |
867 | f.write('%s %s %d' % (pkg, fields['Version'], do)) |
868 | |
869 | - # Set up sourceppa cache for testing |
870 | - sourceppa_path = os.path.join(self.data.dirs[True], 'SourcePPA') |
871 | - with open(sourceppa_path, 'w', encoding='utf-8') as sourceppa: |
872 | - sourceppa.write(json.dumps(self.sourceppa_cache)) |
873 | - |
874 | (excuses_yaml, excuses_html, out) = self.run_britney() |
875 | |
876 | # convert excuses to source indexed dict |