Trees | Indices | Help |
|
---|
|
1 # This file is part of Buildbot. Buildbot is free software: you can 2 # redistribute it and/or modify it under the terms of the GNU General Public 3 # License as published by the Free Software Foundation, version 2. 4 # 5 # This program is distributed in the hope that it will be useful, but WITHOUT 6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 8 # details. 9 # 10 # You should have received a copy of the GNU General Public License along with 11 # this program; if not, write to the Free Software Foundation, Inc., 51 12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 13 # 14 # Copyright Buildbot Team Members 15 16 17 from twisted.web import html 18 from twisted.internet import defer, reactor 19 from twisted.web.util import Redirect, DeferredResource 20 21 import urllib, time 22 from twisted.python import log 23 from buildbot.status.web.base import HtmlResource, \ 24 css_classes, path_to_build, path_to_builder, path_to_slave, \ 25 getAndCheckProperties, ActionResource, path_to_authzfail 26 from buildbot.schedulers.forcesched import ForceScheduler, TextParameter 27 from buildbot.status.web.step import StepsResource 28 from buildbot.status.web.tests import TestsResource 29 from buildbot import util, interfaces32 37 38 @defer.deferredGenerator9240 url = None 41 authz = self.getAuthz(req) 42 d = authz.actionAllowed(self.action, req, self.builder) 43 wfd = defer.waitForDeferred(d) 44 yield wfd 45 res = wfd.getResult() 46 47 if not res: 48 url = path_to_authzfail(req) 49 else: 50 # get a control object 51 c = interfaces.IControl(self.getBuildmaster(req)) 52 bc = c.getBuilder(self.builder.getName()) 53 54 b = self.build_status 55 builder_name = self.builder.getName() 56 log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber())) 57 name =authz.getUsernameFull(req) 58 comments = req.args.get("comments", ["<no reason specified>"])[0] 59 reason = ("The web-page 'rebuild' button was pressed by " 60 "'%s': %s\n" % (name, comments)) 61 msg = "" 62 extraProperties = getAndCheckProperties(req) 63 if not bc or not b.isFinished() or extraProperties is None: 64 msg = "could not rebuild: " 65 if b.isFinished(): 66 msg += "build still not finished " 67 if bc: 68 msg += "could not get builder control" 69 else: 70 d = bc.rebuildBuild(b, reason, extraProperties) 71 wfd = defer.waitForDeferred(d) 72 yield wfd 73 tup = wfd.getResult() 74 # check that (bsid, brids) were properly stored 75 if not (isinstance(tup, tuple) and 76 isinstance(tup[0], int) and 77 isinstance(tup[1], dict)): 78 msg = "rebuilding a build failed "+ str(tup) 79 # we're at 80 # http://localhost:8080/builders/NAME/builds/5/rebuild?[args] 81 # Where should we send them? 82 # 83 # Ideally it would be to the per-build page that they just started, 84 # but we don't know the build number for it yet (besides, it might 85 # have to wait for a current build to finish). The next-most 86 # preferred place is somewhere that the user can see tangible 87 # evidence of their build starting (or to see the reason that it 88 # didn't start). This should be the Builder page. 89 90 url = path_to_builder(req, self.builder), msg 91 yield url95 99 100 @defer.deferredGenerator130102 authz = self.getAuthz(req) 103 d = authz.actionAllowed(self.action, req, self.build_status) 104 wfd = defer.waitForDeferred(d) 105 yield wfd 106 res = wfd.getResult() 107 108 if not res: 109 yield path_to_authzfail(req) 110 return 111 112 b = self.build_status 113 log.msg("web stopBuild of build %s:%s" % \ 114 (b.getBuilder().getName(), b.getNumber())) 115 name = authz.getUsernameFull(req) 116 comments = req.args.get("comments", ["<no reason specified>"])[0] 117 # html-quote both the username and comments, just to be safe 118 reason = ("The web-page 'stop build' button was pressed by " 119 "'%s': %s\n" % (html.escape(name), html.escape(comments))) 120 121 c = interfaces.IControl(self.getBuildmaster(req)) 122 bldrc = c.getBuilder(self.build_status.getBuilder().getName()) 123 if bldrc: 124 bldc = bldrc.getBuild(self.build_status.getNumber()) 125 if bldc: 126 bldc.stopBuild(reason) 127 128 yield path_to_builder(req, self.build_status.getBuilder()) 129 return133 addSlash = True 134 138312140 return ("Buildbot: %s Build #%d" % 141 (self.build_status.getBuilder().getName(), 142 self.build_status.getNumber()))143145 b = self.build_status 146 status = self.getStatus(req) 147 req.setHeader('Cache-Control', 'no-cache') 148 149 cxt['b'] = b 150 cxt['path_to_builder'] = path_to_builder(req, b.getBuilder()) 151 152 if not b.isFinished(): 153 step = b.getCurrentStep() 154 if not step: 155 cxt['current_step'] = "[waiting for Lock]" 156 else: 157 if step.isWaitingForLocks(): 158 cxt['current_step'] = "%s [waiting for Lock]" % step.getName() 159 else: 160 cxt['current_step'] = step.getName() 161 when = b.getETA() 162 if when is not None: 163 cxt['when'] = util.formatInterval(when) 164 cxt['when_time'] = time.strftime("%H:%M:%S", 165 time.localtime(time.time() + when)) 166 167 else: 168 cxt['result_css'] = css_classes[b.getResults()] 169 if b.getTestResults(): 170 cxt['tests_link'] = req.childLink("tests") 171 172 ss = cxt['ss'] = b.getSourceStamp() 173 174 if ss.branch is None and ss.revision is None and ss.patch is None and not ss.changes: 175 cxt['most_recent_rev_build'] = True 176 177 178 got_revision = b.getProperty("got_revision") 179 if got_revision: 180 cxt['got_revision'] = str(got_revision) 181 182 try: 183 cxt['slave_url'] = path_to_slave(req, status.getSlave(b.getSlavename())) 184 except KeyError: 185 pass 186 187 cxt['steps'] = [] 188 189 for s in b.getSteps(): 190 step = {'name': s.getName() } 191 192 if s.isFinished(): 193 if s.isHidden(): 194 continue 195 196 step['css_class'] = css_classes[s.getResults()[0]] 197 (start, end) = s.getTimes() 198 step['time_to_run'] = util.formatInterval(end - start) 199 elif s.isStarted(): 200 if s.isWaitingForLocks(): 201 step['css_class'] = "waiting" 202 step['time_to_run'] = "waiting for locks" 203 else: 204 step['css_class'] = "running" 205 step['time_to_run'] = "running" 206 else: 207 step['css_class'] = "not_started" 208 step['time_to_run'] = "" 209 210 cxt['steps'].append(step) 211 212 step['link'] = req.childLink("steps/%s" % 213 urllib.quote(s.getName(), safe='')) 214 step['text'] = " ".join(s.getText()) 215 step['urls'] = map(lambda x:dict(url=x[1],logname=x[0]), s.getURLs().items()) 216 217 step['logs']= [] 218 for l in s.getLogs(): 219 logname = l.getName() 220 step['logs'].append({ 'link': req.childLink("steps/%s/logs/%s" % 221 (urllib.quote(s.getName(), safe=''), 222 urllib.quote(logname, safe=''))), 223 'name': logname }) 224 225 scheduler = b.getProperty("scheduler", None) 226 parameters = {} 227 master = self.getBuildmaster(req) 228 for sch in master.allSchedulers(): 229 if isinstance(sch, ForceScheduler) and scheduler == sch.name: 230 for p in sch.all_fields: 231 parameters[p.name] = p 232 233 ps = cxt['properties'] = [] 234 for name, value, source in b.getProperties().asList(): 235 uvalue = unicode(value) 236 p = { 'name': name, 'value': uvalue, 'source': source} 237 if len(uvalue) > 500: 238 p['short_value'] = uvalue[:500] 239 if name in parameters: 240 param = parameters[name] 241 if isinstance(param, TextParameter): 242 p['text'] = param.value_to_text(value) 243 p['cols'] = param.cols 244 p['rows'] = param.rows 245 p['label'] = param.label 246 ps.append(p) 247 248 249 cxt['responsible_users'] = list(b.getResponsibleUsers()) 250 251 (start, end) = b.getTimes() 252 cxt['start'] = time.ctime(start) 253 if end: 254 cxt['end'] = time.ctime(end) 255 cxt['elapsed'] = util.formatInterval(end - start) 256 else: 257 now = util.now() 258 cxt['elapsed'] = util.formatInterval(now - start) 259 260 cxt['exactly'] = (ss.revision is not None) or b.getChanges() 261 262 cxt['build_url'] = path_to_build(req, b) 263 cxt['authz'] = self.getAuthz(req) 264 265 template = req.site.buildbot_service.templates.get_template("build.html") 266 return template.render(**cxt)267269 # check if this is allowed 270 if not auth_ok: 271 return StopBuildActionResource(self.build_status) 272 273 b = self.build_status 274 log.msg("web stopBuild of build %s:%s" % \ 275 (b.getBuilder().getName(), b.getNumber())) 276 277 name = self.getAuthz(req).getUsernameFull(req) 278 comments = req.args.get("comments", ["<no reason specified>"])[0] 279 # html-quote both the username and comments, just to be safe 280 reason = ("The web-page 'stop build' button was pressed by " 281 "'%s': %s\n" % (html.escape(name), html.escape(comments))) 282 283 c = interfaces.IControl(self.getBuildmaster(req)) 284 bldrc = c.getBuilder(self.build_status.getBuilder().getName()) 285 if bldrc: 286 bldc = bldrc.getBuild(self.build_status.getNumber()) 287 if bldc: 288 bldc.stopBuild(reason) 289 290 # we're at http://localhost:8080/svn-hello/builds/5/stop?[args] and 291 # we want to go to: http://localhost:8080/svn-hello 292 r = Redirect(path_to_builder(req, self.build_status.getBuilder())) 293 d = defer.Deferred() 294 reactor.callLater(1, d.callback, r) 295 return DeferredResource(d)296 300302 if path == "stop": 303 return self.stop(req) 304 if path == "rebuild": 305 return self.rebuild(req) 306 if path == "steps": 307 return StepsResource(self.build_status) 308 if path == "tests": 309 return TestsResource(self.build_status) 310 311 return HtmlResource.getChild(self, path, req)315 addSlash = True 316 320 323335325 try: 326 num = int(path) 327 except ValueError: 328 num = None 329 if num is not None: 330 build_status = self.builder_status.getBuild(num) 331 if build_status: 332 return StatusResourceBuild(build_status) 333 334 return HtmlResource.getChild(self, path, req)
Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Sun Mar 25 19:40:36 2012 | http://epydoc.sourceforge.net |