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 = None 
195              try: 
196                  got_revision = build.getProperty("got_revision") 
197              except KeyError: 
198                  pass 
199              if got_revision: 
200                  got_revision = str(got_revision) 
201                  if len(got_revision) > 40: 
202                      got_revision = "[revision string too long]" 
203                  source += "(Got Revision: %s)" % got_revision 
204              failflag = (build.getResults() != FAILURE) 
205              pageTitle = ('%s %s on "%s"' % 
206                       (source, ["failed","succeeded"][failflag], 
207                        build.getBuilder().getName())) 
208   
209               
210              failed_steps = [] 
211              log_lines = [] 
212              for s in build.getSteps(): 
213                  if s.getResults()[0] == FAILURE: 
214                      failed_steps.append(s.getName()) 
215   
216                       
217                      for log in s.getLogs(): 
218                          log_lines.append('Last lines of build log "%s":' % 
219                                           log.getName()) 
220                          log_lines.append([]) 
221                          try: 
222                              logdata = log.getText() 
223                          except IOError: 
224                               
225                              logdata ='** log file not available **' 
226                          unilist = list() 
227                          for line in logdata.split('\n')[-30:]: 
228                              unilist.append(unicode(line,'utf-8')) 
229                          log_lines.extend(unilist) 
230   
231              bc = {} 
232              bc['date'] = rfc822_time(finishedTime) 
233              bc['summary_link'] = ('%sbuilders/%s' % 
234                                    (self.link, 
235                                     build.getBuilder().getName()))             
236              bc['name'] = build.getBuilder().getName() 
237              bc['number'] = build.getNumber() 
238              bc['responsible_users'] = build.getResponsibleUsers() 
239              bc['failed_steps'] = failed_steps 
240              bc['pageTitle'] = pageTitle 
241              bc['link'] = link 
242              bc['log_lines'] = log_lines 
243   
244              if finishedTime is not None: 
245                  bc['rfc822_pubdate'] = rfc822_time(finishedTime) 
246                  bc['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ", 
247                                                 finishedTime) 
248   
249                   
250                  guid = ('tag:%s@%s,%s:%s' % 
251                          (self.user, self.hostname, 
252                           time.strftime("%Y-%m-%d", finishedTime), 
253                           time.strftime("%Y%m%d%H%M%S", finishedTime))) 
254                  bc['guid'] = guid 
255   
256              build_cxts.append(bc) 
257   
258          pageTitle = self.pageTitle 
259          if not pageTitle: 
260              pageTitle = 'Build status of %s' % self.title 
261   
262          cxt = {} 
263          cxt['pageTitle'] = pageTitle 
264          cxt['title_url'] = self.link 
265          cxt['title'] = self.title 
266          cxt['language'] = self.language 
267          cxt['description'] = self.description 
268          if self.pubdate is not None: 
269              cxt['rfc822_pubdate'] = rfc822_time( self.pubdate) 
270              cxt['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ", 
271                                                     self.pubdate) 
272   
273          cxt['builds'] = build_cxts 
274          template = request.site.buildbot_service.templates.get_template(self.template_file) 
275          return template.render(**cxt).encode('utf-8').strip() 
  276   
283   
285       
286      template_file = 'feed_atom10.xml' 
287   
288 -    def __init__(self, status, categories=None, pageTitle=None): 
  290