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
63 title = None
64 link = 'http://dummylink'
65 language = 'en-us'
66 description = 'Dummy rss'
67 status = None
68
69 - def __init__(self, status, categories=None, title=None):
81
82 - def getEnv(self, keys, fallback):
83 for key in keys:
84 if key in os.environ:
85 return os.environ[key]
86 return fallback
87
89 builds = []
90
91
92
93
94
95
96 allBuilderNames = self.status.getBuilderNames(categories=self.categories)
97 builders = [self.status.getBuilder(name) for name in allBuilderNames]
98
99
100
101
102
103 showBuilders = request.args.get("show", [])
104 showBuilders.extend(request.args.get("builder", []))
105 if showBuilders:
106 builders = [b for b in builders if b.name in showBuilders]
107
108
109
110
111 showCategories = request.args.get("category", [])
112 if showCategories:
113 builders = [b for b in builders if b.category in showCategories]
114
115 failures_only = request.args.get("failures_only", "false")
116
117 maxFeeds = 25
118
119
120
121
122 for b in builders:
123 lastbuild = b.getLastFinishedBuild()
124 if lastbuild is None:
125 continue
126
127 lastnr = lastbuild.getNumber()
128
129 totalbuilds = 0
130 i = lastnr
131 while i >= 0:
132 build = b.getBuild(i)
133 i -= 1
134 if not build:
135 continue
136
137 results = build.getResults()
138
139 if failures_only == "false" or results == FAILURE:
140 totalbuilds += 1
141 builds.append(build)
142
143
144 if totalbuilds >= maxFeeds:
145 break
146
147
148
149
150 deco = [(build.getTimes(), build) for build in builds]
151 deco.sort()
152 deco.reverse()
153 builds = [build for (b1, build) in deco]
154
155 if builds:
156 builds = builds[:min(len(builds), maxFeeds)]
157 return builds
158
159 - def content(self, request):
160 builds = self.getBuilds(request)
161
162 build_cxts = []
163
164 for build in builds:
165 start, finished = build.getTimes()
166 finishedTime = time.gmtime(int(finished))
167 link = re.sub(r'index.html', "", self.status.getURLForThing(build))
168
169
170
171 ss = build.getSourceStamp()
172 source = ""
173 if ss.branch:
174 source += "Branch %s " % ss.branch
175 if ss.revision:
176 source += "Revision %s " % str(ss.revision)
177 if ss.patch:
178 source += " (plus patch)"
179 if ss.changes:
180 pass
181 if (ss.branch is None and ss.revision is None and ss.patch is None
182 and not ss.changes):
183 source += "Latest revision "
184 got_revision = None
185 try:
186 got_revision = build.getProperty("got_revision")
187 except KeyError:
188 pass
189 if got_revision:
190 got_revision = str(got_revision)
191 if len(got_revision) > 40:
192 got_revision = "[revision string too long]"
193 source += "(Got Revision: %s)" % got_revision
194 failflag = (build.getResults() != FAILURE)
195 title = ('%s %s on "%s"' %
196 (source, ["failed","succeeded"][failflag],
197 build.getBuilder().getName()))
198
199
200 failed_steps = []
201 log_lines = []
202 for s in build.getSteps():
203 if s.getResults()[0] == FAILURE:
204 failed_steps.append(s.getName())
205
206
207 for log in s.getLogs():
208 log_lines.append('Last lines of build log "%s":' %
209 log.getName())
210 log_lines.append([])
211 try:
212 logdata = log.getText()
213 except IOError:
214
215 logdata ='** log file not available **'
216 unilist = list()
217 for line in logdata.split('\n')[-30:]:
218 unilist.append(unicode(line,'utf-8'))
219 log_lines.extend(unilist)
220
221 bc = {}
222 bc['date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
223 finishedTime)
224 bc['summary_link'] = ('%sbuilders/%s' %
225 (self.link,
226 build.getBuilder().getName()))
227 bc['name'] = build.getBuilder().getName()
228 bc['number'] = build.getNumber()
229 bc['responsible_users'] = build.getResponsibleUsers()
230 bc['failed_steps'] = failed_steps
231 bc['title'] = title
232 bc['link'] = link
233 bc['log_lines'] = log_lines
234
235 if finishedTime is not None:
236 bc['rfc822_pubdate'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
237 finishedTime)
238 bc['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ",
239 finishedTime)
240
241
242 guid = ('tag:%s@%s,%s:%s' %
243 (self.user, self.hostname,
244 time.strftime("%Y-%m-%d", finishedTime),
245 time.strftime("%Y%m%d%H%M%S", finishedTime)))
246 bc['guid'] = guid
247
248 build_cxts.append(bc)
249
250 title = self.title
251 if not title:
252 title = 'Build status of %s' % self.projectName
253
254 cxt = {}
255 cxt['title'] = title
256 cxt['project_url'] = self.link
257 cxt['project_name'] = self.projectName
258 cxt['language'] = self.language
259 cxt['description'] = self.description
260 if self.pubdate is not None:
261 cxt['rfc822_pubdate'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
262 self.pubdate)
263 cxt['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ",
264 self.pubdate)
265
266 cxt['builds'] = build_cxts
267 template = request.site.buildbot_service.templates.get_template(self.template_file)
268 return template.render(**cxt).encode('utf-8').strip()
269
276
283