OLD | NEW |
(Empty) | |
| 1 # -*- python -*- |
| 2 # ex: set syntax=python: |
| 3 |
| 4 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 5 # Use of this source code is governed by a BSD-style license that can be |
| 6 # found in the LICENSE file. |
| 7 |
| 8 # It has one job: define a dictionary named BuildmasterConfig. This |
| 9 # dictionary has a variety of keys to control different aspects of the |
| 10 # buildmaster. They are documented in docs/config.xhtml . |
| 11 |
| 12 from buildbot import locks |
| 13 from buildbot.changes import svnpoller |
| 14 from buildbot.scheduler import Dependent |
| 15 from buildbot.scheduler import Scheduler |
| 16 from buildbot.scheduler import Periodic |
| 17 |
| 18 from common import chromium_utils |
| 19 from master import build_utils |
| 20 from master import chromium_step |
| 21 from master import master_utils |
| 22 from master import slaves_list |
| 23 from master.factory import chromium_factory |
| 24 from master.factory import gclient_factory |
| 25 from master.factory import dart_factory |
| 26 from buildbot.process.buildstep import RemoteShellCommand |
| 27 |
| 28 import config |
| 29 ActiveMaster = config.Master.DartFYI |
| 30 |
| 31 # Hack to increase timeout for steps, dart2js debug checked mode takes more than |
| 32 # 8 hours. |
| 33 RemoteShellCommand.__init__.im_func.func_defaults = (None, |
| 34 1, |
| 35 1, |
| 36 1200, |
| 37 48*60*60, {}, |
| 38 'slave-config', |
| 39 True) |
| 40 |
| 41 MASTER_HOST = ActiveMaster.master_host |
| 42 WEB_STATUS = True |
| 43 MAIL_NOTIFIER = False |
| 44 TREE_GATE_KEEPER = False |
| 45 GOOD_REVISIONS = False |
| 46 MASTER_PORT = ActiveMaster.master_port |
| 47 |
| 48 |
| 49 # This is the dictionary that the buildmaster pays attention to. We also use |
| 50 # a shorter alias to save typing. |
| 51 c = BuildmasterConfig = {} |
| 52 |
| 53 config.DatabaseSetup(c, require_dbconfig=ActiveMaster.is_production_host) |
| 54 |
| 55 # 'slavePortnum' defines the TCP port to listen on. This must match the value |
| 56 # configured into the buildslaves (with their --master option) |
| 57 c['slavePortnum'] = ActiveMaster.slave_port |
| 58 |
| 59 # Setup a per slave lock to prevent more than one thing running at once on |
| 60 # a single slave. |
| 61 slave_lock = locks.SlaveLock('overload_lock', maxCount=1) |
| 62 |
| 63 |
| 64 # Slave allocation |
| 65 # build-base-name, category, platform, builder, tester |
| 66 variants = [] |
| 67 |
| 68 |
| 69 slaves = slaves_list.SlavesList('slaves.cfg', 'Dart') |
| 70 |
| 71 |
| 72 ####### CHANGESOURCES |
| 73 |
| 74 def DartTreeFileSplitter(path): |
| 75 pieces = path.split('/') |
| 76 if pieces[0] == 'trunk': |
| 77 return ('trunk', '/'.join(pieces[1:])) |
| 78 elif pieces[0] == 'branches': |
| 79 return ('/'.join(pieces[0:2]), |
| 80 '/'.join(pieces[2:])) |
| 81 else: |
| 82 return None |
| 83 |
| 84 dart_revision_url = "http://code.google.com/p/dart/source/detail?r=%s" |
| 85 |
| 86 # Polls config.Master.dart_url for changes |
| 87 poller = svnpoller.SVNPoller(svnurl=config.Master.dart_url, |
| 88 split_file=DartTreeFileSplitter, |
| 89 pollinterval=10, |
| 90 revlinktmpl=dart_revision_url) |
| 91 |
| 92 c['change_source'] = [poller] |
| 93 |
| 94 ####### SCHEDULERS |
| 95 |
| 96 ## configure the Schedulers |
| 97 |
| 98 builder_names = [] |
| 99 for v in variants: |
| 100 builder_names.append(v['name']) |
| 101 |
| 102 s = Scheduler( |
| 103 name='main', |
| 104 branch="branches/bleeding_edge", |
| 105 treeStableTimer=0, |
| 106 builderNames=builder_names |
| 107 ) |
| 108 |
| 109 c['schedulers'] = [s] |
| 110 |
| 111 |
| 112 ####### BUILDERS |
| 113 |
| 114 # buildbot/process/factory.py provides several BuildFactory classes you can |
| 115 # start with, which implement build processes for common targets (GNU |
| 116 # autoconf projects, CPAN perl modules, etc). The factory.BuildFactory is the |
| 117 # base class, and is configured with a series of BuildSteps. When the build |
| 118 # is run, the appropriate buildslave is told to execute each Step in turn. |
| 119 |
| 120 # the first BuildStep is typically responsible for obtaining a copy of the |
| 121 # sources. There are source-obtaining Steps in buildbot/process/step.py for |
| 122 # CVS, SVN, and others. |
| 123 |
| 124 builders = [] |
| 125 |
| 126 # ---------------------------------------------------------------------------- |
| 127 # FACTORIES |
| 128 |
| 129 factory_base = { |
| 130 'vm-mac': dart_factory.DartFactory('dart', 'vm-mac'), |
| 131 'vm-linux': dart_factory.DartFactory('dart', 'vm-linux'), |
| 132 'vm-win32': dart_factory.DartFactory('dart', 'vm-win32'), |
| 133 'dartc-linux': dart_factory.DartFactory('dart', 'dartc-linux'), |
| 134 'dart_client': dart_factory.DartFactory('dart', 'dart_client'), |
| 135 'dart-editor': dart_factory.DartFactory('dart', 'dart-editor'), |
| 136 'frog': dart_factory.DartFactory('dart', 'frog'), |
| 137 'frogsh': dart_factory.DartFactory('dart', 'frogsh'), |
| 138 } |
| 139 |
| 140 for v in variants: |
| 141 platform = v['platform'] |
| 142 base = factory_base[platform] |
| 143 if platform in ['dart_client', 'dart-editor']: |
| 144 v['factory_builder'] = base.DartAnnotatedFactory( |
| 145 python_script='dart/client/tools/buildbot_annotated_steps.py', |
| 146 ) |
| 147 else: |
| 148 v['factory_builder'] = base.DartFactory( |
| 149 slave_type='BuilderTester', |
| 150 clobber=False, |
| 151 options={ |
| 152 'mode': v['mode'], |
| 153 'arch': v['arch'], |
| 154 'name': v['name'], |
| 155 }, |
| 156 ) |
| 157 |
| 158 |
| 159 factories = [] |
| 160 |
| 161 |
| 162 primary_builders = [] |
| 163 for f in factories: |
| 164 primary_builders.append(f[0]) |
| 165 |
| 166 s_dartium = Scheduler( |
| 167 name='dartium', |
| 168 branch='branches/bleeding_edge', |
| 169 treeStableTimer=0, |
| 170 builderNames=primary_builders) |
| 171 c['schedulers'].append(s_dartium) |
| 172 |
| 173 # ---------------------------------------------------------------------------- |
| 174 # BUILDER DEFINITIONS |
| 175 |
| 176 # The 'builders' list defines the Builders. Each one is configured with a |
| 177 # dictionary, using the following keys: |
| 178 # name (required): the name used to describe this builder |
| 179 # slavename (required): which slave to use, must appear in c['slaves'] |
| 180 # builddir (required): which subdirectory to run the builder in |
| 181 # factory (required): a BuildFactory to define how the build is run |
| 182 # periodicBuildTime (optional): if set, force a build every N seconds |
| 183 # category (optional): it is not used in the normal 'buildbot' meaning. It is |
| 184 # used by gatekeeper to determine which steps it should |
| 185 # look for to close the tree. |
| 186 # |
| 187 |
| 188 c['builders'] = [] |
| 189 for v in variants: |
| 190 c['builders'].append({ |
| 191 'name': v['name'], |
| 192 'builddir': v['name'], |
| 193 'factory': v['factory_builder'], |
| 194 'slavenames': slaves.GetSlavesName(builder=v['name']), |
| 195 'category': v['category'], |
| 196 'locks': [slave_lock], |
| 197 }) |
| 198 |
| 199 |
| 200 for f in factories: |
| 201 c['builders'].append({ |
| 202 'name': f[0], |
| 203 'slavenames': slaves.GetSlavesName(builder=f[0]), |
| 204 'builddir': f[0], |
| 205 'factory': f[2], |
| 206 'category': '%s' % f[1], |
| 207 # Don't enable auto_reboot for people testing locally. |
| 208 'auto_reboot': ActiveMaster.is_production_host, |
| 209 }) |
| 210 |
| 211 ####### BUILDSLAVES |
| 212 |
| 213 # The 'slaves' list defines the set of allowable buildslaves. List all the |
| 214 # slaves registered to a builder. Remove dupes. |
| 215 c['slaves'] = master_utils.AutoSetupSlaves(c['builders'], |
| 216 config.Master.GetBotPassword()) |
| 217 |
| 218 # Make sure everything works together. |
| 219 master_utils.VerifySetup(c, slaves) |
| 220 |
| 221 |
| 222 ####### STATUS TARGETS |
| 223 |
| 224 # 'status' is a list of Status Targets. The results of each build will be |
| 225 # pushed to these targets. buildbot/status/*.py has a variety to choose from, |
| 226 # including web pages, email senders, and IRC bots. |
| 227 |
| 228 c['status'] = [] |
| 229 |
| 230 if WEB_STATUS: |
| 231 c['status'].append( |
| 232 master_utils.CreateWebStatus(MASTER_PORT, allowForce=True, |
| 233 public_html='./public_html', |
| 234 templates=['./templates'])) |
| 235 c['status'].append( |
| 236 master_utils.CreateWebStatus(ActiveMaster.master_port_alt, |
| 237 allowForce=False)) |
| 238 |
| 239 if MAIL_NOTIFIER: |
| 240 from buildbot.status.mail import MailNotifier |
| 241 c['status'].append(MailNotifier(fromaddr=ActiveMaster.from_address, |
| 242 mode='problem', |
| 243 sendToInterestedUsers=True, |
| 244 extraRecipients=['ricow@google.com'], |
| 245 lookup=master_utils.FilterDomain())) |
| 246 |
| 247 if TREE_GATE_KEEPER: |
| 248 from master import gatekeeper |
| 249 # This is the list of the builder categories and the corresponding critical |
| 250 # steps. If one critical step fails, gatekeeper will close the tree |
| 251 # automatically. |
| 252 categories_steps = { |
| 253 '': ['update scripts', 'update', 'clobber', 'clobber_packages'], |
| 254 'closer': ['update scripts', 'update', 'compile', 'unit_tests'], |
| 255 'info': [], |
| 256 'inprogress': [], |
| 257 'plugin': ['clobber', 'compile', |
| 258 'small_tests', 'medium_tests', 'large_tests'], |
| 259 'qa': ['unit_tests'], |
| 260 } |
| 261 exclusions = {} |
| 262 forgiving_steps = ['update scripts', 'update', 'svnkill', 'taskkill', |
| 263 'archived build'] |
| 264 c['status'].append(gatekeeper.GateKeeper( |
| 265 fromaddr=ActiveMaster.from_address, |
| 266 categories_steps=categories_steps, |
| 267 exclusions=exclusions, |
| 268 relayhost=config.Master.smtp, |
| 269 subject='buildbot %(result)s in %(projectName)s on %(builder)s, ' |
| 270 'revision %(revision)s', |
| 271 extraRecipients=ActiveMaster.tree_closing_notification_recipients, |
| 272 lookup='google.com', |
| 273 forgiving_steps=forgiving_steps)) |
| 274 |
| 275 if GOOD_REVISIONS: |
| 276 from master import goodrevisions |
| 277 # This is the list of builders with their respective list of critical steps |
| 278 # that all need to succeed to mark a revision as successful. A single failure |
| 279 # in any of the steps of any of the builders will mark the revision as failed. |
| 280 good_revision_steps = { |
| 281 '': ['update', 'compile'], |
| 282 } |
| 283 c['status'].append(goodrevisions.GoodRevisions( |
| 284 good_revision_steps=good_revision_steps, |
| 285 store_revisions_url=ActiveMaster.store_revisions_url)) |
| 286 |
| 287 |
| 288 # Keep last build logs, the default is too low. |
| 289 c['buildHorizon'] = 1000 |
| 290 c['logHorizon'] = 500 |
| 291 # Must be at least 2x the number of slaves. |
| 292 c['eventHorizon'] = 200 |
| 293 # Must be at least 1x the number of builds listed in console. |
| 294 c['buildCacheSize'] = 60 |
| 295 |
| 296 |
| 297 ####### DEBUGGING OPTIONS |
| 298 |
| 299 # if you set 'debugPassword', then you can connect to the buildmaster with |
| 300 # the diagnostic tool in contrib/debugclient.py . From this tool, you can |
| 301 # manually force builds and inject changes, which may be useful for testing |
| 302 # your buildmaster without actually commiting changes to your repository (or |
| 303 # before you have a functioning 'sources' set up). The debug tool uses the |
| 304 # same port number as the slaves do: 'slavePortnum'. |
| 305 |
| 306 #c['debugPassword'] = 'debugpassword' |
| 307 |
| 308 # if you set 'manhole', you can ssh into the buildmaster and get an |
| 309 # interactive python shell, which may be useful for debugging buildbot |
| 310 # internals. It is probably only useful for buildbot developers. You can also |
| 311 # use an authorized_keys file, or plain telnet. |
| 312 #from buildbot import manhole |
| 313 #c['manhole'] = manhole.PasswordManhole('tcp:9999:interface=127.0.0.1', |
| 314 # 'admin', 'password') |
| 315 |
| 316 |
| 317 ####### PROJECT IDENTITY |
| 318 |
| 319 # the 'projectName' string will be used to describe the project that this |
| 320 # buildbot is working on. For example, it is used as the title of the |
| 321 # waterfall HTML page. The 'projectURL' string will be used to provide a link |
| 322 # from buildbot HTML pages to your project's home page. |
| 323 |
| 324 c['projectName'] = ActiveMaster.project_name |
| 325 c['projectURL'] = config.Master.project_url |
| 326 |
| 327 # the 'buildbotURL' string should point to the location where the buildbot's |
| 328 # internal web server (usually the html.Waterfall page) is visible. This |
| 329 # typically uses the port number set in the Waterfall 'status' entry, but |
| 330 # with an externally-visible host name which the buildbot cannot figure out |
| 331 # without some help. |
| 332 |
| 333 c['buildbotURL'] = 'http://build.chromium.org/p/client.dart/' |
OLD | NEW |