1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 import os
42 import re
43 import time
44 from twisted.web import resource
45 from buildbot.status.builder import FAILURE
46
48 contentType = "text/xml; charset=UTF-8"
49 docType = ''
50
53
55 data = self.content(request)
56 request.setHeader("content-type", self.contentType)
57 if request.method == "HEAD":
58 request.setHeader("content-length", len(data))
59 return ''
60 return data
61
62 _abbr_day = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
63 _abbr_mon = ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
64 'Sep', 'Oct', 'Nov', 'Dec']
65
67 res = time.strftime("%%s, %d %%s %Y %H:%M:%S GMT",
68 tstamp)
69 res = res % (tstamp.tm_wday, tstamp.tm_mon)
70 return res
71
73 pageTitle = None
74 link = 'http://dummylink'
75 language = 'en-us'
76 description = 'Dummy rss'
77 status = None
78
79 - def __init__(self, status, categories=None, pageTitle=None):
91
92 - def getEnv(self, keys, fallback):
93 for key in keys:
94 if key in os.environ:
95 return os.environ[key]
96 return fallback
97
99 builds = []
100
101
102
103
104
105
106 allBuilderNames = self.status.getBuilderNames(categories=self.categories)
107 builders = [self.status.getBuilder(name) for name in allBuilderNames]
108
109
110
111
112
113 showBuilders = request.args.get("show", [])
114 showBuilders.extend(request.args.get("builder", []))
115 if showBuilders:
116 builders = [b for b in builders if b.name in showBuilders]
117
118
119
120
121 showCategories = request.args.get("category", [])
122 if showCategories:
123 builders = [b for b in builders if b.category in showCategories]
124
125 failures_only = request.args.get("failures_only", "false")
126
127 maxFeeds = 25
128
129
130
131
132 for b in builders:
133 lastbuild = b.getLastFinishedBuild()
134 if lastbuild is None:
135 continue
136
137 lastnr = lastbuild.getNumber()
138
139 totalbuilds = 0
140 i = lastnr
141 while i >= 0:
142 build = b.getBuild(i)
143 i -= 1
144 if not build:
145 continue
146
147 results = build.getResults()
148
149 if failures_only == "false" or results == FAILURE:
150 totalbuilds += 1
151 builds.append(build)
152
153
154 if totalbuilds >= maxFeeds:
155 break
156
157
158
159
160 deco = [(build.getTimes(), build) for build in builds]
161 deco.sort()
162 deco.reverse()
163 builds = [build for (b1, build) in deco]
164
165 if builds:
166 builds = builds[:min(len(builds), maxFeeds)]
167 return builds
168
169 - def content(self, request):
170 builds = self.getBuilds(request)
171
172 build_cxts = []
173
174 for build in builds:
175 start, finished = build.getTimes()
176 finishedTime = time.gmtime(int(finished))
177 link = re.sub(r'index.html', "", self.status.getURLForThing(build))
178
179
180
181 ss = build.getSourceStamp()
182 source = ""
183 if ss.branch:
184 source += "Branch %s " % ss.branch
185 if ss.revision:
186 source += "Revision %s " % str(ss.revision)
187 if ss.patch:
188 source += " (plus patch)"
189 if ss.changes:
190 pass
191 if (ss.branch is None and ss.revision is None and ss.patch is None
192 and not ss.changes):
193 source += "Latest revision "
194 got_revision = build.getProperty("got_revision")
195 if got_revision:
196 got_revision = str(got_revision)
197 if len(got_revision) > 40:
198 got_revision = "[revision string too long]"
199 source += "(Got Revision: %s)" % got_revision
200 failflag = (build.getResults() != FAILURE)
201 pageTitle = ('%s %s on "%s"' %
202 (source, ["failed","succeeded"][failflag],
203 build.getBuilder().getName()))
204
205
206 failed_steps = []
207 log_lines = []
208 for s in build.getSteps():
209 if s.getResults()[0] == FAILURE:
210 failed_steps.append(s.getName())
211
212
213 for log in s.getLogs():
214 log_lines.append('Last lines of build log "%s":' %
215 log.getName())
216 log_lines.append([])
217 try:
218 logdata = log.getText()
219 except IOError:
220
221 logdata ='** log file not available **'
222 unilist = list()
223 for line in logdata.split('\n')[-30:]:
224 unilist.append(unicode(line,'utf-8'))
225 log_lines.extend(unilist)
226
227 bc = {}
228 bc['date'] = rfc822_time(finishedTime)
229 bc['summary_link'] = ('%sbuilders/%s' %
230 (self.link,
231 build.getBuilder().getName()))
232 bc['name'] = build.getBuilder().getName()
233 bc['number'] = build.getNumber()
234 bc['responsible_users'] = build.getResponsibleUsers()
235 bc['failed_steps'] = failed_steps
236 bc['pageTitle'] = pageTitle
237 bc['link'] = link
238 bc['log_lines'] = log_lines
239
240 if finishedTime is not None:
241 bc['rfc822_pubdate'] = rfc822_time(finishedTime)
242 bc['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ",
243 finishedTime)
244
245
246 guid = ('tag:%s@%s,%s:%s' %
247 (self.user, self.hostname,
248 time.strftime("%Y-%m-%d", finishedTime),
249 time.strftime("%Y%m%d%H%M%S", finishedTime)))
250 bc['guid'] = guid
251
252 build_cxts.append(bc)
253
254 pageTitle = self.pageTitle
255 if not pageTitle:
256 pageTitle = 'Build status of %s' % self.title
257
258 cxt = {}
259 cxt['pageTitle'] = pageTitle
260 cxt['title_url'] = self.link
261 cxt['title'] = self.title
262 cxt['language'] = self.language
263 cxt['description'] = self.description
264 if self.pubdate is not None:
265 cxt['rfc822_pubdate'] = rfc822_time( self.pubdate)
266 cxt['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ",
267 self.pubdate)
268
269 cxt['builds'] = build_cxts
270 template = request.site.buildbot_service.templates.get_template(self.template_file)
271 return template.render(**cxt).encode('utf-8').strip()
272
279
281
282 template_file = 'feed_atom10.xml'
283
284 - def __init__(self, status, categories=None, pageTitle=None):
286