Merge lp:~mwhudson/ubuntu-archive-scripts/rcbuggy-deployment-fun into lp:ubuntu-archive-scripts

Proposed by Michael Hudson-Doyle
Status: Merged
Merged at revision: 245
Proposed branch: lp:~mwhudson/ubuntu-archive-scripts/rcbuggy-deployment-fun
Merge into: lp:ubuntu-archive-scripts
Diff against target: 257 lines (+117/-45)
2 files modified
find-rcbuggy-problem-packages (+115/-43)
templates/rcbuggy-problem-packages.html (+2/-2)
To merge this branch: bzr merge lp:~mwhudson/ubuntu-archive-scripts/rcbuggy-deployment-fun
Reviewer Review Type Date Requested Status
Ubuntu Package Archive Administrators Pending
Review via email: mp+372665@code.launchpad.net

Description of the change

This time for sure? Should use the chdists properly, does not depend on reverse-depends any more. The uninstallability testing might not work because there are no such cases currently...

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'find-rcbuggy-problem-packages'
2--- find-rcbuggy-problem-packages 2019-09-11 01:33:41 +0000
3+++ find-rcbuggy-problem-packages 2019-09-12 03:12:18 +0000
4@@ -62,10 +62,13 @@
5 cp = subprocess.run(cmd, **kw)
6 return cp.stdout.decode(encoding).strip()
7
8-def extract_uninstallable_to_src_pkg(output_fp):
9- # Extract a mapping from binary package name to the set of source
10- # packages whose migration from proposed makes that package
11- # uninstallable.
12+all_arches = set()
13+
14+def extract_bin_pkg_arch_to_blocked_src_pkgs(output_fp):
15+ # Extract a mapping from binary package name / architectures to
16+ # source package the migration of which would make that package
17+ # uninstallable (and for convenience, return all architectures
18+ # used as keys -- usually there will only be one or two).
19
20 # We're looking for sequences of lines like this:
21
22@@ -76,11 +79,31 @@
23 # (Britney tries to migrate batches of packages but it always
24 # tries each package on its own as well).
25
26- r = {}
27+ # For each potential migration, britney checks architectures in
28+ # sequence and stops when it finds one that regresses (or proceeds
29+ # with the migration if it doesn't find one). This means that we
30+ # can miss blocking packages here --- for example if migrating $src
31+ # would make say $binpkg/amd64 uninstallable, but britney happens
32+ # to check arm64 -- where $binpkg does not exist -- and there are
33+ # regressions there, we will never find out about the problem
34+ # $binpkg causes. This isn't really too bad because clearly in
35+ # this case the migration of $src is blocked by other things that
36+ # need to be resolved, but it does mean that packages might appear
37+ # and disapper from the report depending on the order that britney
38+ # checks architectures in (which is not consistent from run to
39+ # run). C'est la vie.
40+
41+ bin_pkg_arch_to_blocked_src_pkgs = {}
42 srcpkg = None
43+ arch_prefix = "Arch order is: "
44 for line in output_fp:
45- parts = line.split()
46+ line = line.strip()
47+ if line.startswith(arch_prefix):
48+ all_arches.update(line[len(arch_prefix):].split(', '))
49+ parts = line.split(None, 2)
50 if len(parts) >= 2:
51+ if parts[0] in {"Trying", "trying"}:
52+ srcpkg = None
53 if parts[0] == 'skipped:':
54 srcpkg = None
55 # If parts[2] is '(' then this line is about trying to
56@@ -88,13 +111,26 @@
57 # looking for.
58 if parts[2].startswith('('):
59 srcpkg = parts[1]
60- if srcpkg is not None and parts[0] == '*':
61+ if srcpkg is not None and srcpkg[0] != '-' and parts[0] == '*':
62 # parts[1] is "${arch}:"
63 # parts[2:] is a comma+space separated list of binary package names.
64- for binpkg in parts[2:]:
65- binpkg = binpkg.strip(',')
66- r.setdefault(binpkg, set()).add(srcpkg)
67- return r
68+ arch = parts[1][:-1]
69+ for binpkg in parts[2].split(', '):
70+ bin_pkg_arch_to_blocked_src_pkgs.setdefault(
71+ (binpkg, arch), set()).add(srcpkg)
72+ return bin_pkg_arch_to_blocked_src_pkgs
73+
74+
75+def chdist_grep_dctrl_packages(arch, *args):
76+ return run_output(
77+ "chdist", "grep-dctrl-packages", "{}-{}".format(series, arch),
78+ "-nsPackage", *args, check=False).splitlines()
79+
80+
81+def chdist_grep_dctrl_sources(arch, *args):
82+ return run_output(
83+ "chdist", "grep-dctrl-sources", "{}-{}".format(series, arch),
84+ "-nsPackage", *args, check=False).splitlines()
85
86
87 @attr.s
88@@ -102,9 +138,66 @@
89 source_package_name = attr.ib()
90 bugs = attr.ib()
91 block_by_regression = attr.ib(default=attr.Factory(set))
92- block_by_uninstallability = attr.ib(default=attr.Factory(list))
93+ block_by_uninstallability = attr.ib(default=attr.Factory(set))
94 suites = attr.ib(default=attr.Factory(set))
95 _rdeps_lines = attr.ib(default=None)
96+ _binpkgs = attr.ib(default=None)
97+
98+ def binary_pkgs(self):
99+ if self._binpkgs is None:
100+ self._binpkgs = set()
101+ for arch in all_arches:
102+ arch_binpkgs = chdist_grep_dctrl_packages(
103+ arch, "-wS", self.source_package_name)
104+ self._binpkgs.update({(binpkg, arch) for binpkg in arch_binpkgs})
105+ return self._binpkgs
106+
107+ def reverse_depends(self):
108+ if self._rdeps_lines is None:
109+ # These are maps rdep -> binpkg -> arches
110+ reverse_recommends = {}
111+ reverse_depends = {}
112+ # This just maps rbdep -> binpkgs
113+ reverse_build_depends = {}
114+ for binpkg, arch in self.binary_pkgs():
115+ for rec in chdist_grep_dctrl_packages(
116+ arch, "-wFRecommends", binpkg):
117+ if (rec, arch) in self.binary_pkgs():
118+ continue
119+ reverse_recommends.setdefault(rec, {}).setdefault(binpkg, set()).add(arch)
120+ for dep in chdist_grep_dctrl_packages(
121+ arch, "-wFDepends", binpkg):
122+ if (dep, arch) in self.binary_pkgs():
123+ continue
124+ reverse_depends.setdefault(dep, {}).setdefault(binpkg, set()).add(arch)
125+ for bdeb in chdist_grep_dctrl_sources(
126+ arch, "-wFBuild-Depends", binpkg, "--or", "-wFBuild-Depends-Indep", binpkg):
127+ reverse_build_depends.setdefault(bdeb, set()).add(binpkg)
128+ self._rdeps_lines = []
129+ if reverse_depends:
130+ self._rdeps_lines.append("Reverse-Depends")
131+ for rdep in sorted(reverse_depends):
132+ for binpkg in sorted(reverse_depends[rdep]):
133+ if reverse_depends[rdep][binpkg] == all_arches:
134+ arches = "all architectures"
135+ else:
136+ arches = ", ".join(reverse_depends[rdep][binpkg])
137+ self._rdeps_lines.append(" ".join(["*", rdep, "for", binpkg, "on", arches]))
138+ if reverse_recommends:
139+ self._rdeps_lines.append("Reverse-Recommends")
140+ for rdep in sorted(reverse_recommends):
141+ for binpkg in sorted(reverse_recommends[rdep]):
142+ if reverse_recommends[rdep][binpkg] == all_arches:
143+ arches = "all architectures"
144+ else:
145+ arches = ", ".join(reverse_recommends[rdep][binpkg])
146+ self._rdeps_lines.append(" ".join(["*", rdep, "for", binpkg, "on", arches]))
147+ if reverse_build_depends:
148+ self._rdeps_lines.append("Reverse-Build-Depends")
149+ for rdep in sorted(reverse_build_depends):
150+ for binpkg in sorted(reverse_build_depends[rdep]):
151+ self._rdeps_lines.append(" ".join(["*", rdep, "for", binpkg]))
152+ return self._rdeps_lines
153
154 @property
155 def comment(self):
156@@ -119,32 +212,12 @@
157 return comment
158
159 @property
160- def rdeps_lines(self):
161- if self._rdeps_lines is None:
162- rdeps = run_output("reverse-depends", 'src:' + self.source_package_name)
163- rbdeps = run_output("reverse-depends", '-b', 'src:' + self.source_package_name)
164-
165- if rdeps == 'No reverse dependencies found':
166- rdeps = ''
167- if rbdeps == 'No reverse dependencies found':
168- rbdeps = ''
169-
170- if rdeps or rbdeps:
171- if rdeps and rbdeps:
172- self._rdeps_lines = (rdeps + '\n' + rbdeps).splitlines()
173- else:
174- self._rdeps_lines = (rdeps + rbdeps).splitlines()
175- else:
176- self._rdeps_lines = []
177- return self._rdeps_lines
178-
179- @property
180 def rdeps_text_short(self):
181- return "\n".join(self.rdeps_lines[:10])
182+ return "\n".join(self.reverse_depends()[:10])
183
184 @property
185 def rdeps_text_more(self):
186- return "\n".join(self.rdeps_lines[10:])
187+ return "\n".join(self.reverse_depends()[10:])
188
189 @property
190 def removal_commands(self):
191@@ -154,14 +227,14 @@
192 cmds = []
193 for suite in suites:
194 cmd = " ".join(["remove-package", "-s", suite, "-m", shlex.quote(self.comment), self.source_package_name])
195- if self.rdeps_lines:
196+ if self.reverse_depends():
197 cmd = '#' + cmd
198 cmds.append(cmd)
199 return cmds
200
201 @property
202 def css_class(self):
203- if self.rdeps_lines:
204+ if self.reverse_depends():
205 return 'removal-not-ok'
206 else:
207 return 'removal-ok'
208@@ -178,7 +251,7 @@
209 with open(args.ubuntu_excuses) as fp:
210 ubuntu_excuses = yaml.load(fp, Loader=yaml.CSafeLoader)
211 with open(args.ubuntu_update_output) as fp:
212- uninstallable_to_src_pkg = extract_uninstallable_to_src_pkg(fp)
213+ bin_pkg_arch_to_blocked_src_pkgs = extract_bin_pkg_arch_to_blocked_src_pkgs(fp)
214 with open(args.debian_excuses) as fp:
215 debian_excuses = yaml.load(fp, Loader=yaml.CSafeLoader)
216
217@@ -219,18 +292,17 @@
218 if source['old-version'] != '-':
219 rc_gones[item].suites.add(series)
220 print("checking uninstallability")
221- for pkg in rc_gones:
222- if pkg not in in_proposed_by_autopkgtest_or_missing_binaries:
223+ for rc_gone in rc_gones.values():
224+ if rc_gone.source_package_name not in in_proposed_by_autopkgtest_or_missing_binaries:
225 continue
226- bin_pkgs = run_output("chdist", "grep-dctrl-packages", series, "-SwnsPackage", pkg, check=False)
227- for bin_pkg in set(bin_pkgs.splitlines()):
228- rc_gones[pkg].block_by_uninstallability.extend(uninstallable_to_src_pkg.get(bin_pkg, []))
229+ for bin_pkg, arch in set(rc_gone.binary_pkgs()):
230+ rc_gone.block_by_uninstallability.update(bin_pkg_arch_to_blocked_src_pkgs.get((bin_pkg, arch), set()))
231 print("finding reverse-deps")
232 packages = []
233 for _, rc_gone in sorted(rc_gones.items()):
234 if not rc_gone.block_by_regression and not rc_gone.block_by_uninstallability:
235 continue
236- rc_gone.rdeps_lines
237+ rc_gone.reverse_depends()
238 packages.append(rc_gone)
239
240 print("rendering")
241
242=== modified file 'templates/rcbuggy-problem-packages.html'
243--- templates/rcbuggy-problem-packages.html 2019-09-09 01:48:46 +0000
244+++ templates/rcbuggy-problem-packages.html 2019-09-12 03:12:18 +0000
245@@ -62,10 +62,10 @@
246 {% endif %}
247 {% if package.block_by_uninstallability %}
248 <p>
249- At least one binary from this package is made uninstallable by the versions of {{ package.block_by_uninstallability|join(", ") }} in -proposed.
250+ At least one binary from this package is made uninstallable by the versions of {{ package.block_by_uninstallability|sort|join(", ") }} in -proposed.
251 </p>
252 {% endif %}
253- {% if package.rdeps_lines %}
254+ {% if package._rdeps_lines %}
255 <pre class="rdeps">
256 {{ package.rdeps_text_short }}
257 {% if package.rdeps_text_more -%}

Subscribers

People subscribed via source and target branches