def CanMergeBuildRequests(req1, req2): """ Determine whether or not two BuildRequests can be merged. Note that the call to buildbot.sourcestamp.SourceStamp.canBeMergedWith() is conspicuously missing. This is because that method verifies that: 1. req1.source.repository == req2.source.repository 2. req1.source.project == req2.source.project 3. req1.source.branch == req2.source.branch 4. req1.patch == None and req2.patch = None 5. (req1.source.changes and req2.source.changes) or \ (not req1.source.changes and not req2.source.changes and \ req1.source.revision == req2.source.revision) Of the above, we want 1, 2, 3, and 5. Instead of 4, we want to make sure that neither request is a Trybot request. """ # Verify that the repositories are the same (#1 above). if req1.source.repository != req2.source.repository: return False # Verify that the projects are the same (#2 above). if req1.source.project != req2.source.project: return False # Verify that the branches are the same (#3 above). if req1.source.branch != req2.source.branch: return False # If either is a try request, don't merge (#4 above). if (builder_name_schema.IsTrybot(req1.buildername) or builder_name_schema.IsTrybot(req2.buildername)): return False # Verify that either: both requests are associated with changes OR neither # request is associated with a change but the revisions match (#5 above). if req1.source.changes and not req2.source.changes: return False if not req1.source.changes and req2.source.changes: return False if not (req1.source.changes and req2.source.changes): if req1.source.revision != req2.source.revision: return False return True
def __init__(self, status, include_only_cq_trybots=False): JsonResource.__init__(self, status) for builder_name in self.status.getBuilderNames(): if builder_name_schema.IsTrybot(builder_name) and ( not include_only_cq_trybots or builder_name in slaves_cfg.CQ_TRYBOTS): self.putChild( builder_name, BuilderJsonResource(status, status.getBuilder(builder_name)))
def isInterestingBuilder(self, builder_status): """ Override of gatekeeper.GateKeeper.isInterestingBuilder: http://src.chromium.org/viewvc/chrome/trunk/tools/build/scripts/master/gatekeeper.py?view=markup We modify it to actually check whether the builder should be considered by the GateKeeper, as indicated in its category name. """ ret = (not builder_name_schema.IsTrybot(builder_status.getName()) and chromium_notifier.ChromiumNotifier.isInterestingBuilder( self, builder_status)) log.msg('[gatekeeper-debug2] ======================') log.msg('[gatekeeper-debug2] is not trybot: %s' % (not builder_name_schema.IsTrybot(builder_status.getName()))) log.msg('[gatekeeper-debug2] isInterestingBuilder: %s' % (chromium_notifier.ChromiumNotifier.isInterestingBuilder( self, builder_status))) log.msg('[gatekeeper-debug2] builder_status.getName(): %s' % (builder_status.getName())) log.msg('[gatekeeper-debug2] ret: %s' % ret) log.msg('[gatekeeper-debug2] ======================') return ret
def buildMessage(self, name, build, results): if builder_name_schema.IsTrybot(build[0].getBuilder().name): if not hasattr(build[0].source, 'timestamp'): if 'patch_file_url' in build[0].getProperties(): build[0].source.timestamp = _ParseTimeStampFromURL( build[0].getProperty('patch_file_url')) subject = ( 'try %(result)s for changelist "%(reason)s" at %(timestamp)s' ) else: subject = 'try %(result)s for issue-patchset "%(reason)s"' # pylint: disable=W0201 self.subject = subject return TryMailNotifier.buildMessage(self, name, build, results)
def __init__(self, categories=None, num_events=200, num_events_max=None, title='Waterfall', only_show_failures=False, builder_filter=lambda x: not builder_name_schema.IsTrybot(x)): HtmlResource.__init__(self) self.categories = categories self.num_events = num_events self.num_events_max = num_events_max self.putChild("help", WaterfallHelp(categories)) self.BuilderFilter = builder_filter self.title = title self.only_show_failures = only_show_failures
def asDict(self, request): builders = request.args.get('builder', self.status.getBuilderNames()) data = {'builders': []} for builder_name in builders: if builder_name_schema.IsTrybot(builder_name): continue try: builder_status = self.status.getBuilder(builder_name) except KeyError: log.msg('status.getBuilder(%r) failed' % builder_name) continue outcome = base.ITopBox(builder_status).getBox(request).class_ lastbuild = 'LastBuild' if outcome.startswith(lastbuild): outcome = outcome[len(lastbuild):] data['builders'].append({ 'outcome': outcome.strip(), 'name': builder_name }) return data
def buildMessage(self, name, builds, results): if self.sendToInterestedUsers and self.lookup: for build in builds: # Loop through all builds we are emailing about if builder_name_schema.IsTrybot(build.getBuilder().name): return blame_list = set(build.getResponsibleUsers()) for change in build.getChanges( ): # Loop through all changes in a build if (change.comments and _COMMIT_BOT == utils.FixGitSvnEmail(change.who)): # If the change has been submitted by the commit bot then find the # original author and the reviewers and add them to the blame list for commit_queue_line in ( _COMMIT_QUEUE_AUTHOR_LINE, _COMMIT_QUEUE_REVIEWERS_LINE): users = re.search( '%s(.*?)\n' % commit_queue_line, change.comments).group(1).split(',') blame_list = blame_list.union(users) if change.who in blame_list: # Remove the commit bot from the blame list. blame_list.remove(change.who) # Git-svn tacks a git-svn-id onto the email addresses. Remove it. new_blamelist = [ utils.FixGitSvnEmail(email) for email in blame_list ] # pylint: disable=C0301 # Set the extended blamelist. It was originally set in # http://buildbot.net/buildbot/docs/0.8.4/reference/buildbot.process.build-pysrc.html # (line 339) build.setBlamelist(new_blamelist) return MailNotifier.buildMessage(self, name, builds, results)
def createEmail(self, msgdict, builderName, title, results, builds=None, patches=None, logs=None): # Trybots have their own Notifier if builder_name_schema.IsTrybot(builderName): return None m = MailNotifier.createEmail(self, msgdict, builderName, title, results, builds, patches, logs) if builds and builds[0].getSourceStamp().revision: m.replace_header( 'Subject', 'buildbot %(result)s in %(title)s for %(revision)s' % { 'result': Results[results], 'title': title, 'revision': builds[0].getSourceStamp().revision, }) return m
def getAllBuildsForRevision(self, status, request, last_revision, num_builds, categories, builders, debug_info): """Returns a dictionary of builds we need to inspect to be able to display the console page. The key is the builder name, and the value is an array of build we care about. We also returns a dictionary of builders we care about. The key is it's category. last_revision is the last revision we want to display in the page. categories is a list of categories to display. It is coming from the HTTP GET parameters. builders is a list of builders to display. It is coming from the HTTP GET parameters. """ all_builds = dict() # List of all builders in the dictionary. builder_list = dict() debug_info["builds_scanned"] = 0 # Get all the builders. builder_names = status.getBuilderNames()[:] for builder_name in builder_names: builder = status.getBuilder(builder_name) # Make sure we are interested in this builder. if categories and builder.category not in categories: continue if builders and builder_name not in builders: continue if builder_name_schema.IsTrybot(builder_name): continue # We want to display this builder. category_full = builder.category or 'default' category_parts = category_full.split('|') category = category_parts[0] if len(category_parts) > 1: subcategory = category_parts[1] else: subcategory = 'default' if not builder_list.get(category): builder_list[category] = {} if not builder_list[category].get(subcategory): builder_list[category][subcategory] = {} if not builder_list[category][subcategory].get(category_full): builder_list[category][subcategory][category_full] = [] b = {} b["color"] = "notstarted" b["pageTitle"] = builder_name b["url"] = "./builders/%s" % urllib.quote(builder_name, safe='() ') b["builderName"] = builder_name state, _ = status.getBuilder(builder_name).getState() # Check if it's offline, if so, the box is purple. if state == "offline": b["color"] = "offline" else: # If not offline, then display the result of the last # finished build. build = self.getHeadBuild(status.getBuilder(builder_name)) while build and not build.isFinished(): build = build.getPreviousBuild() if build: b["color"] = getResultsClass(build.getResults(), None, False) # Append this builder to the dictionary of builders. builder_list[category][subcategory][category_full].append(b) # Set the list of builds for this builder. all_builds[builder_name] = self.getBuildsForRevision( request, builder, builder_name, last_revision, num_builds, debug_info) return (builder_list, all_builds)