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