Ticket #296: idleScheduler-again.diff
| File idleScheduler-again.diff, 10.4 kB (added by bhearsum, 7 months ago) |
|---|
-
a/buildbot/scheduler.py
old new 393 393 return [] 394 394 395 395 def doPeriodicBuild(self): 396 396 bs = buildset.BuildSet(self.builderNames, 397 397 SourceStamp(branch=self.branch), 398 398 self.reason, 399 399 properties=self.properties) 400 400 self.submitBuildSet(bs) 401 402 403 404 class Idle(BaseUpstreamScheduler): 405 compare_attrs = ('name', 'builderNames', 'upstream', 'idleBuildTimer', 406 'branch', 'properties') 407 408 def __init__(self, name, builderNames, upstream, idleBuildTimer, 409 branch=None, properties={}): 410 BaseUpstreamScheduler.__init__(self, name, properties) 411 self.builderNames = builderNames 412 self.branch = branch 413 self.idleBuildTimer = idleBuildTimer 414 self.reason = ("The Idle scheduler name '%s' triggered this build" 415 % name) 416 self.runningBuilds = 0 417 418 assert isinstance(upstream, (list, tuple)), \ 419 "Upstream schedulers in Idle scheduler must be a list" 420 assert len(upstream) > 0, \ 421 "You must provide at least 1 upstream scheduler to an Idle scheduler" 422 self.upstream = upstream 423 for s in self.upstream: 424 assert interfaces.IUpstreamScheduler.providedBy(s) 425 s.subscribeToBuilds(self.stopTimer, start=True, success=False) 426 s.subscribeToBuilds(self.restartTimer, failure=True) 427 # we can't add ourselves to self.upstream because it will cause 428 # BuildMaster.loadConfig_Schedulers to recurse infinitely 429 self.subscribeToBuilds(self.stopTimer, start=True, success=False) 430 self.subscribeToBuilds(self.restartTimer, failure=True) 431 432 self.timer = internet.TimerService(self.idleBuildTimer, 433 self.doPeriodicBuild) 434 self.timer.setServiceParent(self) 435 436 def listBuilderNames(self): 437 return self.builderNames 438 439 def getPendingBuildTimes(self): 440 return [] 441 442 def doPeriodicBuild(self): 443 bs = buildset.BuildSet(self.builderNames, 444 SourceStamp(branch=self.branch), 445 self.reason, 446 properties=self.properties) 447 self.submitBuildSet(bs) 448 449 def stopTimer(self, ss): 450 self.runningBuilds += 1 451 if self.timer._loop.running: 452 self.timer._loop.stop() 453 454 def restartTimer(self, ss): 455 self.runningBuilds -= 1 456 if self.runningBuilds == 0: 457 self.timer._loop.start(self.idleBuildTimer, now=False) 401 458 402 459 403 460 404 461 class Nightly(BaseUpstreamScheduler): 405 462 """Imitate 'cron' scheduling. This can be used to schedule a nightly 406 463 build, or one which runs are certain times of the day, week, or month. 407 464 408 465 Pass some subset of minute, hour, dayOfMonth, month, and dayOfWeek; each -
a/buildbot/test/test_run.py
old new 62 62 63 63 from buildbot.scheduler import Scheduler 64 64 c['schedulers'] = [Scheduler('dummy', None, 0.1, ['dummy', 'dummy2'])] 65 65 66 66 c['builders'].append({'name': 'dummy', 'slavename': 'bot1', 67 67 'builddir': 'dummy', 'factory': f2}) 68 68 c['builders'].append({'name': 'dummy2', 'slavename': 'bot1', 69 69 'builddir': 'dummy2', 'factory': f2}) 70 """ 71 72 config_idle = config_base + """ 73 c['slaves'].append(BuildSlave('bot2', 'sekrit')) 74 75 from buildbot.scheduler import Idle, Scheduler 76 77 f2 = factory.BuildFactory([s(dummy.Dummy, timeout=2)]) 78 79 c['schedulers'] = [] 80 s = Scheduler('dummy2', None, 0, ['dummy']) 81 c['schedulers'].append(s) 82 c['schedulers'].append(Idle('dummy', ['dummy'], [s], 4)) 83 84 c['builders'] = [{'name': 'dummy', 'slavenames': ['bot1', 'bot2'], 85 'builddir': 'dummy', 'factory': f2}] 70 86 """ 71 87 72 88 config_2 = config_base + """ 73 89 c['builders'] = [{'name': 'dummy', 'slavename': 'bot1', 74 90 'builddir': 'dummy1', 'factory': f2}, 75 91 {'name': 'testdummy', 'slavename': 'bot1', 76 92 'builddir': 'dummy2', 'factory': f2, 'category': 'test'}] 77 93 """ … … 209 225 if builder.slaves[0].state == BUILDING ] 210 226 # assert that only one build is running right now. If the 211 227 # max_builds= weren't in effect, this would be 2. 212 228 self.failUnlessEqual(len(building_bs), 1) 213 229 d.addCallback(_check) 214 230 215 231 return d 216 232 233 234 class Idle(RunMixin, unittest.TestCase): 235 def setUp(self): 236 RunMixin.setUp(self) 237 238 self.master.loadConfig(config_idle) 239 self.master.readConfig = True 240 self.master.startService() 241 242 return self.connectSlave() 243 244 def isBuilding(self): 245 b = self.master.botmaster.builders['dummy'] 246 return len(b.building) 247 248 def forceBuild(self): 249 c = changes.Change("foo", ["blah"], "stuff") 250 self.master.change_svc.addChange(c) 251 252 def testIdleTimerReset(self): 253 # idle timer is set to 4, if we wait that long we should have a build 254 # going 255 self.failUnlessEqual(self.isBuilding(), 1) 256 d = defer.Deferred() 257 reactor.callLater(2.1, d.callback, None) 258 d.addCallback(self._testIdleTimerReset_1) 259 return d 260 261 def _testIdleTimerReset_1(self, res): 262 self.failUnlessEqual(self.isBuilding(), 0) 263 # now wait until after it is done and force a build 264 d = defer.Deferred() 265 reactor.callLater(2, d.callback, None) 266 d.addCallback(self._testIdleTimerReset_2) 267 return d 268 269 def _testIdleTimerReset_2(self, res): 270 self.forceBuild() 271 d = defer.Deferred() 272 # need extra time here because changes are delayed slightly 273 reactor.callLater(4, d.callback, None) 274 d.addCallback(self._testIdleTimerReset_3) 275 return d 276 277 def _testIdleTimerReset_3(self, res): 278 self.failUnlessEqual(self.isBuilding(), 0) 279 d = defer.Deferred() 280 reactor.callLater(4, d.callback, None) 281 d.addCallback(self._testIdleTimerReset_4) 282 return d 283 284 def _testIdleTimerReset_4(self, res): 285 self.failUnlessEqual(self.isBuilding(), 1) 286 287 def testIdleTimerManyBuilds(self): 288 d = self.connectSlave(slavename='bot2') 289 d.addCallback(self._testIdleTimerManyBuilds_1) 290 return d 291 292 def _testIdleTimerManyBuilds_1(self, res): 293 self.forceBuild() 294 self.forceBuild() 295 d = defer.Deferred() 296 reactor.callLater(1, d.callback, None) 297 d.addCallback(self._testIdleTimerManyBuilds_2) 298 return d 299 300 def _testIdleTimerManyBuilds_2(self, res): 301 b = self.master.botmaster.builders['dummy'] 302 self.failUnlessEqual(self.isBuilding(), 2) 303 d = defer.Deferred() 304 reactor.callLater(4, d.callback, None) 305 d.addCallback(self._testIdleTimerManyBuilds_3) 306 return d 307 308 def _testIdleTimerManyBuilds_3(self, res): 309 self.failUnlessEqual(self.isBuilding(), 0) 217 310 218 311 class Ping(RunMixin, unittest.TestCase): 219 312 def testPing(self): 220 313 self.master.loadConfig(config_2) 221 314 self.master.readConfig = True 222 315 self.master.startService() 223 316 224 317 d = self.connectSlave() -
a/docs/buildbot.texinfo
old new 140 140 * Debug options:: 141 141 142 142 Change Sources and Schedulers 143 143 144 144 * Scheduler Scheduler:: 145 145 * AnyBranchScheduler:: 146 146 * Dependent Scheduler:: 147 147 * Periodic Scheduler:: 148 * Idle Scheduler:: 148 149 * Nightly Scheduler:: 149 150 * Try Schedulers:: 150 151 * Triggerable Scheduler:: 151 152 152 153 Buildslave Specifiers 153 154 154 155 * When Buildslaves Go Missing:: 155 156 … … 2229 2230 docstrings there are the best source of documentation on the arguments 2230 2231 taken by each one. 2231 2232 2232 2233 @menu 2233 2234 * Scheduler Scheduler:: 2234 2235 * AnyBranchScheduler:: 2235 2236 * Dependent Scheduler:: 2236 2237 * Periodic Scheduler:: 2238 * Idle Scheduler:: 2237 2239 * Nightly Scheduler:: 2238 2240 * Try Schedulers:: 2239 2241 * Triggerable Scheduler:: 2240 2242 @end menu 2241 2243 2242 2244 @node Scheduler Scheduler 2243 2245 @subsection Scheduler Scheduler 2244 2246 @slindex buildbot.scheduler.Scheduler … … 2432 2434 c['schedulers'] = [nightly] 2433 2435 @end example 2434 2436 2435 2437 The Scheduler in this example just runs the full solaris build once 2436 2438 per day. Note that this Scheduler only lets you control the time 2437 2439 between builds, not the absolute time-of-day of each Build, so this 2438 2440 could easily wind up a ``daily'' or ``every afternoon'' scheduler 2439 2441 depending upon when it was first activated. 2442 2443 @node Idle Scheduler 2444 @subsection Idle Scheduler 2445 @slindex buildbot.scheduler.Idle 2446 2447 This scheduler triggers builds after N seconds of idle time. Idle time 2448 is determined by subscribing to builds from upstream schedulers, and 2449 builds triggered by this scheduler. 2450 2451 @table @code 2452 @item name 2453 2454 @item builderNames 2455 2456 @item upstream 2457 A list of upstream scheduler instances to watch. Whenever a build triggered 2458 by any of these schedulers is running, the idle timer is stopped. When 2459 all running builds from these schedulers are completed the timer is 2460 restarted. 2461 2462 @item idleBuildTimer 2463 The amount of idle time, in seconds, required before a build is triggered. 2464 @end table 2465 2466 @example 2467 from buildbot import scheduler 2468 s = scheduler.Scheduler(name="onchange", 2469 builderNames=["linux", "osx"], 2470 branch="feature-branch", 2471 treeStableTimer=60*5) 2472 idle = scheduler.Idle(name="idle", 2473 builderNames=["linux", "osx"], 2474 branch="feature-branch", 2475 idleBuildTimer=60*60*2, # 2 hours 2476 upstream=[s]) 2477 c['schedulers'] = [s, idle] 2478 @end example 2479 2480 In this scenario builds will be triggered when the tree changes, as well as 2481 every 2 hours of inactivity. 2440 2482 2441 2483 @node Nightly Scheduler 2442 2484 @subsection Nightly Scheduler 2443 2485 @slindex buildbot.scheduler.Nightly 2444 2486 2445 2487 This is highly configurable periodic build scheduler, which triggers 2446 2488 a build at particular times of day, week, month, or year. The 2447 2489 configuration syntax is very similar to the well-known @code{crontab}
![[Buildbot Logo]](/trac/chrome/site/header-text-transparent.png)