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
1=== modified file 'source/build_status.html'
2--- source/build_status.html 2011-10-07 04:09:43 +0000
3+++ source/build_status.html 2011-10-07 04:09:43 +0000
4@@ -184,6 +184,20 @@
5 {{ table(lst, ps, 'Also belongs to another packageset?') }}
6 {% endfor -%}
7
8+ {% if main_archive %}
9+ <h2 id="main_superseded">main (superseded): {{ main_superseded|count }} packages (<a href="#top">top</a>)</h2>
10+ {{ table(main_superseded) }}
11+
12+ <h2 id="restricted_superseded">restricted (superseded): {{ restricted_superseded|count }} packages (<a href="#top">top</a>)</h2>
13+ {{ table(restricted_superseded) }}
14+
15+ <h2 id="universe_superseded">universe (superseded): {{ universe_superseded|count }} packages (<a href="#top">top</a>)</h2>
16+ {{ table(universe_superseded) }}
17+
18+ <h2 id="multiverse_superseded">multiverse (superseded): {{ multiverse_superseded|count }} packages (<a href="#top">top</a>)</h2>
19+ {{ table(multiverse_superseded) }}
20+ {%- endif %}
21+
22 <hr/>
23 <p style="font-size:smaller">Last update: {{ lastupdate }}</p>
24 <p>
25
26=== modified file 'source/build_status.py'
27--- source/build_status.py 2011-10-07 04:09:43 +0000
28+++ source/build_status.py 2011-10-07 04:09:43 +0000
29@@ -56,7 +56,8 @@
30 lp_object = launchpad.load(personteam_link)
31 personteam.display_name = lp_object.display_name
32 personteam.name = lp_object.name
33-
34+ except KeyError:
35+ return None
36 except HTTPError, e:
37 if e.response.status == 410:
38 personteam = None
39@@ -115,9 +116,11 @@
40 def __cmp__(self, other):
41 return cmp(self.name, other.name)
42
43- def isFTBFS(self, arch_list = default_arch_list):
44+ def isFTBFS(self, arch_list = default_arch_list, current = True):
45 ''' Returns True if at least one FTBFS exists. '''
46 for ver in self.versions:
47+ if ver.current != current:
48+ continue
49 for arch in arch_list:
50 log = ver.getArch(arch)
51 if log is not None:
52@@ -149,11 +152,13 @@
53
54 # fill the new SPPH object with data
55 lp_object = launchpad.load(spph_link)
56+ spph._lp = lp_object
57 spph.logs = dict()
58 spph.version = lp_object.source_package_version
59 spph.pocket = lp_object.pocket
60 spph.changed_by = PersonTeam(lp_object.package_creator_link)
61 #spph.signed_by = spph._lp.package_signer_link and PersonTeam(lp_object.package_signer_link)
62+ spph.current = None
63 SourcePackage(lp_object).versions.append(spph)
64
65 # add to cache
66@@ -178,8 +183,10 @@
67
68 if self.buildstate == 'UPLOADFAIL':
69 self.log = translate_api_web(build.upload_log_url)
70- else:
71+ elif build.build_log_url:
72 self.log = translate_api_web(build.build_log_url)
73+ else:
74+ self.log = ''
75
76 if self.buildstate == 'MANUALDEPWAIT':
77 self.tooltip = 'waits on %s' % build.dependencies
78@@ -201,14 +208,14 @@
79 return u'Changed-By: %s' % (self.changed_by)
80
81
82-def fetch_pkg_list(archive, series, state, last_published, arch_list=default_arch_list):
83+def fetch_pkg_list(archive, series, state, last_published, arch_list=default_arch_list, main_archive=None, main_series=None):
84 print "Processing '%s'" % state
85
86 cur_last_published = None
87 # XXX wgrant 2009-09-19: This is an awful hack. We should really
88 # just let IArchive.getBuildRecords take a series argument.
89 if archive.name == 'primary':
90- buildlist = series.getBuildRecords(build_state = state, pocket='Proposed')
91+ buildlist = series.getBuildRecords(build_state = state)
92 else:
93 buildlist = archive.getBuildRecords(build_state = state)
94
95@@ -232,29 +239,52 @@
96
97 print " %s %s" % (build.datebuilt, build.title)
98
99+ spph = SPPH(csp_link)
100+
101+ if spph.current is None:
102+ # If a main archive is specified, we check if the current source
103+ # is still published there. If it isn't, then it's out of date.
104+ # We should make this obvious.
105+ # The main archive will normally be the primary archive, and
106+ # probably only makes sense if the target archive is a rebuild.
107+ if main_archive:
108+ main_publications = main_archive.getPublishedSources(
109+ distro_series=main_series,
110+ exact_match=True,
111+ source_name=spph._lp.source_package_name,
112+ version=spph._lp.source_package_version,
113+ status='Published')
114+ spph.current = len(main_publications[:1]) > 0
115+ else:
116+ spph.current = True
117+
118+ if not spph.current:
119+ print " superseded"
120 SPPH(csp_link).addBuildLog(build)
121
122 return cur_last_published
123
124
125-def generate_page(archive, series, archs_by_archive, template = 'build_status.html', arch_list = default_arch_list):
126+def generate_page(archive, series, archs_by_archive, main_archive, template = 'build_status.html', arch_list = default_arch_list):
127 try:
128 out = open('../%s-%s.html' % (archive.name, series.name), 'w')
129 except IOError:
130 return
131
132 # sort the package lists
133- filter_ftbfs = lambda pkglist: filter(methodcaller('isFTBFS', arch_list), sorted(pkglist))
134+ filter_ftbfs = lambda pkglist, current: filter(methodcaller('isFTBFS', arch_list, current), sorted(pkglist))
135 data = {}
136 for comp in ('main', 'restricted', 'universe', 'multiverse'):
137- data[comp] = filter_ftbfs(components[comp])
138+ data[comp] = filter_ftbfs(components[comp], True)
139+ data['%s_superseded' % comp] = filter_ftbfs(components[comp], False)
140 for pkgset, pkglist in packagesets_ftbfs.items():
141- packagesets_ftbfs[pkgset] = filter_ftbfs(pkglist)
142+ packagesets_ftbfs[pkgset] = filter_ftbfs(pkglist, True)
143
144 # container object to hold the counts and the tooltip
145 class StatData(object):
146- def __init__(self, cnt, tooltip):
147+ def __init__(self, cnt, cnt_superseded, tooltip):
148 self.cnt = cnt
149+ self.cnt_superseded = cnt_superseded
150 self.tooltip = tooltip
151
152 # compute some statistics (number of packages for each build failure type)
153@@ -264,21 +294,25 @@
154 for arch in arch_list:
155 tooltip = []
156 cnt = 0
157+ cnt_sup = 0
158 for comp in ('main', 'restricted', 'universe', 'multiverse'):
159 s = sum([pkg.getCount(arch, state) for pkg in data[comp]])
160- if s:
161+ s_sup = sum([pkg.getCount(arch, state) for pkg in data['%s_superseded' % comp]])
162+ if s or s_sup:
163 cnt += s
164- tooltip.append('<td>%s:</td><td style="text-align:right;">%i</td>' % (comp, s))
165+ cnt_sup += s_sup
166+ tooltip.append('<td>%s:</td><td style="text-align:right;">%i (%i superseded)</td>' % (comp, s, s_sup))
167 if cnt:
168 tooltiphtml = u'<table><tr>'
169 tooltiphtml += u'</tr><tr>'.join(tooltip)
170 tooltiphtml += u'</tr></table>'
171- stats[state][arch] = StatData(cnt, tooltiphtml)
172+ stats[state][arch] = StatData(cnt, cnt_sup, tooltiphtml)
173 else:
174- stats[state][arch] = StatData(None, None)
175+ stats[state][arch] = StatData(None, None, None)
176
177 data['stats'] = stats
178 data['archive'] = archive
179+ data['main_archive'] = main_archive
180 data['series'] = series
181 data['arch_list'] = arch_list
182 data['archs_by_archive'] = archs_by_archive
183@@ -338,10 +372,9 @@
184
185 if __name__ == '__main__':
186 # login anonymously to LP
187- launchpad = Launchpad.login_anonymously('qa-ftbfs', lp_service)
188+ launchpad = Launchpad.login_anonymously('qa-ftbfs', lp_service, version=api_version)
189
190 ubuntu = launchpad.distributions['ubuntu']
191-
192 assert len(sys.argv) >= 4
193
194 try:
195@@ -355,6 +388,12 @@
196 print 'Error: %s is not a valid series.' % sys.argv[2]
197 sys.exit(1)
198
199+ if archive.name != 'primary':
200+ main_archive = ubuntu.main_archive
201+ main_series = ubuntu.current_series
202+ else:
203+ main_archive = main_series = None
204+
205 archs_by_archive = dict(main=[], ports=[])
206 for arch in sys.argv[3:]:
207 das = series.getDistroArchSeries(archtag=arch)
208@@ -388,11 +427,11 @@
209 packagesets_ftbfs[ps.name] = [] # empty list to add FTBFS for each package set later
210
211 for state in ('Failed to build', 'Dependency wait', 'Chroot problem', 'Failed to upload'):
212- last_published[state] = fetch_pkg_list(archive, series, state, last_published[state], default_arch_list)
213+ last_published[state] = fetch_pkg_list(archive, series, state, last_published[state], default_arch_list, main_archive, main_series)
214
215 save_timestamps(archive, series, last_published)
216
217 print "Generating HTML page..."
218- generate_page(archive, series, archs_by_archive)
219+ generate_page(archive, series, archs_by_archive, main_archive)
220 print "Generating CSV file..."
221 generate_csvfile(archive, series)

Subscribers

People subscribed via source and target branches

to all changes: