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
=== modified file 'find-rcbuggy-problem-packages'
--- find-rcbuggy-problem-packages 2019-09-11 01:33:41 +0000
+++ find-rcbuggy-problem-packages 2019-09-12 03:12:18 +0000
@@ -62,10 +62,13 @@
62 cp = subprocess.run(cmd, **kw)62 cp = subprocess.run(cmd, **kw)
63 return cp.stdout.decode(encoding).strip()63 return cp.stdout.decode(encoding).strip()
6464
65def extract_uninstallable_to_src_pkg(output_fp):65all_arches = set()
66 # Extract a mapping from binary package name to the set of source66
67 # packages whose migration from proposed makes that package67def extract_bin_pkg_arch_to_blocked_src_pkgs(output_fp):
68 # uninstallable.68 # Extract a mapping from binary package name / architectures to
69 # source package the migration of which would make that package
70 # uninstallable (and for convenience, return all architectures
71 # used as keys -- usually there will only be one or two).
6972
70 # We're looking for sequences of lines like this:73 # We're looking for sequences of lines like this:
7174
@@ -76,11 +79,31 @@
76 # (Britney tries to migrate batches of packages but it always79 # (Britney tries to migrate batches of packages but it always
77 # tries each package on its own as well).80 # tries each package on its own as well).
7881
79 r = {}82 # For each potential migration, britney checks architectures in
83 # sequence and stops when it finds one that regresses (or proceeds
84 # with the migration if it doesn't find one). This means that we
85 # can miss blocking packages here --- for example if migrating $src
86 # would make say $binpkg/amd64 uninstallable, but britney happens
87 # to check arm64 -- where $binpkg does not exist -- and there are
88 # regressions there, we will never find out about the problem
89 # $binpkg causes. This isn't really too bad because clearly in
90 # this case the migration of $src is blocked by other things that
91 # need to be resolved, but it does mean that packages might appear
92 # and disapper from the report depending on the order that britney
93 # checks architectures in (which is not consistent from run to
94 # run). C'est la vie.
95
96 bin_pkg_arch_to_blocked_src_pkgs = {}
80 srcpkg = None97 srcpkg = None
98 arch_prefix = "Arch order is: "
81 for line in output_fp:99 for line in output_fp:
82 parts = line.split()100 line = line.strip()
101 if line.startswith(arch_prefix):
102 all_arches.update(line[len(arch_prefix):].split(', '))
103 parts = line.split(None, 2)
83 if len(parts) >= 2:104 if len(parts) >= 2:
105 if parts[0] in {"Trying", "trying"}:
106 srcpkg = None
84 if parts[0] == 'skipped:':107 if parts[0] == 'skipped:':
85 srcpkg = None108 srcpkg = None
86 # If parts[2] is '(' then this line is about trying to109 # If parts[2] is '(' then this line is about trying to
@@ -88,13 +111,26 @@
88 # looking for.111 # looking for.
89 if parts[2].startswith('('):112 if parts[2].startswith('('):
90 srcpkg = parts[1]113 srcpkg = parts[1]
91 if srcpkg is not None and parts[0] == '*':114 if srcpkg is not None and srcpkg[0] != '-' and parts[0] == '*':
92 # parts[1] is "${arch}:"115 # parts[1] is "${arch}:"
93 # parts[2:] is a comma+space separated list of binary package names.116 # parts[2:] is a comma+space separated list of binary package names.
94 for binpkg in parts[2:]:117 arch = parts[1][:-1]
95 binpkg = binpkg.strip(',')118 for binpkg in parts[2].split(', '):
96 r.setdefault(binpkg, set()).add(srcpkg)119 bin_pkg_arch_to_blocked_src_pkgs.setdefault(
97 return r120 (binpkg, arch), set()).add(srcpkg)
121 return bin_pkg_arch_to_blocked_src_pkgs
122
123
124def chdist_grep_dctrl_packages(arch, *args):
125 return run_output(
126 "chdist", "grep-dctrl-packages", "{}-{}".format(series, arch),
127 "-nsPackage", *args, check=False).splitlines()
128
129
130def chdist_grep_dctrl_sources(arch, *args):
131 return run_output(
132 "chdist", "grep-dctrl-sources", "{}-{}".format(series, arch),
133 "-nsPackage", *args, check=False).splitlines()
98134
99135
100@attr.s136@attr.s
@@ -102,9 +138,66 @@
102 source_package_name = attr.ib()138 source_package_name = attr.ib()
103 bugs = attr.ib()139 bugs = attr.ib()
104 block_by_regression = attr.ib(default=attr.Factory(set))140 block_by_regression = attr.ib(default=attr.Factory(set))
105 block_by_uninstallability = attr.ib(default=attr.Factory(list))141 block_by_uninstallability = attr.ib(default=attr.Factory(set))
106 suites = attr.ib(default=attr.Factory(set))142 suites = attr.ib(default=attr.Factory(set))
107 _rdeps_lines = attr.ib(default=None)143 _rdeps_lines = attr.ib(default=None)
144 _binpkgs = attr.ib(default=None)
145
146 def binary_pkgs(self):
147 if self._binpkgs is None:
148 self._binpkgs = set()
149 for arch in all_arches:
150 arch_binpkgs = chdist_grep_dctrl_packages(
151 arch, "-wS", self.source_package_name)
152 self._binpkgs.update({(binpkg, arch) for binpkg in arch_binpkgs})
153 return self._binpkgs
154
155 def reverse_depends(self):
156 if self._rdeps_lines is None:
157 # These are maps rdep -> binpkg -> arches
158 reverse_recommends = {}
159 reverse_depends = {}
160 # This just maps rbdep -> binpkgs
161 reverse_build_depends = {}
162 for binpkg, arch in self.binary_pkgs():
163 for rec in chdist_grep_dctrl_packages(
164 arch, "-wFRecommends", binpkg):
165 if (rec, arch) in self.binary_pkgs():
166 continue
167 reverse_recommends.setdefault(rec, {}).setdefault(binpkg, set()).add(arch)
168 for dep in chdist_grep_dctrl_packages(
169 arch, "-wFDepends", binpkg):
170 if (dep, arch) in self.binary_pkgs():
171 continue
172 reverse_depends.setdefault(dep, {}).setdefault(binpkg, set()).add(arch)
173 for bdeb in chdist_grep_dctrl_sources(
174 arch, "-wFBuild-Depends", binpkg, "--or", "-wFBuild-Depends-Indep", binpkg):
175 reverse_build_depends.setdefault(bdeb, set()).add(binpkg)
176 self._rdeps_lines = []
177 if reverse_depends:
178 self._rdeps_lines.append("Reverse-Depends")
179 for rdep in sorted(reverse_depends):
180 for binpkg in sorted(reverse_depends[rdep]):
181 if reverse_depends[rdep][binpkg] == all_arches:
182 arches = "all architectures"
183 else:
184 arches = ", ".join(reverse_depends[rdep][binpkg])
185 self._rdeps_lines.append(" ".join(["*", rdep, "for", binpkg, "on", arches]))
186 if reverse_recommends:
187 self._rdeps_lines.append("Reverse-Recommends")
188 for rdep in sorted(reverse_recommends):
189 for binpkg in sorted(reverse_recommends[rdep]):
190 if reverse_recommends[rdep][binpkg] == all_arches:
191 arches = "all architectures"
192 else:
193 arches = ", ".join(reverse_recommends[rdep][binpkg])
194 self._rdeps_lines.append(" ".join(["*", rdep, "for", binpkg, "on", arches]))
195 if reverse_build_depends:
196 self._rdeps_lines.append("Reverse-Build-Depends")
197 for rdep in sorted(reverse_build_depends):
198 for binpkg in sorted(reverse_build_depends[rdep]):
199 self._rdeps_lines.append(" ".join(["*", rdep, "for", binpkg]))
200 return self._rdeps_lines
108201
109 @property202 @property
110 def comment(self):203 def comment(self):
@@ -119,32 +212,12 @@
119 return comment212 return comment
120213
121 @property214 @property
122 def rdeps_lines(self):
123 if self._rdeps_lines is None:
124 rdeps = run_output("reverse-depends", 'src:' + self.source_package_name)
125 rbdeps = run_output("reverse-depends", '-b', 'src:' + self.source_package_name)
126
127 if rdeps == 'No reverse dependencies found':
128 rdeps = ''
129 if rbdeps == 'No reverse dependencies found':
130 rbdeps = ''
131
132 if rdeps or rbdeps:
133 if rdeps and rbdeps:
134 self._rdeps_lines = (rdeps + '\n' + rbdeps).splitlines()
135 else:
136 self._rdeps_lines = (rdeps + rbdeps).splitlines()
137 else:
138 self._rdeps_lines = []
139 return self._rdeps_lines
140
141 @property
142 def rdeps_text_short(self):215 def rdeps_text_short(self):
143 return "\n".join(self.rdeps_lines[:10])216 return "\n".join(self.reverse_depends()[:10])
144217
145 @property218 @property
146 def rdeps_text_more(self):219 def rdeps_text_more(self):
147 return "\n".join(self.rdeps_lines[10:])220 return "\n".join(self.reverse_depends()[10:])
148221
149 @property222 @property
150 def removal_commands(self):223 def removal_commands(self):
@@ -154,14 +227,14 @@
154 cmds = []227 cmds = []
155 for suite in suites:228 for suite in suites:
156 cmd = " ".join(["remove-package", "-s", suite, "-m", shlex.quote(self.comment), self.source_package_name])229 cmd = " ".join(["remove-package", "-s", suite, "-m", shlex.quote(self.comment), self.source_package_name])
157 if self.rdeps_lines:230 if self.reverse_depends():
158 cmd = '#' + cmd231 cmd = '#' + cmd
159 cmds.append(cmd)232 cmds.append(cmd)
160 return cmds233 return cmds
161234
162 @property235 @property
163 def css_class(self):236 def css_class(self):
164 if self.rdeps_lines:237 if self.reverse_depends():
165 return 'removal-not-ok'238 return 'removal-not-ok'
166 else:239 else:
167 return 'removal-ok'240 return 'removal-ok'
@@ -178,7 +251,7 @@
178 with open(args.ubuntu_excuses) as fp:251 with open(args.ubuntu_excuses) as fp:
179 ubuntu_excuses = yaml.load(fp, Loader=yaml.CSafeLoader)252 ubuntu_excuses = yaml.load(fp, Loader=yaml.CSafeLoader)
180 with open(args.ubuntu_update_output) as fp:253 with open(args.ubuntu_update_output) as fp:
181 uninstallable_to_src_pkg = extract_uninstallable_to_src_pkg(fp)254 bin_pkg_arch_to_blocked_src_pkgs = extract_bin_pkg_arch_to_blocked_src_pkgs(fp)
182 with open(args.debian_excuses) as fp:255 with open(args.debian_excuses) as fp:
183 debian_excuses = yaml.load(fp, Loader=yaml.CSafeLoader)256 debian_excuses = yaml.load(fp, Loader=yaml.CSafeLoader)
184257
@@ -219,18 +292,17 @@
219 if source['old-version'] != '-':292 if source['old-version'] != '-':
220 rc_gones[item].suites.add(series)293 rc_gones[item].suites.add(series)
221 print("checking uninstallability")294 print("checking uninstallability")
222 for pkg in rc_gones:295 for rc_gone in rc_gones.values():
223 if pkg not in in_proposed_by_autopkgtest_or_missing_binaries:296 if rc_gone.source_package_name not in in_proposed_by_autopkgtest_or_missing_binaries:
224 continue297 continue
225 bin_pkgs = run_output("chdist", "grep-dctrl-packages", series, "-SwnsPackage", pkg, check=False)298 for bin_pkg, arch in set(rc_gone.binary_pkgs()):
226 for bin_pkg in set(bin_pkgs.splitlines()):299 rc_gone.block_by_uninstallability.update(bin_pkg_arch_to_blocked_src_pkgs.get((bin_pkg, arch), set()))
227 rc_gones[pkg].block_by_uninstallability.extend(uninstallable_to_src_pkg.get(bin_pkg, []))
228 print("finding reverse-deps")300 print("finding reverse-deps")
229 packages = []301 packages = []
230 for _, rc_gone in sorted(rc_gones.items()):302 for _, rc_gone in sorted(rc_gones.items()):
231 if not rc_gone.block_by_regression and not rc_gone.block_by_uninstallability:303 if not rc_gone.block_by_regression and not rc_gone.block_by_uninstallability:
232 continue304 continue
233 rc_gone.rdeps_lines305 rc_gone.reverse_depends()
234 packages.append(rc_gone)306 packages.append(rc_gone)
235307
236 print("rendering")308 print("rendering")
237309
=== modified file 'templates/rcbuggy-problem-packages.html'
--- templates/rcbuggy-problem-packages.html 2019-09-09 01:48:46 +0000
+++ templates/rcbuggy-problem-packages.html 2019-09-12 03:12:18 +0000
@@ -62,10 +62,10 @@
62 {% endif %}62 {% endif %}
63 {% if package.block_by_uninstallability %}63 {% if package.block_by_uninstallability %}
64 <p>64 <p>
65 At least one binary from this package is made uninstallable by the versions of {{ package.block_by_uninstallability|join(", ") }} in -proposed.65 At least one binary from this package is made uninstallable by the versions of {{ package.block_by_uninstallability|sort|join(", ") }} in -proposed.
66 </p>66 </p>
67 {% endif %}67 {% endif %}
68 {% if package.rdeps_lines %}68 {% if package._rdeps_lines %}
69 <pre class="rdeps">69 <pre class="rdeps">
70{{ package.rdeps_text_short }}70{{ package.rdeps_text_short }}
71{% if package.rdeps_text_more -%}71{% if package.rdeps_text_more -%}

Subscribers

People subscribed via source and target branches