Package buildbot :: Package status :: Package web :: Module build
[frames] | no frames]

Source Code for Module buildbot.status.web.build

  1   
  2  from twisted.web import html 
  3  from twisted.web.util import Redirect, DeferredResource 
  4  from twisted.internet import defer, reactor 
  5   
  6  import urllib, time 
  7  from twisted.python import log 
  8  from buildbot.status.web.base import HtmlResource, \ 
  9       css_classes, path_to_build, path_to_builder, path_to_slave, \ 
 10       getAndCheckProperties, path_to_authfail 
 11   
 12  from buildbot.status.web.step import StepsResource 
 13  from buildbot import util, interfaces 
 14   
 15   
 16   
 17  # /builders/$builder/builds/$buildnum 
18 -class StatusResourceBuild(HtmlResource):
19 addSlash = True 20
21 - def __init__(self, build_status):
24
25 - def getTitle(self, request):
26 return ("Buildbot: %s Build #%d" % 27 (self.build_status.getBuilder().getName(), 28 self.build_status.getNumber()))
29
30 - def content(self, req, cxt):
31 b = self.build_status 32 status = self.getStatus(req) 33 34 cxt['b'] = b 35 cxt['path_to_builder'] = path_to_builder(req, b.getBuilder()) 36 37 if not b.isFinished(): 38 when = b.getETA() 39 if when is not None: 40 cxt['when'] = util.formatInterval(when) 41 cxt['when_time'] = time.strftime("%H:%M:%S", 42 time.localtime(time.time() + when)) 43 44 else: 45 cxt['result_css'] = css_classes[b.getResults()] 46 if b.getTestResults(): 47 cxt['tests_link'] = req.childLink("tests") 48 49 ss = cxt['ss'] = b.getSourceStamp() 50 51 if ss.branch is None and ss.revision is None and ss.patch is None and not ss.changes: 52 cxt['most_recent_rev_build'] = True 53 54 55 got_revision = None 56 try: 57 got_revision = b.getProperty("got_revision") 58 except KeyError: 59 pass 60 if got_revision: 61 cxt['got_revision'] = str(got_revision) 62 63 try: 64 cxt['slave_url'] = path_to_slave(req, status.getSlave(b.getSlavename())) 65 except KeyError: 66 pass 67 68 cxt['steps'] = [] 69 70 for s in b.getSteps(): 71 step = {'name': s.getName() } 72 cxt['steps'].append(step) 73 74 if s.isFinished(): 75 step['css_class'] = css_classes[s.getResults()[0]] 76 (start, end) = s.getTimes() 77 step['time_to_run'] = util.formatInterval(end - start) 78 elif s.isStarted(): 79 step['css_class'] = "running" 80 step['time_to_run'] = "running" 81 else: 82 step['css_class'] = "not_started" 83 step['time_to_run'] = "" 84 85 step['link'] = req.childLink("steps/%s" % urllib.quote(s.getName())) 86 step['text'] = " ".join(s.getText()) 87 step['urls'] = map(lambda x:dict(url=x[1],logname=x[0]), s.getURLs().items()) 88 89 step['logs']= [] 90 for l in s.getLogs(): 91 logname = l.getName() 92 step['logs'].append({ 'link': req.childLink("steps/%s/logs/%s" % 93 (urllib.quote(s.getName()), 94 urllib.quote(logname))), 95 'name': logname }) 96 97 ps = cxt['properties'] = [] 98 for name, value, source in b.getProperties().asList(): 99 value = str(value) 100 p = { 'name': name, 'value': value, 'source': source} 101 if len(value) > 500: 102 p['short_value'] = value[:500] 103 104 ps.append(p) 105 106 107 cxt['responsible_users'] = list(b.getResponsibleUsers()) 108 109 (start, end) = b.getTimes() 110 cxt['start'] = time.ctime(start) 111 if end: 112 cxt['end'] = time.ctime(end) 113 cxt['elapsed'] = util.formatInterval(end - start) 114 else: 115 now = util.now() 116 cxt['elapsed'] = util.formatInterval(now - start) 117 118 cxt['exactly'] = (ss.revision is not None) or b.getChanges() 119 120 cxt['build_url'] = path_to_build(req, b) 121 cxt['authz'] = self.getAuthz(req) 122 123 template = req.site.buildbot_service.templates.get_template("build.html") 124 return template.render(**cxt)
125
126 - def stop(self, req, auth_ok=False):
127 # check if this is allowed 128 if not auth_ok: 129 if not self.getAuthz(req).actionAllowed('stopBuild', req, self.build_status): 130 return Redirect(path_to_authfail(req)) 131 132 b = self.build_status 133 log.msg("web stopBuild of build %s:%s" % \ 134 (b.getBuilder().getName(), b.getNumber())) 135 name = req.args.get("username", ["<unknown>"])[0] 136 comments = req.args.get("comments", ["<no reason specified>"])[0] 137 # html-quote both the username and comments, just to be safe 138 reason = ("The web-page 'stop build' button was pressed by " 139 "'%s': %s\n" % (html.escape(name), html.escape(comments))) 140 141 c = interfaces.IControl(self.getBuildmaster(req)) 142 bldrc = c.getBuilder(self.build_status.getBuilder().getName()) 143 if bldrc: 144 bldc = bldrc.getBuild(self.build_status.getNumber()) 145 if bldc: 146 bldc.stopBuild(reason) 147 148 # we're at http://localhost:8080/svn-hello/builds/5/stop?[args] and 149 # we want to go to: http://localhost:8080/svn-hello 150 r = Redirect(path_to_builder(req, self.build_status.getBuilder())) 151 d = defer.Deferred() 152 reactor.callLater(1, d.callback, r) 153 return DeferredResource(d)
154
155 - def rebuild(self, req):
156 # check auth 157 if not self.getAuthz(req).actionAllowed('forceBuild', req, self.build_status.getBuilder()): 158 return Redirect(path_to_authfail(req)) 159 160 # get a control object 161 c = interfaces.IControl(self.getBuildmaster(req)) 162 bc = c.getBuilder(self.build_status.getBuilder().getName()) 163 164 b = self.build_status 165 builder_name = b.getBuilder().getName() 166 log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber())) 167 name = req.args.get("username", ["<unknown>"])[0] 168 comments = req.args.get("comments", ["<no reason specified>"])[0] 169 reason = ("The web-page 'rebuild' button was pressed by " 170 "'%s': %s\n" % (name, comments)) 171 extraProperties = getAndCheckProperties(req) 172 if not bc or not b.isFinished() or extraProperties is None: 173 log.msg("could not rebuild: bc=%s, isFinished=%s" 174 % (bc, b.isFinished())) 175 # TODO: indicate an error 176 else: 177 bc.rebuildBuild(b, reason, extraProperties) 178 # we're at 179 # http://localhost:8080/builders/NAME/builds/5/rebuild?[args] 180 # Where should we send them? 181 # 182 # Ideally it would be to the per-build page that they just started, 183 # but we don't know the build number for it yet (besides, it might 184 # have to wait for a current build to finish). The next-most 185 # preferred place is somewhere that the user can see tangible 186 # evidence of their build starting (or to see the reason that it 187 # didn't start). This should be the Builder page. 188 189 r = Redirect(path_to_builder(req, self.build_status.getBuilder())) 190 d = defer.Deferred() 191 reactor.callLater(1, d.callback, r) 192 return DeferredResource(d)
193
194 - def getChild(self, path, req):
195 if path == "stop": 196 return self.stop(req) 197 if path == "rebuild": 198 return self.rebuild(req) 199 if path == "steps": 200 return StepsResource(self.build_status) 201 202 return HtmlResource.getChild(self, path, req)
203 204 # /builders/$builder/builds
205 -class BuildsResource(HtmlResource):
206 addSlash = True 207
208 - def __init__(self, builder_status):
209 HtmlResource.__init__(self) 210 self.builder_status = builder_status
211
212 - def content(self, req, cxt):
213 return "subpages shows data for each build"
214
215 - def getChild(self, path, req):
216 try: 217 num = int(path) 218 except ValueError: 219 num = None 220 if num is not None: 221 build_status = self.builder_status.getBuild(num) 222 if build_status: 223 return StatusResourceBuild(build_status) 224 225 return HtmlResource.getChild(self, path, req)
226