def force(self, req, auth_ok=False): name = self.getAuthz(req).getUsername(req) reason = req.args.get("comments", ["<no reason specified>"])[0] branch = req.args.get("branch", [""])[0] revision = req.args.get("revision", [""])[0] repository = req.args.get("repository", [""])[0] project = req.args.get("project", [""])[0] log.msg("web forcebuild of builder '%s', branch='%s', revision='%s'," " repository='%s', project='%s' by user '%s'" % (self.builder_status.getName(), branch, revision, repository, project, name)) if not auth_ok: req_args = dict(name=name, reason=reason, branch=branch, revision=revision, repository=repository, project=project) return ForceBuildActionResource(self.builder_status, req_args) master = self.getBuildmaster(req) # keep weird stuff out of the branch revision, and property strings. branch_validate = master.config.validation['branch'] revision_validate = master.config.validation['revision'] if not branch_validate.match(branch): log.msg("bad branch '%s'" % branch) return Redirect(path_to_builder(req, self.builder_status)) if not revision_validate.match(revision): log.msg("bad revision '%s'" % revision) return Redirect(path_to_builder(req, self.builder_status)) properties = getAndCheckProperties(req) if properties is None: return Redirect(path_to_builder(req, self.builder_status)) if not branch: branch = None if not revision: revision = None d = master.db.sourcestamps.addSourceStamp(branch=branch, revision=revision, project=project, repository=repository) def make_buildset(ssid): r = ( "The web-page 'force build' button was pressed by '%s': %s\n" % (html.escape(name), html.escape(reason))) return master.addBuildset( builderNames=[self.builder_status.getName()], ssid=ssid, reason=r, properties=properties.asDict()) d.addCallback(make_buildset) d.addErrback(log.err, "(ignored) while trying to force build") # send the user back to the builder page return Redirect(path_to_builder(req, self.builder_status))
def force(self, req, auth_ok=False): name = req.args.get("username", ["<unknown>"])[0] reason = req.args.get("comments", ["<no reason specified>"])[0] branch = req.args.get("branch", [""])[0] revision = req.args.get("revision", [""])[0] repository = req.args.get("repository", [""])[0] project = req.args.get("project", [""])[0] log.msg("web forcebuild of builder '%s', branch='%s', revision='%s'," " repository='%s', project='%s' by user '%s'" % (self.builder_status.getName(), branch, revision, repository, project, name)) # check if this is allowed if not auth_ok: if not self.getAuthz(req).actionAllowed('forceBuild', req, self.builder_status): log.msg("..but not authorized") return Redirect(path_to_authfail(req)) # ensure that they've filled out the username field at least. if name == "<unknown>": log.msg("..but didn't include a username to blame") return Redirect(path_to_authfail(req)) # keep weird stuff out of the branch revision, and property strings. # TODO: centralize this somewhere. if not re.match(r'^[\w.+/~-]*$', branch): log.msg("bad branch '%s'" % branch) return Redirect(path_to_builder(req, self.builder_status)) if not re.match(r'^[ \w\.\-\/]*$', revision): log.msg("bad revision '%s'" % revision) return Redirect(path_to_builder(req, self.builder_status)) properties = getAndCheckProperties(req) if properties is None: return Redirect(path_to_builder(req, self.builder_status)) if not branch: branch = None if not revision: revision = None master = self.getBuildmaster(req) d = master.db.sourcestamps.addSourceStamp(branch=branch, revision=revision, project=project, repository=repository) def make_buildset(ssid): r = ( "The web-page 'force build' button was pressed by '%s': %s\n" % (html.escape(name), html.escape(reason))) return master.addBuildset( builderNames=[self.builder_status.getName()], ssid=ssid, reason=r, properties=properties.asDict()) d.addCallback(make_buildset) d.addErrback(log.err, "(ignored) while trying to force build") # send the user back to the builder page return Redirect(path_to_builder(req, self.builder_status))
def force(self, req, auth_ok=False): name = req.args.get("username", ["<unknown>"])[0] reason = req.args.get("comments", ["<no reason specified>"])[0] branch = req.args.get("branch", [""])[0] revision = req.args.get("revision", [""])[0] repository = req.args.get("repository", [""])[0] project = req.args.get("project", [""])[0] r = "The web-page 'force build' button was pressed by '%s': %s\n" \ % (html.escape(name), html.escape(reason)) log.msg("web forcebuild of builder '%s', branch='%s', revision='%s'," " repository='%s', project='%s' by user '%s'" % (self.builder_status.getName(), branch, revision, repository, project, name)) # check if this is allowed if not auth_ok: if not self.getAuthz(req).actionAllowed('forceBuild', req, self.builder_status): log.msg("..but not authorized") return Redirect(path_to_authfail(req)) # keep weird stuff out of the branch revision, and property strings. # TODO: centralize this somewhere. if not re.match(r'^[\w.+/~-]*$', branch): log.msg("bad branch '%s'" % branch) return Redirect(path_to_builder(req, self.builder_status)) if not re.match(r'^[ \w\.\-\/]*$', revision): log.msg("bad revision '%s'" % revision) return Redirect(path_to_builder(req, self.builder_status)) properties = getAndCheckProperties(req) if properties is None: return Redirect(path_to_builder(req, self.builder_status)) if not branch: branch = None if not revision: revision = None # TODO: if we can authenticate that a particular User pushed the # button, use their name instead of None, so they'll be informed of # the results. # TODO2: we can authenticate that a particular User pushed the button # now, so someone can write this support. but it requires a # buildbot.changes.changes.Change instance which is tedious at this # stage to compute s = SourceStamp(branch=branch, revision=revision, project=project, repository=repository) try: c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder_status.getName()) bc.submitBuildRequest(s, r, properties) except interfaces.NoSlaveError: # TODO: tell the web user that their request could not be # honored pass # send the user back to the builder page return Redirect(path_to_builder(req, self.builder_status))
def performAction(self, req): # check if this is allowed d = self.getAuthz(req).actionAllowed(self.action, req, self.builder_status) wfd = defer.waitForDeferred(d) yield wfd res = wfd.getResult() if not res: log.msg("..but not authorized") yield path_to_authfail(req) return master = self.getBuildmaster(req) # keep weird stuff out of the branch revision, and property strings. branch_validate = master.config.validation['branch'] revision_validate = master.config.validation['revision'] if not branch_validate.match(self.req_args['branch']): log.msg("bad branch '%s'" % self.req_args['branch']) yield path_to_builder(req, self.builder_status) return if not revision_validate.match(self.req_args['revision']): log.msg("bad revision '%s'" % self.req_args['revision']) yield path_to_builder(req, self.builder_status) return properties = getAndCheckProperties(req) if properties is None: yield path_to_builder(req, self.builder_status) return if not self.req_args['branch']: self.req_args['branch'] = None if not self.req_args['revision']: self.req_args['revision'] = None d = master.db.sourcestamps.addSourceStamp( branch=self.req_args['branch'], revision=self.req_args['revision'], project=self.req_args['project'], repository=self.req_args['repository']) wfd = defer.waitForDeferred(d) yield wfd ssid = wfd.getResult() r = ("The web-page 'force build' button was pressed by '%s': %s\n" % (html.escape( self.req_args['name']), html.escape(self.req_args['reason']))) d = master.addBuildset(builderNames=[self.builder_status.getName()], ssid=ssid, reason=r, properties=properties.asDict()) wfd = defer.waitForDeferred(d) yield wfd tup = wfd.getResult() # check that (bsid, brids) were properly stored if not isinstance(tup, (int, dict)): log.err("(ignored) while trying to force build") # send the user back to the builder page yield path_to_builder(req, self.builder_status)
def performAction(self, req): # check if this is allowed d = self.getAuthz(req).actionAllowed(self.action, req, self.builder_status) wfd = defer.waitForDeferred(d) yield wfd res = wfd.getResult() if not res: log.msg("..but not authorized") yield path_to_authfail(req) return master = self.getBuildmaster(req) # keep weird stuff out of the branch revision, and property strings. branch_validate = master.config.validation['branch'] revision_validate = master.config.validation['revision'] if not branch_validate.match(self.req_args['branch']): log.msg("bad branch '%s'" % self.req_args['branch']) yield path_to_builder(req, self.builder_status) return if not revision_validate.match(self.req_args['revision']): log.msg("bad revision '%s'" % self.req_args['revision']) yield path_to_builder(req, self.builder_status) return properties = getAndCheckProperties(req) if properties is None: yield path_to_builder(req, self.builder_status) return if not self.req_args['branch']: self.req_args['branch'] = None if not self.req_args['revision']: self.req_args['revision'] = None d = master.db.sourcestamps.addSourceStamp( branch=self.req_args['branch'], revision=self.req_args['revision'], project=self.req_args['project'], repository=self.req_args['repository']) wfd = defer.waitForDeferred(d) yield wfd ssid = wfd.getResult() r = ("The web-page 'force build' button was pressed by '%s': %s\n" % (html.escape(self.req_args['name']), html.escape(self.req_args['reason']))) d = master.addBuildset(builderNames=[self.builder_status.getName()], ssid=ssid, reason=r, properties=properties.asDict()) wfd = defer.waitForDeferred(d) yield wfd tup = wfd.getResult() # check that (bsid, brids) were properly stored if not isinstance(tup, (int, dict)): log.err("(ignored) while trying to force build") # send the user back to the builder page yield path_to_builder(req, self.builder_status)
def force(self, req, auth_ok=False): name = req.args.get("username", ["<unknown>"])[0] reason = req.args.get("comments", ["<no reason specified>"])[0] branch = req.args.get("branch", [""])[0] revision = req.args.get("revision", [""])[0] repository = req.args.get("repository", [""])[0] project = req.args.get("project", [""])[0] r = "The web-page 'force build' button was pressed by '%s': %s\n" \ % (html.escape(name), html.escape(reason)) log.msg("web forcebuild of builder '%s', branch='%s', revision='%s'," " repository='%s', project='%s' by user '%s'" % ( self.builder_status.getName(), branch, revision, repository, project, name)) # check if this is allowed if not auth_ok: if not self.getAuthz(req).actionAllowed('forceBuild', req, self.builder_status): log.msg("..but not authorized") return Redirect(path_to_authfail(req)) # keep weird stuff out of the branch revision, and property strings. # TODO: centralize this somewhere. if not re.match(r'^[\w.+/~-]*$', branch): log.msg("bad branch '%s'" % branch) return Redirect(path_to_builder(req, self.builder_status)) if not re.match(r'^[ \w\.\-\/]*$', revision): log.msg("bad revision '%s'" % revision) return Redirect(path_to_builder(req, self.builder_status)) properties = getAndCheckProperties(req) if properties is None: return Redirect(path_to_builder(req, self.builder_status)) if not branch: branch = None if not revision: revision = None # TODO: if we can authenticate that a particular User pushed the # button, use their name instead of None, so they'll be informed of # the results. # TODO2: we can authenticate that a particular User pushed the button # now, so someone can write this support. but it requires a # buildbot.changes.changes.Change instance which is tedious at this # stage to compute s = SourceStamp(branch=branch, revision=revision, project=project, repository=repository) try: c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder_status.getName()) bc.submitBuildRequest(s, r, properties) except interfaces.NoSlaveError: # TODO: tell the web user that their request could not be # honored pass # send the user back to the builder page return Redirect(path_to_builder(req, self.builder_status))
def force(self, req, auth_ok=False): name = req.args.get("username", ["<unknown>"])[0] reason = req.args.get("comments", ["<no reason specified>"])[0] branch = req.args.get("branch", [""])[0] revision = req.args.get("revision", [""])[0] repository = req.args.get("repository", [""])[0] project = req.args.get("project", [""])[0] log.msg("web forcebuild of builder '%s', branch='%s', revision='%s'," " repository='%s', project='%s' by user '%s'" % ( self.builder_status.getName(), branch, revision, repository, project, name)) # check if this is allowed if not auth_ok: if not self.getAuthz(req).actionAllowed('forceBuild', req, self.builder_status): log.msg("..but not authorized") return Redirect(path_to_authfail(req)) # ensure that they've filled out the username field at least. if name == "<unknown>": log.msg("..but didn't include a username to blame") return Redirect(path_to_authfail(req)) master = self.getBuildmaster(req) # keep weird stuff out of the branch revision, and property strings. branch_validate = master.config.validation['branch'] revision_validate = master.config.validation['revision'] if not branch_validate.match(branch): log.msg("bad branch '%s'" % branch) return Redirect(path_to_builder(req, self.builder_status)) if not revision_validate.match(revision): log.msg("bad revision '%s'" % revision) return Redirect(path_to_builder(req, self.builder_status)) properties = getAndCheckProperties(req) if properties is None: return Redirect(path_to_builder(req, self.builder_status)) if not branch: branch = None if not revision: revision = None d = master.db.sourcestamps.addSourceStamp(branch=branch, revision=revision, project=project, repository=repository) def make_buildset(ssid): r = ("The web-page 'force build' button was pressed by '%s': %s\n" % (html.escape(name), html.escape(reason))) return master.addBuildset( builderNames=[self.builder_status.getName()], ssid=ssid, reason=r, properties=properties.asDict()) d.addCallback(make_buildset) d.addErrback(log.err, "(ignored) while trying to force build") # send the user back to the builder page return Redirect(path_to_builder(req, self.builder_status))
def force(self, req, auth_ok=False): name = req.args.get("username", ["<unknown>"])[0] reason = req.args.get("comments", ["<no reason specified>"])[0] branch = req.args.get("branch", [""])[0] revision = req.args.get("revision", [""])[0] repository = req.args.get("repository", [""])[0] project = req.args.get("project", [""])[0] log.msg("web forcebuild of builder '%s', branch='%s', revision='%s'," " repository='%s', project='%s' by user '%s'" % ( self.builder_status.getName(), branch, revision, repository, project, name)) # check if this is allowed if not auth_ok: if not self.getAuthz(req).actionAllowed('forceBuild', req, self.builder_status): log.msg("..but not authorized") return Redirect(path_to_authfail(req)) # keep weird stuff out of the branch revision, and property strings. # TODO: centralize this somewhere. if not re.match(r'^[\w.+/~-]*$', branch): log.msg("bad branch '%s'" % branch) return Redirect(path_to_builder(req, self.builder_status)) if not re.match(r'^[ \w\.\-\/]*$', revision): log.msg("bad revision '%s'" % revision) return Redirect(path_to_builder(req, self.builder_status)) properties = getAndCheckProperties(req) if properties is None: return Redirect(path_to_builder(req, self.builder_status)) if not branch: branch = None if not revision: revision = None master = self.getBuildmaster(req) d = master.db.sourcestamps.createSourceStamp(branch=branch, revision=revision, project=project, repository=repository) def make_buildset(ssid): r = ("The web-page 'force build' button was pressed by '%s': %s\n" % (html.escape(name), html.escape(reason))) return master.addBuildset( builderNames=[self.builder_status.getName()], ssid=ssid, reason=r, properties=None) d.addCallback(make_buildset) d.addErrback(log.err, "(ignored) while trying to force build") # send the user back to the builder page return Redirect(path_to_builder(req, self.builder_status))
def request_line(self, build_request, req): when = time.strftime("%b %d %H:%M:%S", time.localtime(build_request.getSubmitTime())) delay = util.formatInterval(util.now() - build_request.getSubmitTime()) changes = build_request.source.changes if changes: change_strings = [] for c in changes: change_strings.append("<a href=\"%s\">%s</a>" % (path_to_change(req, c), c.who)) if len(change_strings) == 1: reason = "change by %s" % change_strings[0] else: reason = "changes by %s" % ", ".join(change_strings) elif build_request.source.revision: reason = build_request.source.revision else: reason = "no changes specified" if self.builder_control is not None: cancelURL = path_to_builder(req, self.builder_status) + '/cancelbuild' cancelButton = ''' <form action="%s" class="command cancelbuild" style="display:inline" method="post"> <input type="hidden" name="id" value="%s" /> <input type="submit" value="Cancel Build" /> </form>''' % (cancelURL, id(build_request)) else: cancelButton = "" return "<font size=\"-1\">(%s, waiting %s)</font>%s%s" % (when, delay, cancelButton, reason)
def performAction(self, req): # check if this is allowed d = self.getAuthz(req).actionAllowed(self.action, req, self.builder_status) wfd = defer.waitForDeferred(d) yield wfd res = wfd.getResult() if not res: log.msg("..but not authorized") yield path_to_authzfail(req) return master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] if schedulername == "<unknown>": yield path_to_builder(req, self.builder_status), "forcescheduler arg not found" return for sch in master.allSchedulers(): if schedulername == sch.name: try: d = sch.forceWithWebRequest(owner,self.builder_status.getName(),req) msg = "" except Exception, e: msg = html.escape(e.message.encode('ascii','ignore')) break
def performAction(self, req): url = None authz = self.getAuthz(req) res = yield authz.actionAllowed(self.action, req, self.builder) if not res: url = path_to_authzfail(req) else: # get a control object c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder.getName()) b = self.build_status builder_name = self.builder.getName() log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber())) name = authz.getUsernameFull(req) comments = _get_comments_from_request(req) reason = self.rebuildString % { 'build_number': b.getNumber(), 'owner': b.getInterestedUsers(), 'rebuild_owner': name, 'rebuild_comments': comments } useSourcestamp = req.args.get("useSourcestamp", None) if useSourcestamp and useSourcestamp == ['updated']: absolute = False else: absolute = True msg = "" extraProperties = getAndCheckProperties(req) if not bc or not b.isFinished() or extraProperties is None: msg = "could not rebuild: " if not b.isFinished(): msg += "build still not finished " if not bc: msg += "could not get builder control" else: tup = yield bc.rebuildBuild(b, reason=reason, extraProperties=extraProperties, absolute=absolute) # rebuildBuild returns None on error (?!) if not tup: msg = "rebuilding a build failed " + str(tup) # we're at # http://localhost:8080/builders/NAME/builds/5/rebuild?[args] # Where should we send them? # # Ideally it would be to the per-build page that they just started, # but we don't know the build number for it yet (besides, it might # have to wait for a current build to finish). The next-most # preferred place is somewhere that the user can see tangible # evidence of their build starting (or to see the reason that it # didn't start). This should be the Builder page. url = path_to_builder(req, self.builder), msg defer.returnValue(url)
def performAction(self, req): # check if this is allowed res = yield self.getAuthz(req).actionAllowed(self.action, req, self.builder_status) if not res: log.msg("..but not authorized") defer.returnValue(path_to_authzfail(req)) return master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] if schedulername == "<unknown>": defer.returnValue((path_to_builder(req, self.builder_status), "forcescheduler arg not found")) return args = {} # damn html's ungeneric checkbox implementation... for cb in req.args.get("checkbox", []): args[cb] = True args.update(req.args) builder_name = self.builder_status.getName() for sch in master.allSchedulers(): if schedulername == sch.name: try: yield sch.force(owner, builder_name, **args) msg = "" except ValidationError, e: msg = html.escape(e.message.encode('ascii', 'ignore')) break
def request_line(self, build_request, req): when = time.strftime("%b %d %H:%M:%S", time.localtime(build_request.getSubmitTime())) delay = util.formatInterval(util.now() - build_request.getSubmitTime()) changes = build_request.source.changes if changes: change_strings = [] for c in changes: change_strings.append("<a href=\"%s\">%s</a>" % (path_to_change(req, c), c.who)) if len(change_strings) == 1: reason = "change by %s" % change_strings[0] else: reason = "changes by %s" % ", ".join(change_strings) elif build_request.source.revision: reason = build_request.source.revision else: reason = "no changes specified" if self.builder_control is not None: cancelURL = path_to_builder(req, self.builder_status) + '/cancelbuild' cancelButton = ''' <form action="%s" class="command cancelbuild" style="display:inline" method="post"> <input type="hidden" name="id" value="%s" /> <input type="submit" value="Cancel Build" /> </form>''' % (cancelURL, id(build_request)) else: cancelButton = "" return "<font size=\"-1\">(%s, waiting %s)</font>%s%s" % ( when, delay, cancelButton, reason)
def stop(self, req, auth_ok=False): # check if this is allowed if not auth_ok: return StopBuildActionResource(self.build_status) b = self.build_status log.msg("web stopBuild of build %s:%s" % (b.getBuilder().getName(), b.getNumber())) name = self.getAuthz(req).getUsernameFull(req) comments = _get_comments_from_request(req) # html-quote both the username and comments, just to be safe reason = ("The web-page 'stop build' button was pressed by " "'%s': %s\n" % (html.escape(name), html.escape(comments))) c = interfaces.IControl(self.getBuildmaster(req)) bldrc = c.getBuilder(self.build_status.getBuilder().getName()) if bldrc: bldc = bldrc.getBuild(self.build_status.getNumber()) if bldc: bldc.stopBuild(reason) # we're at http://localhost:8080/svn-hello/builds/5/stop?[args] and # we want to go to: http://localhost:8080/svn-hello r = Redirect(path_to_builder(req, self.build_status.getBuilder())) d = defer.Deferred() reactor.callLater(1, d.callback, r) return DeferredResource(d)
def performAction(self, req): authz = self.getAuthz(req) d = authz.actionAllowed(self.action, req, self.build_status) wfd = defer.waitForDeferred(d) yield wfd res = wfd.getResult() if not res: yield path_to_authfail(req) return b = self.build_status log.msg("web stopBuild of build %s:%s" % \ (b.getBuilder().getName(), b.getNumber())) name = authz.getUsername(req) comments = req.args.get("comments", ["<no reason specified>"])[0] # html-quote both the username and comments, just to be safe reason = ("The web-page 'stop build' button was pressed by " "'%s': %s\n" % (html.escape(name), html.escape(comments))) c = interfaces.IControl(self.getBuildmaster(req)) bldrc = c.getBuilder(self.build_status.getBuilder().getName()) if bldrc: bldc = bldrc.getBuild(self.build_status.getNumber()) if bldc: bldc.stopBuild(reason) yield path_to_builder(req, self.build_status.getBuilder()) return
def force(self, req, builderNames): master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] if schedulername == "<unknown>": defer.returnValue((path_to_builder(req, self.builder_status), "forcescheduler arg not found")) return args = {} # decode all of the args encoding = getRequestCharset(req) for name, argl in req.args.iteritems(): if name == "checkbox": # damn html's ungeneric checkbox implementation... for cb in argl: args[cb.decode(encoding)] = True else: args[name] = [ arg.decode(encoding) for arg in argl ] for sch in master.allSchedulers(): if schedulername == sch.name: try: yield sch.force(owner, builderNames, **args) msg = "" except ValidationError, e: msg = html.escape(e.message.encode('ascii','ignore')) break
def performAction(self, req): # check if this is allowed res = yield self.getAuthz(req).actionAllowed(self.action, req, self.builder_status) if not res: log.msg("..but not authorized") defer.returnValue(path_to_authzfail(req)) return master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] if schedulername == "<unknown>": defer.returnValue((path_to_builder(req, self.builder_status), "forcescheduler arg not found")) return args = {} # damn html's ungeneric checkbox implementation... for cb in req.args.get("checkbox", []): args[cb] = True args.update(req.args) builder_name = self.builder_status.getName() for sch in master.allSchedulers(): if schedulername == sch.name: try: yield sch.force(owner, builder_name, **args) msg = "" except ValidationError, e: msg = html.escape(e.message.encode('ascii','ignore')) break
def performAction(self, req): url = None authz = self.getAuthz(req) res = yield authz.actionAllowed(self.action, req, self.builder) if not res: url = path_to_authzfail(req) else: # get a control object c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder.getName()) b = self.build_status builder_name = self.builder.getName() log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber())) name = authz.getUsernameFull(req) comments = _get_comments_from_request(req) reason = self.rebuildString % { 'build_number': b.getNumber(), 'owner': b.getInterestedUsers(), 'rebuild_owner': name, 'rebuild_comments': comments } useSourcestamp = req.args.get("useSourcestamp", None) if useSourcestamp and useSourcestamp == ['updated']: absolute = False else: absolute = True msg = "" extraProperties = getAndCheckProperties(req) if not bc or not b.isFinished() or extraProperties is None: msg = "could not rebuild: " if b.isFinished(): msg += "build still not finished " if bc: msg += "could not get builder control" else: tup = yield bc.rebuildBuild(b, reason=reason, extraProperties=extraProperties, absolute=absolute) # rebuildBuild returns None on error (?!) if not tup: msg = "rebuilding a build failed " + str(tup) # we're at # http://localhost:8080/builders/NAME/builds/5/rebuild?[args] # Where should we send them? # # Ideally it would be to the per-build page that they just started, # but we don't know the build number for it yet (besides, it might # have to wait for a current build to finish). The next-most # preferred place is somewhere that the user can see tangible # evidence of their build starting (or to see the reason that it # didn't start). This should be the Builder page. url = path_to_builder(req, self.builder), msg defer.returnValue(url)
def builder_cxt(self, request, builder): state, builds = builder.getState() # look for upcoming builds. We say the state is "waiting" if the # builder is otherwise idle and there is a scheduler which tells us a # build will be performed some time in the near future. TODO: this # functionality used to be in BuilderStatus.. maybe this code should # be merged back into it. upcoming = [] builderName = builder.getName() for s in self.getStatus(request).getSchedulers(): if builderName in s.listBuilderNames(): upcoming.extend(s.getPendingBuildTimes()) if state == "idle" and upcoming: state = "waiting" wfd = defer.waitForDeferred( builder.getPendingBuildRequestStatuses()) yield wfd n_pending = len(wfd.getResult()) cxt = { 'url': path_to_builder(request, builder), 'name': builder.getName(), 'state': state, 'n_pending': n_pending } yield cxt
def performAction(self, req): d = self.getAuthz(req).actionAllowed(self.action, req, self.build_status) wfd = defer.waitForDeferred(d) yield wfd res = wfd.getResult() if not res: yield path_to_authfail(req) return b = self.build_status log.msg("web stopBuild of build %s:%s" % \ (b.getBuilder().getName(), b.getNumber())) name = req.args.get("username", ["<unknown>"])[0] comments = req.args.get("comments", ["<no reason specified>"])[0] # html-quote both the username and comments, just to be safe reason = ("The web-page 'stop build' button was pressed by " "'%s': %s\n" % (html.escape(name), html.escape(comments))) c = interfaces.IControl(self.getBuildmaster(req)) bldrc = c.getBuilder(self.build_status.getBuilder().getName()) if bldrc: bldc = bldrc.getBuild(self.build_status.getNumber()) if bldc: bldc.stopBuild(reason) yield path_to_builder(req, self.build_status.getBuilder()) return
def builder_cxt(self, request, builder): state, builds = builder.getState() # look for upcoming builds. We say the state is "waiting" if the # builder is otherwise idle and there is a scheduler which tells us a # build will be performed some time in the near future. TODO: this # functionality used to be in BuilderStatus.. maybe this code should # be merged back into it. upcoming = [] builderName = builder.getName() for s in self.getStatus(request).getSchedulers(): if builderName in s.listBuilderNames(): upcoming.extend(s.getPendingBuildTimes()) if state == "idle" and upcoming: state = "waiting" wfd = defer.waitForDeferred(builder.getPendingBuildRequestStatuses()) yield wfd n_pending = len(wfd.getResult()) cxt = { 'url': path_to_builder(request, builder), 'name': builder.getName(), 'state': state, 'n_pending': n_pending } yield cxt
def performAction(self, req): authz = self.getAuthz(req) res = yield authz.actionAllowed(self.action, req, self.build_status) if not res: defer.returnValue(path_to_authzfail(req)) return b = self.build_status log.msg("web stopBuild of build %s:%s" % (b.getBuilder().getName(), b.getNumber())) name = authz.getUsernameFull(req) comments = _get_comments_from_request(req) # html-quote both the username and comments, just to be safe reason = ("The web-page 'stop build' button was pressed by " "'%s': %s\n" % (html.escape(name), html.escape(comments))) c = interfaces.IControl(self.getBuildmaster(req)) bldrc = c.getBuilder(self.build_status.getBuilder().getName()) if bldrc: bldc = bldrc.getBuild(self.build_status.getNumber()) if bldc: bldc.stopBuild(reason) defer.returnValue(path_to_builder(req, self.build_status.getBuilder()))
def builder_cxt(self, request, builder): state, builds = builder.getState() # look for upcoming builds. We say the state is "waiting" if the # builder is otherwise idle and there is a scheduler which tells us a # build will be performed some time in the near future. TODO: this # functionality used to be in BuilderStatus.. maybe this code should # be merged back into it. upcoming = [] builderName = builder.getName() for s in self.getStatus(request).getSchedulers(): if builderName in s.listBuilderNames(): upcoming.extend(s.getPendingBuildTimes()) if state == "idle" and upcoming: state = "waiting" # TODO: for now, this pending/upcoming stuff is in the "current # activity" box, but really it should go into a "next activity" row # instead. The only times it should show up in "current activity" is # when the builder is otherwise idle. cxt = { 'url': path_to_builder(request, builder), 'name': builder.getName(), 'state': state, 'n_pending': len(builder.getPendingBuilds()) } return cxt
def stop(self, req, auth_ok=False): # check if this is allowed if not auth_ok: if not self.getAuthz(req).actionAllowed('stopBuild', req, self.build_status): return Redirect(path_to_authfail(req)) b = self.build_status log.msg("web stopBuild of build %s:%s" % \ (b.getBuilder().getName(), b.getNumber())) name = req.args.get("username", ["<unknown>"])[0] comments = req.args.get("comments", ["<no reason specified>"])[0] # html-quote both the username and comments, just to be safe reason = ("The web-page 'stop build' button was pressed by " "'%s': %s\n" % (html.escape(name), html.escape(comments))) c = interfaces.IControl(self.getBuildmaster(req)) bldrc = c.getBuilder(self.build_status.getBuilder().getName()) if bldrc: bldc = bldrc.getBuild(self.build_status.getNumber()) if bldc: bldc.stopBuild(reason) # we're at http://localhost:8080/svn-hello/builds/5/stop?[args] and # we want to go to: http://localhost:8080/svn-hello r = Redirect(path_to_builder(req, self.build_status.getBuilder())) d = defer.Deferred() reactor.callLater(1, d.callback, r) return DeferredResource(d)
def performAction(self, req): try: request_id = req.args.get("id", [None])[0] if request_id == "all": cancel_all = True else: cancel_all = False request_id = int(request_id) except: request_id = None authz = self.getAuthz(req) if request_id: c = interfaces.IControl(self.getBuildmaster(req)) builder_control = c.getBuilder(self.builder_status.getName()) brcontrols = yield builder_control.getPendingBuildRequestControls() for build_req in brcontrols: if cancel_all or (build_req.brid == request_id): log.msg("Cancelling %s" % build_req) res = yield authz.actionAllowed('cancelPendingBuild', req, build_req) if res: build_req.cancel() else: defer.returnValue(path_to_authzfail(req)) return if not cancel_all: break defer.returnValue(path_to_builder(req, self.builder_status))
def performAction(self, req): authz = self.getAuthz(req) res = yield authz.actionAllowed(self.action, req, self.build_status) if not res: defer.returnValue(path_to_authzfail(req)) return b = self.build_status log.msg("web stopBuild of build %s:%s" % \ (b.getBuilder().getName(), b.getNumber())) name = authz.getUsernameFull(req) comments = req.args.get("comments", ["<no reason specified>"])[0] comments.decode(getRequestCharset(req)) # html-quote both the username and comments, just to be safe reason = ("The web-page 'stop build' button was pressed by " "'%s': %s\n" % (html.escape(name), html.escape(comments))) c = interfaces.IControl(self.getBuildmaster(req)) bldrc = c.getBuilder(self.build_status.getBuilder().getName()) if bldrc: bldc = bldrc.getBuild(self.build_status.getNumber()) if bldc: bldc.stopBuild(reason) defer.returnValue(path_to_builder(req, self.build_status.getBuilder()))
def force(self, req, builderNames): master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] if schedulername == "<unknown>": defer.returnValue((path_to_builder(req, self.builder_status), "forcescheduler arg not found")) return args = {} # decode all of the args encoding = getRequestCharset(req) for name, argl in req.args.iteritems(): if name == "checkbox": # damn html's ungeneric checkbox implementation... for cb in argl: args[cb.decode(encoding)] = True else: args[name] = [arg.decode(encoding) for arg in argl] for sch in master.allSchedulers(): if schedulername == sch.name: try: yield sch.force(owner, builderNames, **args) msg = "" except ValidationError, e: msg = html.escape(e.message.encode('ascii', 'ignore')) break
def stopchange(self, req, auth_ok=False): """Cancel all pending builds that include a given numbered change.""" try: request_change = req.args.get("change", [None])[0] request_change = int(request_change) except: request_change = None authz = self.getAuthz(req) if request_change: # FIXME: Please, for the love of god one day make there only be # one getPendingBuilds() with combined status info/controls c = interfaces.IControl(self.getBuildmaster(req)) builder_control = c.getBuilder(self.builder_status.getName()) build_controls = dict((x.brid, x) for x in builder_control.getPendingBuilds()) for build_req in self.builder_status.getPendingBuilds(): ss = build_req.getSourceStamp() if not ss.changes: continue for change in ss.changes: if change.number == request_change: control = build_controls[build_req.brid] log.msg("Cancelling %s" % control) if auth_ok or authz.actionAllowed('stopChange', req, control): control.cancel() else: return Redirect(path_to_authfail(req)) return Redirect(path_to_builder(req, self.builder_status))
def content(self, req, cxt): s = self.step_status b = s.getBuild() logs = cxt['logs'] = [] for l in s.getLogs(): # FIXME: If the step name has a / in it, this is broken # either way. If we quote it but say '/'s are safe, # it chops up the step name. If we quote it and '/'s # are not safe, it escapes the / that separates the # step name from the log number. logs.append({'has_contents': l.hasContents(), 'name': l.getName(), 'link': req.childLink("logs/%s" % urllib.quote(l.getName())) }) start, end = s.getTimes() if start: cxt['start'] = ctime(start) if end: cxt['end'] = ctime(end) cxt['elapsed'] = util.formatInterval(end - start) else: cxt['end'] = "Not Finished" cxt['elapsed'] = util.formatInterval(util.now() - start) cxt.update(dict(builder_link = path_to_builder(req, b.getBuilder()), build_link = path_to_build(req, b), b = b, s = s, result_css = css_classes[s.getResults()[0]])) template = req.site.buildbot_service.templates.get_template("buildstep.html"); return template.render(**cxt)
def performAction(self, req): # check if this is allowed res = yield self.getAuthz(req).actionAllowed(self.action, req, self.builder_status) if not res: log.msg("..but not authorized") defer.returnValue(path_to_authzfail(req)) return master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] if schedulername == "<unknown>": defer.returnValue((path_to_builder(req, self.builder_status), "forcescheduler arg not found")) return for sch in master.allSchedulers(): if schedulername == sch.name: try: yield sch.forceWithWebRequest( owner, self.builder_status.getName(), req) msg = "" except Exception, e: msg = html.escape(e.message.encode('ascii', 'ignore')) break
def content(self, req, cxt): tr = self.test_result b = self.status cxt['b'] = self.status logs = cxt['logs'] = [] for lname, log in tr.getLogs().items(): if isinstance(log, str): log = log.decode('utf-8') logs.append({ 'name': lname, 'log': log, 'link': req.childLink("logs/%s" % urllib.quote(lname)) }) cxt['text'] = tr.text cxt['result_word'] = Results[tr.getResults()] cxt.update( dict(builder_link=path_to_builder(req, b.getBuilder()), build_link=path_to_build(req, b), result_css=css_classes[tr.getResults()], b=b, tr=tr)) template = req.site.buildbot_service.templates.get_template( "testresult.html") return template.render(**cxt)
def cancelbuild(self, req): try: request_id = req.args.get("id", [None])[0] if request_id == "all": cancel_all = True else: cancel_all = False request_id = int(request_id) except: request_id = None authz = self.getAuthz(req) if request_id: c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder_status.getName()) for build_req in bc.getPendingBuilds(): if cancel_all or (build_req.brid == request_id): log.msg("Cancelling %s" % build_req) if authz.actionAllowed('cancelPendingBuild', req, build_req): build_req.cancel() else: return Redirect(path_to_authfail(req)) if not cancel_all: break return Redirect(path_to_builder(req, self.builder_status))
def stopchange(self, req, auth_ok=False): """Cancel all pending builds that include a given numbered change.""" try: request_change = req.args.get("change", [None])[0] request_change = int(request_change) except: request_change = None authz = self.getAuthz(req) if request_change: # FIXME: Please, for the love of god one day make there only be # one getPendingBuilds() with combined status info/controls c = interfaces.IControl(self.getBuildmaster(req)) builder_control = c.getBuilder(self.builder_status.getName()) build_controls = dict( (x.brid, x) for x in builder_control.getPendingBuilds()) for build_req in self.builder_status.getPendingBuilds(): ss = build_req.getSourceStamp() if not ss.changes: continue for change in ss.changes: if change.number == request_change: control = build_controls[build_req.brid] log.msg("Cancelling %s" % control) if auth_ok or authz.actionAllowed( 'stopChange', req, control): control.cancel() else: return Redirect(path_to_authfail(req)) return Redirect(path_to_builder(req, self.builder_status))
def cancelbuild(self, req): try: request_id = req.args.get("id", [None])[0] if request_id == "all": cancel_all = True else: cancel_all = False request_id = int(request_id) except: request_id = None authz = self.getAuthz(req) if request_id: c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder_status.getName()) for build_req in bc.getPendingBuilds(): if cancel_all or id(build_req.original_request.status) == request_id: log.msg("Cancelling %s" % build_req) if authz.actionAllowed("cancelPendingBuild", req, build_req): build_req.cancel() else: return Redirect(path_to_authfail(req)) if not cancel_all: break return Redirect(path_to_builder(req, self.builder_status))
def body(self, req): s = self.step_status b = s.getBuild() builder_name = b.getBuilder().getName() build_num = b.getNumber() data = "" data += '<h1>BuildStep <a href="%s">%s</a>:' % (path_to_builder(req, b.getBuilder()), builder_name) data += '<a href="%s">#%d</a>' % (path_to_build(req, b), build_num) data += ":%s</h1>\n" % s.getName() if s.isFinished(): data += "<h2>Finished</h2>\n" "<p>%s</p>\n" % html.escape("%s" % s.getText()) else: data += "<h2>Not Finished</h2>\n" "<p>ETA %s seconds</p>\n" % s.getETA() exp = s.getExpectations() if exp: data += "<h2>Expectations</h2>\n" "<ul>\n" for e in exp: data += "<li>%s: current=%s, target=%s</li>\n" % (html.escape(e[0]), e[1], e[2]) data += "</ul>\n" (start, end) = s.getTimes() if not start: start_text = end_text = elapsed = "Not Started" else: start_text = ctime(start) if end: end_text = ctime(end) elapsed = util.formatInterval(end - start) else: end_text = "Not Finished" elapsed = util.formatInterval(util.now() - start) data += "<h2>Timing</h2>\n" data += "<table>\n" data += "<tr><td>Start</td><td>%s</td></tr>\n" % start_text data += "<tr><td>End</td><td>%s</td></tr>\n" % end_text data += "<tr><td>Elapsed</td><td>%s</td></tr>\n" % elapsed data += "</table>\n" logs = s.getLogs() if logs: data += "<h2>Logs</h2>\n" "<ul>\n" for logfile in logs: if logfile.hasContents(): # FIXME: If the step name has a / in it, this is broken # either way. If we quote it but say '/'s are safe, # it chops up the step name. If we quote it and '/'s # are not safe, it escapes the / that separates the # step name from the log number. logname = logfile.getName() logurl = req.childLink("logs/%s" % urllib.quote(logname)) data += '<li><a href="%s">%s</a></li>\n' % (logurl, html.escape(logname)) else: data += "<li>%s</li>\n" % html.escape(logname) data += "</ul>\n" return data
def performAction(self, req): """Cancel all pending builds that include a given numbered change.""" success = yield self.stopChangeForBuilder(req, self.builder_status) if not success: defer.returnValue(path_to_authzfail(req)) else: defer.returnValue(path_to_builder(req, self.builder_status))
class ForceAction(ActionResource): @defer.inlineCallbacks def force(self, req, builderNames): master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] if schedulername == "<unknown>": try: for scheduler in master.allSchedulers(): if isinstance( scheduler, ForceScheduler ) and builderNames[0] in scheduler.builderNames: schedulername = scheduler.name break else: raise RuntimeError("Could not find force scheduler") except: defer.returnValue((path_to_builder( req, self.builder_status ), "forcescheduler arg not found, and could not find a default force scheduler for builderName" )) return args = {} # decode all of the args encoding = getRequestCharset(req) for name, argl in req.args.iteritems(): if name == "checkbox": # damn html's ungeneric checkbox implementation... for cb in argl: args[cb.decode(encoding)] = True else: args[name] = [arg.decode(encoding) for arg in argl] for scheduler in master.allSchedulers(): if schedulername == scheduler.name: try: yield scheduler.force(owner, builderNames, **args) msg = "" except ValidationError, e: msg = html.escape(e.message.encode('ascii', 'ignore')) break # send the user back to the proper page returnpage = args.get("returnpage", None) if "builders" in returnpage: defer.returnValue( (path_to_builders(req, self.builder_status.getProject()))) elif "builders_json" in returnpage: s = self.getStatus(req) defer.returnValue( (s.getBuildbotURL() + path_to_json_builders(req, self.builder_status.getProject()))) elif "pending_json" in returnpage and builderNames > 0: s = self.getStatus(req) defer.returnValue((s.getBuildbotURL() + path_to_json_pending(req, builderNames[0]))) defer.returnValue((path_to_builder(req, self.builder_status)))
def builder_row(self, bn, req, branches, num_builds): status = self.getStatus(req) builder = status.getBuilder(bn) state = builder.getState()[0] if state == 'building': state = 'idle' row = tags.tr() builderLink = path_to_builder(req, builder) row(tags.td(class_="box %s" % (state, ))(tags.a(href=builderLink)(bn))) builds = sorted([ build for build in builder.getCurrentBuilds() if set(map_branches(branches)) & builder._getBuildBranches(build) ], key=lambda build: build.getNumber(), reverse=True) builds.extend( builder.generateFinishedBuilds(map_branches(branches), num_builds=num_builds)) if builds: for b in builds: url = path_to_build(req, b) try: label = b.getProperty("got_revision") except KeyError: label = None # Label should never be "None", but sometimes # buildbot has disgusting bugs. if not label or label == "None" or len(str(label)) > 20: label = "#%d" % b.getNumber() if b.isFinished(): text = b.getText() else: when = b.getETA() if when: text = [ "%s" % (formatInterval(when), ), "%s" % (time.strftime( "%H:%M:%S", time.localtime(time.time() + when)), ) ] else: text = [] row( tags.td(align="center", bgcolor=_backgroundColors[b.getResults()], class_=("LastBuild box ", build_get_class(b)))([ (element, tags.br) for element in [tags.a(href=url)(label)] + text ])) else: row(tags.td(class_="LastBuild box")("no build")) return row
def ping(self, req): log.msg("web ping of builder '%s'" % self.builder_status.getName()) if not self.getAuthz(req).actionAllowed('pingBuilder', req, self.builder_status): log.msg("..but not authorized") return Redirect(path_to_authfail(req)) c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder_status.getName()) bc.ping() # send the user back to the builder page return Redirect(path_to_builder(req, self.builder_status))
def ping(self, req): log.msg("web ping of builder '%s'" % self.builder_status.getName()) if not self.getAuthz(req).actionAllowed("pingBuilder", req, self.builder_status): log.msg("..but not authorized") return Redirect(path_to_authfail(req)) c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder_status.getName()) bc.ping() # send the user back to the builder page return Redirect(path_to_builder(req, self.builder_status))
def body(self, req): s = self.step_status b = s.getBuild() builder_name = b.getBuilder().getName() build_num = b.getNumber() data = "" data += ('<h1>BuildStep <a href="%s">%s</a>:' % (path_to_builder(req, b.getBuilder()), builder_name)) data += '<a href="%s">#%d</a>' % (path_to_build(req, b), build_num) data += ":%s</h1>\n" % s.getName() if s.isFinished(): data += ("<h2>Finished</h2>\n" "<p>%s</p>\n" % html.escape("%s" % s.getText())) else: data += ("<h2>Not Finished</h2>\n" "<p>ETA %s seconds</p>\n" % s.getETA()) exp = s.getExpectations() if exp: data += ("<h2>Expectations</h2>\n" "<ul>\n") for e in exp: data += "<li>%s: current=%s, target=%s</li>\n" % \ (html.escape(e[0]), e[1], e[2]) data += "</ul>\n" (start, end) = s.getTimes() data += "<h2>Timing</h2>\n" data += "<table>\n" data += "<tr><td>Start</td><td>%s</td></tr>\n" % ctime(start) if end: data += "<tr><td>End</td><td>%s</td></tr>\n" % ctime(end) data += "<tr><td>Elapsed</td><td>%s</td></tr>\n" % util.formatInterval( end - start) data += "</table>\n" logs = s.getLogs() if logs: data += ("<h2>Logs</h2>\n" "<ul>\n") for logfile in logs: if logfile.hasContents(): # FIXME: If the step name has a / in it, this is broken # either way. If we quote it but say '/'s are safe, # it chops up the step name. If we quote it and '/'s # are not safe, it escapes the / that separates the # step name from the log number. logname = logfile.getName() logurl = req.childLink("logs/%s" % urllib.quote(logname)) data += ('<li><a href="%s">%s</a></li>\n' % (logurl, html.escape(logname))) else: data += '<li>%s</li>\n' % html.escape(logname) data += "</ul>\n" return data
def content(self, req, cxt): b = self.builder_status cxt['name'] = b.getName() slaves = b.getSlaves() connected_slaves = [s for s in slaves if s.isConnected()] cxt['current'] = [self.builder(x, req) for x in b.getCurrentBuilds()] cxt['pending'] = [] for pb in b.getPendingBuilds(): source = pb.getSourceStamp() changes = [] if source.changes: for c in source.changes: changes.append({ 'url' : path_to_change(req, c), 'who' : c.who}) if source.revision: reason = source.revision else: reason = "no changes specified" cxt['pending'].append({ 'when': time.strftime("%b %d %H:%M:%S", time.localtime(pb.getSubmitTime())), 'delay': util.formatInterval(util.now() - pb.getSubmitTime()), 'reason': reason, 'id': pb.brid, 'changes' : changes }) numbuilds = int(req.args.get('numbuilds', ['5'])[0]) recent = cxt['recent'] = [] for build in b.generateFinishedBuilds(num_builds=int(numbuilds)): recent.append(self.get_line_values(req, build, False)) sl = cxt['slaves'] = [] connected_slaves = 0 for slave in slaves: s = {} sl.append(s) s['link'] = path_to_slave(req, slave) s['name'] = slave.getName() c = s['connected'] = slave.isConnected() if c: s['admin'] = slave.getAdmin() connected_slaves += 1 cxt['connected_slaves'] = connected_slaves cxt['authz'] = self.getAuthz(req) cxt['builder_url'] = path_to_builder(req, b) template = req.site.buildbot_service.templates.get_template("builder.html") return template.render(**cxt)
def content(self, req, cxt): b = self.builder_status cxt["name"] = b.getName() slaves = b.getSlaves() connected_slaves = [s for s in slaves if s.isConnected()] cxt["current"] = [self.builder(x, req) for x in b.getCurrentBuilds()] cxt["pending"] = [] for pb in b.getPendingBuilds(): changes = [] if pb.source.changes: for c in pb.source.changes: changes.append({"url": path_to_change(req, c), "who": c.who}) if pb.source.revision: reason = pb.source.revision else: reason = "no changes specified" cxt["pending"].append( { "when": time.strftime("%b %d %H:%M:%S", time.localtime(pb.getSubmitTime())), "delay": util.formatInterval(util.now() - pb.getSubmitTime()), "reason": reason, "id": id(pb), "changes": changes, } ) numbuilds = int(req.args.get("numbuilds", ["5"])[0]) recent = cxt["recent"] = [] for build in b.generateFinishedBuilds(num_builds=int(numbuilds)): recent.append(self.get_line_values(req, build, False)) sl = cxt["slaves"] = [] connected_slaves = 0 for slave in slaves: s = {} sl.append(s) s["link"] = path_to_slave(req, slave) s["name"] = slave.getName() c = s["connected"] = slave.isConnected() if c: s["admin"] = slave.getAdmin() connected_slaves += 1 cxt["connected_slaves"] = connected_slaves cxt["authz"] = self.getAuthz(req) cxt["builder_url"] = path_to_builder(req, b) template = req.site.buildbot_service.templates.get_template("builder.html") return template.render(**cxt)
def force(self, req, builderNames): master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) scheduler_name = req.args.get("forcescheduler", ["<unknown>"])[0] args = self.decode_request_arguments(req) if scheduler_name == "<unknown>": scheduler = master.scheduler_manager.findSchedulerByBuilderName( builderNames[0], scheduler_type=ForceScheduler, ) else: scheduler = master.scheduler_manager.findSchedulerByName( name=scheduler_name) try: yield scheduler.force(owner, builderNames, **args) except ValidationError: pass except AttributeError: if scheduler_name == '<unknown>': defer.returnValue(( path_to_builder(req, self.builder_status), 'forcescheduler arg not found, and could not find a default force scheduler for builderName', ), ) # send the user back to the proper page returnpage = args.get("returnpage", {}) if "builders" in returnpage: defer.returnValue( (path_to_builders(req, self.builder_status.getProject()))) elif "builders_json" in returnpage: s = self.getStatus(req) defer.returnValue( (s.getBuildbotURL() + path_to_json_builders(req, self.builder_status.getProject()))) elif "pending_json" in returnpage and builderNames > 0: s = self.getStatus(req) defer.returnValue((s.getBuildbotURL() + path_to_json_pending(req, builderNames[0]))) defer.returnValue((path_to_builder(req, self.builder_status)))
def performAction(self, req): """Cancel all pending builds that include a given numbered change.""" wfd = defer.waitForDeferred( self.stopChangeForBuilder(req, self.builder_status)) yield wfd success = wfd.getResult() if not success: yield path_to_authfail(req) else: yield path_to_builder(req, self.builder_status)
def builder_row(self, bn, req, branches, num_builds): status = self.getStatus(req) builder = status.getBuilder(bn) state = builder.getState()[0] if state == 'building': state = 'idle' row = tags.tr() builderLink = path_to_builder(req, builder) row(tags.td(class_="box %s" % (state,)) (tags.a(href=builderLink)(bn))) builds = sorted([ build for build in builder.getCurrentBuilds() if set(map_branches(branches)) & builder._getBuildBranches(build) ], key=lambda build: build.getNumber(), reverse=True) builds.extend(builder.generateFinishedBuilds( map_branches(branches), num_builds=num_builds)) if builds: for b in builds: url = path_to_build(req, b) try: label = b.getProperty("got_revision") except KeyError: label = None # Label should never be "None", but sometimes # buildbot has disgusting bugs. if not label or label == "None" or len(str(label)) > 20: label = "#%d" % b.getNumber() if b.isFinished(): text = b.getText() else: when = b.getETA() if when: text = [ "%s" % (formatInterval(when),), "%s" % (time.strftime( "%H:%M:%S", time.localtime(time.time() + when)),) ] else: text = [] row(tags.td( align="center", bgcolor=_backgroundColors[b.getResults()], class_=("LastBuild box ", build_get_class(b)))([ (element, tags.br) for element in [tags.a(href=url)(label)] + text])) else: row(tags.td(class_="LastBuild box")("no build")) return row
def performAction(self, req): url = None authz = self.getAuthz(req) d = authz.actionAllowed(self.action, req, self.builder) wfd = defer.waitForDeferred(d) yield wfd res = wfd.getResult() if not res: url = path_to_authzfail(req) else: # get a control object c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder.getName()) b = self.build_status builder_name = self.builder.getName() log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber())) name = authz.getUsernameFull(req) comments = req.args.get("comments", ["<no reason specified>"])[0] reason = ("The web-page 'rebuild' button was pressed by " "'%s': %s\n" % (name, comments)) msg = "" extraProperties = getAndCheckProperties(req) if not bc or not b.isFinished() or extraProperties is None: msg = "could not rebuild: " if b.isFinished(): msg += "build still not finished " if bc: msg += "could not get builder control" else: d = bc.rebuildBuild(b, reason, extraProperties) wfd = defer.waitForDeferred(d) yield wfd tup = wfd.getResult() # check that (bsid, brids) were properly stored if not (isinstance(tup, tuple) and isinstance(tup[0], int) and isinstance(tup[1], dict)): msg = "rebuilding a build failed " + str(tup) # we're at # http://localhost:8080/builders/NAME/builds/5/rebuild?[args] # Where should we send them? # # Ideally it would be to the per-build page that they just started, # but we don't know the build number for it yet (besides, it might # have to wait for a current build to finish). The next-most # preferred place is somewhere that the user can see tangible # evidence of their build starting (or to see the reason that it # didn't start). This should be the Builder page. url = path_to_builder(req, self.builder), msg yield url
def performAction(self, req): url = None authz = self.getAuthz(req) d = authz.actionAllowed(self.action, req, self.builder) wfd = defer.waitForDeferred(d) yield wfd res = wfd.getResult() if not res: url = path_to_authzfail(req) else: # get a control object c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder.getName()) b = self.build_status builder_name = self.builder.getName() log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber())) name =authz.getUsernameFull(req) comments = req.args.get("comments", ["<no reason specified>"])[0] reason = ("The web-page 'rebuild' button was pressed by " "'%s': %s\n" % (name, comments)) msg = "" extraProperties = getAndCheckProperties(req) if not bc or not b.isFinished() or extraProperties is None: msg = "could not rebuild: " if b.isFinished(): msg += "build still not finished " if bc: msg += "could not get builder control" else: d = bc.rebuildBuild(b, reason, extraProperties) wfd = defer.waitForDeferred(d) yield wfd tup = wfd.getResult() # check that (bsid, brids) were properly stored if not (isinstance(tup, tuple) and isinstance(tup[0], int) and isinstance(tup[1], dict)): msg = "rebuilding a build failed "+ str(tup) # we're at # http://localhost:8080/builders/NAME/builds/5/rebuild?[args] # Where should we send them? # # Ideally it would be to the per-build page that they just started, # but we don't know the build number for it yet (besides, it might # have to wait for a current build to finish). The next-most # preferred place is somewhere that the user can see tangible # evidence of their build starting (or to see the reason that it # didn't start). This should be the Builder page. url = path_to_builder(req, self.builder), msg yield url
def content(self, req, cxt): b = self.build_status status = self.getStatus(req) req.setHeader('Cache-Control', 'no-cache') cxt['b'] = b cxt['path_to_builder'] = path_to_builder(req, b.getBuilder()) ssList = b.getSourceStamps() sourcestamps = cxt['sourcestamps'] = ssList all_got_revisions = b.getAllGotRevisions() cxt['got_revisions'] = all_got_revisions cxt.update(self.getCommonBuildInfo(req, b)) cxt['builds'] = [] for c in self.getChildren(req): cxt['builds'].append(self.getChildBuild(req, c)) pending = yield self.getPending(req) for p in pending: cxt['builds'].append(p) ps = cxt['properties'] = [] for name, value, source in b.getProperties().asList(): if not isinstance(value, dict): cxt_value = unicode(value) else: cxt_value = value p = {'name': name, 'value': cxt_value, 'source': source} if len(cxt_value) > 500: p['short_value'] = cxt_value[:500] ps.append(p) cxt['responsible_users'] = list(b.getResponsibleUsers()) exactly = True has_changes = False for ss in sourcestamps: exactly = exactly and (ss.revision is not None) has_changes = has_changes or ss.changes cxt['exactly'] = (exactly) or b.getChanges() cxt['has_changes'] = has_changes cxt['build_url'] = path_to_build(req, b) cxt['authz'] = self.getAuthz(req) cxt['shutting_down'] = status.shuttingDown template = req.site.buildbot_service.templates.get_template( "travis.build.html") defer.returnValue(template.render(**cxt))
def performAction(self, req): log.msg("web ping of builder '%s'" % self.builder_status.getName()) res = yield self.getAuthz(req).actionAllowed("pingBuilder", req, self.builder_status) if not res: log.msg("..but not authorized") defer.returnValue(path_to_authzfail(req)) return c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder_status.getName()) bc.ping() # send the user back to the builder page defer.returnValue(path_to_builder(req, self.builder_status))
def content(self, req, cxt): b = self.build_status status = self.getStatus(req) req.setHeader('Cache-Control', 'no-cache') cxt['b'] = b cxt['path_to_builder'] = path_to_builder(req, b.getBuilder()) ssList = b.getSourceStamps() sourcestamps = cxt['sourcestamps'] = ssList all_got_revisions = b.getAllGotRevisions() cxt['got_revisions'] = all_got_revisions cxt.update(self.getCommonBuildInfo(req, b)) cxt['builds'] = [] for c in self.getChildren(req): cxt['builds'].append(self.getChildBuild(req, c)) pending = yield self.getPending(req) for p in pending: cxt['builds'].append(p) ps = cxt['properties'] = [] for name, value, source in b.getProperties().asList(): if not isinstance(value, dict): cxt_value = unicode(value) else: cxt_value = value p = { 'name': name, 'value': cxt_value, 'source': source} if len(cxt_value) > 500: p['short_value'] = cxt_value[:500] ps.append(p) cxt['responsible_users'] = list(b.getResponsibleUsers()) exactly = True has_changes = False for ss in sourcestamps: exactly = exactly and (ss.revision is not None) has_changes = has_changes or ss.changes cxt['exactly'] = (exactly) or b.getChanges() cxt['has_changes'] = has_changes cxt['build_url'] = path_to_build(req, b) cxt['authz'] = self.getAuthz(req) cxt['shutting_down'] = status.shuttingDown template = req.site.buildbot_service.templates.get_template("travis.build.html") defer.returnValue(template.render(**cxt))
def performAction(self, req): # check if this is allowed res = yield self.getAuthz(req).actionAllowed(self.action, req, self.builder_status) if not res: log.msg("..but not authorized") defer.returnValue(path_to_authzfail(req)) return builderName = self.builder_status.getName() msg = yield self.force(req, [builderName]) # send the user back to the builder page defer.returnValue((path_to_builder(req, self.builder_status), msg))
def performAction(self, req): log.msg("web ping of builder '%s'" % self.builder_status.getName()) res = yield self.getAuthz(req).actionAllowed('pingBuilder', req, self.builder_status) if not res: log.msg("..but not authorized") defer.returnValue(path_to_authzfail(req)) return c = interfaces.IControl(self.getBuildmaster(req)) bc = c.getBuilder(self.builder_status.getName()) bc.ping() # send the user back to the builder page defer.returnValue(path_to_builder(req, self.builder_status))