Merge lp:~wgrant/lp-ftbfs-report/multi-archive-superseded into lp:lp-ftbfs-report

Proposed by William Grant
Status: Merged
Merged at revision: 49
Proposed branch: lp:~wgrant/lp-ftbfs-report/multi-archive-superseded
Merge into: lp:lp-ftbfs-report
Prerequisite: lp:~wgrant/lp-ftbfs-report/multi-archive
Diff against target: 221 lines (+71/-18)
2 files modified
source/build_status.html (+14/-0)
source/build_status.py (+57/-18)
To merge this branch: bzr merge lp:~wgrant/lp-ftbfs-report/multi-archive-superseded
Reviewer Review Type Date Requested Status
Michael Bienia Pending
Review via email: mp+78538@code.launchpad.net

Commit message

Add support for detecting superseded builds in non-primary archives.

Description of the change

This branch adds support for identifying superseded builds in non-primary archives. If the archive is non-primary, the distribution's primary archive is checked for an active publication for each build. If no active publication is found, the build is shown in a separate section.

Also a couple of fixes to be more robust against lazr.restfulclient versions (catching a KeyError when looking up people), and against broken builds (handling an absent build_log_url).

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 'source/build_status.html'
--- source/build_status.html 2011-10-07 04:09:43 +0000
+++ source/build_status.html 2011-10-07 04:09:43 +0000
@@ -184,6 +184,20 @@
184 {{ table(lst, ps, 'Also belongs to another packageset?') }}184 {{ table(lst, ps, 'Also belongs to another packageset?') }}
185 {% endfor -%}185 {% endfor -%}
186186
187 {% if main_archive %}
188 <h2 id="main_superseded">main (superseded): {{ main_superseded|count }} packages (<a href="#top">top</a>)</h2>
189 {{ table(main_superseded) }}
190
191 <h2 id="restricted_superseded">restricted (superseded): {{ restricted_superseded|count }} packages (<a href="#top">top</a>)</h2>
192 {{ table(restricted_superseded) }}
193
194 <h2 id="universe_superseded">universe (superseded): {{ universe_superseded|count }} packages (<a href="#top">top</a>)</h2>
195 {{ table(universe_superseded) }}
196
197 <h2 id="multiverse_superseded">multiverse (superseded): {{ multiverse_superseded|count }} packages (<a href="#top">top</a>)</h2>
198 {{ table(multiverse_superseded) }}
199 {%- endif %}
200
187 <hr/>201 <hr/>
188 <p style="font-size:smaller">Last update: {{ lastupdate }}</p>202 <p style="font-size:smaller">Last update: {{ lastupdate }}</p>
189 <p>203 <p>
190204
=== modified file 'source/build_status.py'
--- source/build_status.py 2011-10-07 04:09:43 +0000
+++ source/build_status.py 2011-10-07 04:09:43 +0000
@@ -56,7 +56,8 @@
56 lp_object = launchpad.load(personteam_link)56 lp_object = launchpad.load(personteam_link)
57 personteam.display_name = lp_object.display_name57 personteam.display_name = lp_object.display_name
58 personteam.name = lp_object.name58 personteam.name = lp_object.name
5959 except KeyError:
60 return None
60 except HTTPError, e:61 except HTTPError, e:
61 if e.response.status == 410:62 if e.response.status == 410:
62 personteam = None63 personteam = None
@@ -115,9 +116,11 @@
115 def __cmp__(self, other):116 def __cmp__(self, other):
116 return cmp(self.name, other.name)117 return cmp(self.name, other.name)
117118
118 def isFTBFS(self, arch_list = default_arch_list):119 def isFTBFS(self, arch_list = default_arch_list, current = True):
119 ''' Returns True if at least one FTBFS exists. '''120 ''' Returns True if at least one FTBFS exists. '''
120 for ver in self.versions:121 for ver in self.versions:
122 if ver.current != current:
123 continue
121 for arch in arch_list:124 for arch in arch_list:
122 log = ver.getArch(arch)125 log = ver.getArch(arch)
123 if log is not None:126 if log is not None:
@@ -149,11 +152,13 @@
149152
150 # fill the new SPPH object with data153 # fill the new SPPH object with data
151 lp_object = launchpad.load(spph_link)154 lp_object = launchpad.load(spph_link)
155 spph._lp = lp_object
152 spph.logs = dict()156 spph.logs = dict()
153 spph.version = lp_object.source_package_version157 spph.version = lp_object.source_package_version
154 spph.pocket = lp_object.pocket158 spph.pocket = lp_object.pocket
155 spph.changed_by = PersonTeam(lp_object.package_creator_link)159 spph.changed_by = PersonTeam(lp_object.package_creator_link)
156 #spph.signed_by = spph._lp.package_signer_link and PersonTeam(lp_object.package_signer_link)160 #spph.signed_by = spph._lp.package_signer_link and PersonTeam(lp_object.package_signer_link)
161 spph.current = None
157 SourcePackage(lp_object).versions.append(spph)162 SourcePackage(lp_object).versions.append(spph)
158163
159 # add to cache164 # add to cache
@@ -178,8 +183,10 @@
178183
179 if self.buildstate == 'UPLOADFAIL':184 if self.buildstate == 'UPLOADFAIL':
180 self.log = translate_api_web(build.upload_log_url)185 self.log = translate_api_web(build.upload_log_url)
181 else:186 elif build.build_log_url:
182 self.log = translate_api_web(build.build_log_url)187 self.log = translate_api_web(build.build_log_url)
188 else:
189 self.log = ''
183190
184 if self.buildstate == 'MANUALDEPWAIT':191 if self.buildstate == 'MANUALDEPWAIT':
185 self.tooltip = 'waits on %s' % build.dependencies192 self.tooltip = 'waits on %s' % build.dependencies
@@ -201,14 +208,14 @@
201 return u'Changed-By: %s' % (self.changed_by)208 return u'Changed-By: %s' % (self.changed_by)
202209
203210
204def fetch_pkg_list(archive, series, state, last_published, arch_list=default_arch_list):211def fetch_pkg_list(archive, series, state, last_published, arch_list=default_arch_list, main_archive=None, main_series=None):
205 print "Processing '%s'" % state212 print "Processing '%s'" % state
206213
207 cur_last_published = None214 cur_last_published = None
208 # XXX wgrant 2009-09-19: This is an awful hack. We should really215 # XXX wgrant 2009-09-19: This is an awful hack. We should really
209 # just let IArchive.getBuildRecords take a series argument.216 # just let IArchive.getBuildRecords take a series argument.
210 if archive.name == 'primary':217 if archive.name == 'primary':
211 buildlist = series.getBuildRecords(build_state = state, pocket='Proposed')218 buildlist = series.getBuildRecords(build_state = state)
212 else:219 else:
213 buildlist = archive.getBuildRecords(build_state = state)220 buildlist = archive.getBuildRecords(build_state = state)
214221
@@ -232,29 +239,52 @@
232239
233 print " %s %s" % (build.datebuilt, build.title)240 print " %s %s" % (build.datebuilt, build.title)
234241
242 spph = SPPH(csp_link)
243
244 if spph.current is None:
245 # If a main archive is specified, we check if the current source
246 # is still published there. If it isn't, then it's out of date.
247 # We should make this obvious.
248 # The main archive will normally be the primary archive, and
249 # probably only makes sense if the target archive is a rebuild.
250 if main_archive:
251 main_publications = main_archive.getPublishedSources(
252 distro_series=main_series,
253 exact_match=True,
254 source_name=spph._lp.source_package_name,
255 version=spph._lp.source_package_version,
256 status='Published')
257 spph.current = len(main_publications[:1]) > 0
258 else:
259 spph.current = True
260
261 if not spph.current:
262 print " superseded"
235 SPPH(csp_link).addBuildLog(build)263 SPPH(csp_link).addBuildLog(build)
236264
237 return cur_last_published265 return cur_last_published
238266
239267
240def generate_page(archive, series, archs_by_archive, template = 'build_status.html', arch_list = default_arch_list):268def generate_page(archive, series, archs_by_archive, main_archive, template = 'build_status.html', arch_list = default_arch_list):
241 try:269 try:
242 out = open('../%s-%s.html' % (archive.name, series.name), 'w')270 out = open('../%s-%s.html' % (archive.name, series.name), 'w')
243 except IOError:271 except IOError:
244 return272 return
245273
246 # sort the package lists274 # sort the package lists
247 filter_ftbfs = lambda pkglist: filter(methodcaller('isFTBFS', arch_list), sorted(pkglist))275 filter_ftbfs = lambda pkglist, current: filter(methodcaller('isFTBFS', arch_list, current), sorted(pkglist))
248 data = {}276 data = {}
249 for comp in ('main', 'restricted', 'universe', 'multiverse'):277 for comp in ('main', 'restricted', 'universe', 'multiverse'):
250 data[comp] = filter_ftbfs(components[comp])278 data[comp] = filter_ftbfs(components[comp], True)
279 data['%s_superseded' % comp] = filter_ftbfs(components[comp], False)
251 for pkgset, pkglist in packagesets_ftbfs.items():280 for pkgset, pkglist in packagesets_ftbfs.items():
252 packagesets_ftbfs[pkgset] = filter_ftbfs(pkglist)281 packagesets_ftbfs[pkgset] = filter_ftbfs(pkglist, True)
253282
254 # container object to hold the counts and the tooltip283 # container object to hold the counts and the tooltip
255 class StatData(object):284 class StatData(object):
256 def __init__(self, cnt, tooltip):285 def __init__(self, cnt, cnt_superseded, tooltip):
257 self.cnt = cnt286 self.cnt = cnt
287 self.cnt_superseded = cnt_superseded
258 self.tooltip = tooltip288 self.tooltip = tooltip
259289
260 # compute some statistics (number of packages for each build failure type)290 # compute some statistics (number of packages for each build failure type)
@@ -264,21 +294,25 @@
264 for arch in arch_list:294 for arch in arch_list:
265 tooltip = []295 tooltip = []
266 cnt = 0296 cnt = 0
297 cnt_sup = 0
267 for comp in ('main', 'restricted', 'universe', 'multiverse'):298 for comp in ('main', 'restricted', 'universe', 'multiverse'):
268 s = sum([pkg.getCount(arch, state) for pkg in data[comp]])299 s = sum([pkg.getCount(arch, state) for pkg in data[comp]])
269 if s:300 s_sup = sum([pkg.getCount(arch, state) for pkg in data['%s_superseded' % comp]])
301 if s or s_sup:
270 cnt += s302 cnt += s
271 tooltip.append('<td>%s:</td><td style="text-align:right;">%i</td>' % (comp, s))303 cnt_sup += s_sup
304 tooltip.append('<td>%s:</td><td style="text-align:right;">%i (%i superseded)</td>' % (comp, s, s_sup))
272 if cnt:305 if cnt:
273 tooltiphtml = u'<table><tr>'306 tooltiphtml = u'<table><tr>'
274 tooltiphtml += u'</tr><tr>'.join(tooltip)307 tooltiphtml += u'</tr><tr>'.join(tooltip)
275 tooltiphtml += u'</tr></table>'308 tooltiphtml += u'</tr></table>'
276 stats[state][arch] = StatData(cnt, tooltiphtml)309 stats[state][arch] = StatData(cnt, cnt_sup, tooltiphtml)
277 else:310 else:
278 stats[state][arch] = StatData(None, None)311 stats[state][arch] = StatData(None, None, None)
279312
280 data['stats'] = stats313 data['stats'] = stats
281 data['archive'] = archive314 data['archive'] = archive
315 data['main_archive'] = main_archive
282 data['series'] = series316 data['series'] = series
283 data['arch_list'] = arch_list317 data['arch_list'] = arch_list
284 data['archs_by_archive'] = archs_by_archive318 data['archs_by_archive'] = archs_by_archive
@@ -338,10 +372,9 @@
338372
339if __name__ == '__main__':373if __name__ == '__main__':
340 # login anonymously to LP374 # login anonymously to LP
341 launchpad = Launchpad.login_anonymously('qa-ftbfs', lp_service)375 launchpad = Launchpad.login_anonymously('qa-ftbfs', lp_service, version=api_version)
342376
343 ubuntu = launchpad.distributions['ubuntu']377 ubuntu = launchpad.distributions['ubuntu']
344
345 assert len(sys.argv) >= 4378 assert len(sys.argv) >= 4
346379
347 try:380 try:
@@ -355,6 +388,12 @@
355 print 'Error: %s is not a valid series.' % sys.argv[2]388 print 'Error: %s is not a valid series.' % sys.argv[2]
356 sys.exit(1)389 sys.exit(1)
357390
391 if archive.name != 'primary':
392 main_archive = ubuntu.main_archive
393 main_series = ubuntu.current_series
394 else:
395 main_archive = main_series = None
396
358 archs_by_archive = dict(main=[], ports=[])397 archs_by_archive = dict(main=[], ports=[])
359 for arch in sys.argv[3:]:398 for arch in sys.argv[3:]:
360 das = series.getDistroArchSeries(archtag=arch)399 das = series.getDistroArchSeries(archtag=arch)
@@ -388,11 +427,11 @@
388 packagesets_ftbfs[ps.name] = [] # empty list to add FTBFS for each package set later427 packagesets_ftbfs[ps.name] = [] # empty list to add FTBFS for each package set later
389428
390 for state in ('Failed to build', 'Dependency wait', 'Chroot problem', 'Failed to upload'):429 for state in ('Failed to build', 'Dependency wait', 'Chroot problem', 'Failed to upload'):
391 last_published[state] = fetch_pkg_list(archive, series, state, last_published[state], default_arch_list)430 last_published[state] = fetch_pkg_list(archive, series, state, last_published[state], default_arch_list, main_archive, main_series)
392431
393 save_timestamps(archive, series, last_published)432 save_timestamps(archive, series, last_published)
394433
395 print "Generating HTML page..."434 print "Generating HTML page..."
396 generate_page(archive, series, archs_by_archive)435 generate_page(archive, series, archs_by_archive, main_archive)
397 print "Generating CSV file..."436 print "Generating CSV file..."
398 generate_csvfile(archive, series)437 generate_csvfile(archive, series)

Subscribers

People subscribed via source and target branches

to all changes: