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 = 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) # 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) 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 asDict(self, request): result = {'builders': []} #Get codebases codebases = {} getCodebasesArg(request=request, codebases=codebases) result['latestRevisions'] = yield self.getLatestRevision(codebases) encoding = getRequestCharset(request) branches = [ branch.decode(encoding) for branch in request.args.get("branch", []) if branch ] result['comparisonURL'] = path_to_comparison(request, self.project_status.name, codebases) defers = [] for name in self.children: child = self.getChildWithDefault(name, request) d = child.asDict(request, codebases, branches, True) defers.append(d) for d in defers: r = yield d result['builders'].append(r) defer.returnValue(result)
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 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): 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 = urllib.quote(self.builder.getName(), safe='') builder_name_link = urllib.quote(self.builder.getName(), safe='') 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] comments.decode(getRequestCharset(req)) reason = ("The web-page 'rebuild' button was pressed " "'%s': %s\n" % (name, 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, newOwner=authz.getUsernameFull(req)) # 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): 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 = req.args.get("comments", ["<no reason specified>"])[0] comments.decode(getRequestCharset(req)) reason = ("The web-page 'rebuild' button was pressed by " "'%s': %s\n" % (name, 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 decode_request_arguments(request): args = {} encoding = getRequestCharset(request) for name, argl in request.args.iteritems(): if name == 'checkbox': for cb in argl: args[cb.decode(encoding)] = True else: args[name] = [arg.decode(encoding) for arg in argl] return args
def asDict(self, request, params=None): include_steps = True include_props = True # We pass params only if we are doing this directly and not from a user args = request.args if params is not None: args = params if "steps" in args: include_steps = True if "1" in args["steps"] else False if "props" in args: include_props = True if "1" in args["props"] else False results = getResultsArg(request) if self.builder_status is not None: codebases = {} getCodebasesArg(request=request, codebases=codebases) encoding = getRequestCharset(request) branches = [ b.decode(encoding) for b in request.args.get("branch", []) if b ] builds = yield self.builder_status.generateFinishedBuildsAsync( branches=map_branches(branches), codebases=codebases, results=results, num_builds=self.number) defer.returnValue([ b.asDict(request, include_artifacts=True, include_failure_url=True, include_steps=include_steps, include_properties=include_props) for b in builds ]) return if self.slave_status is not None: slavename = self.slave_status.getName() builds = yield self.status.generateFinishedBuildsAsync( num_builds=self.number, results=results, slavename=slavename) defer.returnValue([ rb.asDict(request=request, include_steps=False) for rb in builds ]) return
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 = req.args.get("comments", ["<no reason specified>"])[0] comments.decode(getRequestCharset(req)) 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: tup = yield bc.rebuildBuild(b, reason, extraProperties) # 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 defer.returnValue(url)
def asDict(self, request, codebases=None, branches=None, base_build_dict=False, params=None): # We pass params only if we are doing this directly and not from a user args = request.args if params is not None: args = params include_build_steps = self.getRequestArgumentValue( args=args, parameter="build_steps", defaultValue=True) include_build_props = self.getRequestArgumentValue( args=args, parameter="build_props", defaultValue=True) include_pending_builds = self.getRequestArgumentValue( args=args, parameter="pending_builds", defaultValue=False) if codebases is None or branches is None: #Get codebases codebases = {} getCodebasesArg(request=request, codebases=codebases) encoding = getRequestCharset(request) branches = [ branch.decode(encoding) for branch in request.args.get("branch", []) if branch ] builder_dict = yield self.builder_dict( self.builder, codebases, request, branches, base_build_dict, include_build_steps, include_build_props, include_pending_builds) if self.latest_rev: builder_dict['latestRevisions'] = yield self.getLatestRevision( codebases) defer.returnValue(builder_dict)
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 = req.args.copy() # decode all of the args encoding = getRequestCharset(req) for name, argl in args.iteritems(): args[name] = [ arg.decode(encoding) for arg in argl ] # damn html's ungeneric checkbox implementation... for cb in args.get("checkbox", []): args[cb] = True 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): 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 cancel 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 'Cancel Build' button was pressed by " "'%s': %s\n" % (html.escape(name), html.escape(comments))) if self.build_status.getResults() == RESUME: yield self.build_status.builder.cancelBuildRequestsOnResume( self.build_status.getNumber()) defer.returnValue(path_to_build(req, self.build_status))
def content(self, req, cxt): status = self.getStatus(req) encoding = getRequestCharset(req) builders = req.args.get("builder", status.getBuilderNames()) branches = [ b.decode(encoding) for b in req.args.get("branch", []) if b ] # get counts of pending builds for each builder brstatus_ds = [] brcounts = {} def keep_count(statuses, builderName): brcounts[builderName] = len(statuses) for builderName in builders: builder_status = status.getBuilder(builderName) d = builder_status.getPendingBuildRequestStatuses() d.addCallback(keep_count, builderName) brstatus_ds.append(d) yield defer.gatherResults(brstatus_ds) cxt['branches'] = branches bs = cxt['builders'] = [] building = 0 online = 0 base_builders_url = path_to_root(req) + "builders/" for bn in builders: bld = { 'link': base_builders_url + urllib.quote(bn, safe=''), 'name': bn } bs.append(bld) builder = status.getBuilder(bn) builds = list(builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if builds: b = builds[0] bld['build_url'] = (bld['link'] + "/builds/%d" % b.getNumber()) label = None all_got_revisions = b.getAllGotRevisions() # If len = 1 then try if revision can be used as label. if len(all_got_revisions) == 1: label = all_got_revisions[all_got_revisions.keys()[0]] if not label or len(str(label)) > 20: label = "#%d" % b.getNumber() bld['build_label'] = label bld['build_text'] = " ".join(b.getText()) bld['build_css_class'] = build_get_class(b) current_box = ICurrentBox(builder).getBox(status, brcounts) bld['current_box'] = current_box.td() builder_status = builder.getState()[0] if builder_status == "building": building += 1 online += 1 elif builder_status != "offline": online += 1 cxt['authz'] = self.getAuthz(req) cxt['num_building'] = building cxt['num_online'] = online buildForceContext(cxt, req, self.getBuildmaster(req)) template = req.site.buildbot_service.templates.get_template("builders.html") defer.returnValue(template.render(**cxt))
def _get_comments_from_request(req): comments = req.args.get("comments", ["<no reason specified>"])[0] return comments.decode(getRequestCharset(req))
def do_test_getRequestCharset(self, hdr, exp): req = mock.Mock() req.getHeader.return_value = hdr self.assertEqual(base.getRequestCharset(req), exp)
def content(self, req, cxt): status = self.getStatus(req) encoding = getRequestCharset(req) showTags = req.args.get("tag", []) if not showTags: showTags = req.args.get("category", []) if not showTags: showTags = None builders = req.args.get("builder", status.getBuilderNames(tags=showTags)) branches = [ b.decode(encoding) for b in req.args.get("branch", []) if b ] # get counts of pending builds for each builder brstatus_ds = [] brcounts = {} def keep_count(statuses, builderName): brcounts[builderName] = len(statuses) for builderName in builders: builder_status = status.getBuilder(builderName) d = builder_status.getPendingBuildRequestStatuses() d.addCallback(keep_count, builderName) brstatus_ds.append(d) yield defer.gatherResults(brstatus_ds) cxt['branches'] = branches bs = cxt['builders'] = [] building = 0 online = 0 base_builders_url = path_to_root(req) + "builders/" for bn in builders: bld = { 'link': base_builders_url + urllib.quote(bn, safe=''), 'tags': status.getBuilder(bn).tags, 'name': bn } bs.append(bld) builder = status.getBuilder(bn) builds = list( builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if builds: b = builds[0] bld['build_url'] = (bld['link'] + "/builds/%d" % b.getNumber()) label = None all_got_revisions = b.getAllGotRevisions() # If len = 1 then try if revision can be used as label. if len(all_got_revisions) == 1: label = all_got_revisions[all_got_revisions.keys()[0]] if not label or len(str(label)) > 20: label = "#%d" % b.getNumber() bld['build_label'] = label bld['build_text'] = " ".join(b.getText()) bld['build_css_class'] = build_get_class(b) current_box = ICurrentBox(builder).getBox(status, brcounts) bld['current_box'] = current_box.td() builder_status = builder.getState()[0] if builder_status == "building": building += 1 online += 1 elif builder_status != "offline": online += 1 cxt['authz'] = self.getAuthz(req) cxt['num_building'] = building cxt['num_online'] = online buildForceContext(cxt, req, self.getBuildmaster(req)) template = req.site.buildbot_service.templates.get_template( "builders.html") defer.returnValue(template.render(**cxt))
def content(self, request, cxt): status = self.getStatus(request) args = request.args.copy() # decode all of the args encoding = getRequestCharset(request) for name, argl in args.iteritems(): if '_branch' in name: args[name] = [ self.decodeFromURL(arg, encoding) for arg in argl ] #Get builder info builder_status = None if args.has_key("builder_name") and len(args["builder_name"]) == 1: builder_status = status.getBuilder( self.decodeFromURL(args["builder_name"][0], encoding)) bm = self.getBuildmaster(request) cxt['slaves'] = [ s for s in builder_status.getSlaves() if s.isConnected() ] cxt['slaves'] = sorted(cxt['slaves'], key=attrgetter('friendly_name')) #Get branches encoding = getRequestCharset(request) branches = [ b.decode(encoding) for b in args.get("branch", []) if b ] cxt['branches'] = branches return_page = "" if args.has_key("return_page"): return_page = args['return_page'] if not isinstance(return_page, basestring): return_page = args['return_page'][0] #Add scheduler info buildForceContext(cxt, request, self.getBuildmaster(request), builder_status.getName()) #URL to force page with return param url = args['builder_url'][0] url_parts = list(urlparse(url)) if len(url_parts) > 0 and len(return_page) > 0: return_page = "&returnpage={0}".format(return_page) else: return_page = "?returnpage={0}".format(return_page) cxt['return_page'] = return_page url_parts[2] += "/force" url_parts[4] += return_page force_url = urlunparse(url_parts) cxt['force_url'] = force_url authz = self.getAuthz(request) cxt['is_admin'] = yield authz.getUserAttr(request, 'is_admin', 0) cxt['rt_update'] = args request.args = args template = request.site.buildbot_service.templates.get_template( "force_build_dialog.html") defer.returnValue(template.render(**cxt)) else: page = ErrorPage(INTERNAL_SERVER_ERROR, "Missing parameters", "Not all parameters were given") defer.returnValue(page.render(request))