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
202 log_lines.extend(logdata.split('\n')[-30:])
203
204 bc = {}
205 bc['date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
206 finishedTime)
207 bc['summary_link'] = ('%sbuilders/%s' %
208 (self.link,
209 build.getBuilder().getName()))
210 bc['name'] = build.getBuilder().getName()
211 bc['number'] = build.getNumber()
212 bc['responsible_users'] = build.getResponsibleUsers()
213 bc['failed_steps'] = failed_steps
214 bc['title'] = title
215 bc['link'] = link
216 bc['log_lines'] = log_lines
217
218 if finishedTime is not None:
219 bc['rfc822_pubdate'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
220 finishedTime)
221 bc['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ",
222 finishedTime)
223
224
225 guid = ('tag:%s@%s,%s:%s' %
226 (self.user, self.hostname,
227 time.strftime("%Y-%m-%d", finishedTime),
228 time.strftime("%Y%m%d%H%M%S", finishedTime)))
229 bc['guid'] = guid
230
231 build_cxts.append(bc)
232
233 title = self.title
234 if not title:
235 title = 'Build status of %s' % self.projectName
236
237 cxt = {}
238 cxt['title'] = title
239 cxt['project_url'] = self.link
240 cxt['project_name'] = self.projectName
241 cxt['language'] = self.language
242 cxt['description'] = self.description
243 if self.pubdate is not None:
244 cxt['rfc822_pubdate'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
245 self.pubdate)
246 cxt['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ",
247 self.pubdate)
248
249 cxt['builds'] = build_cxts
250 template = request.site.buildbot_service.templates.get_template(self.template_file)
251 return template.render(**cxt).encode('utf-8').strip()
252
259
266