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