Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: recipe_engine/step_runner.py

Issue 2340483002: Revert of Add better documentation, trigger namedtuple. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « recipe_engine/run.py ('k') | recipe_engine/stream.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2016 The LUCI Authors. All rights reserved. 1 # Copyright 2016 The LUCI Authors. All rights reserved.
2 # Use of this source code is governed under the Apache License, Version 2.0 2 # Use of this source code is governed under the Apache License, Version 2.0
3 # that can be found in the LICENSE file. 3 # that can be found in the LICENSE file.
4 4
5 import StringIO 5 import StringIO
6 import collections 6 import collections
7 import contextlib 7 import contextlib
8 import datetime 8 import datetime
9 import json 9 import json
10 import os 10 import os
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 for line in buf.get_buffered(): 347 for line in buf.get_buffered():
348 outstreams[pipe].write_line(line) 348 outstreams[pipe].write_line(line)
349 else: 349 else:
350 proc.wait(timeout) 350 proc.wait(timeout)
351 351
352 return proc.returncode 352 return proc.returncode
353 353
354 def _trigger_builds(self, step, trigger_specs): 354 def _trigger_builds(self, step, trigger_specs):
355 assert trigger_specs is not None 355 assert trigger_specs is not None
356 for trig in trigger_specs: 356 for trig in trigger_specs:
357 builder_name = trig.builder_name 357 builder_name = trig.get('builder_name')
358 if not builder_name: 358 if not builder_name:
359 raise ValueError('Trigger spec: builder_name is not set') 359 raise ValueError('Trigger spec: builder_name is not set')
360 360
361 changes = trig.buildbot_changes or [] 361 changes = trig.get('buildbot_changes', [])
362 assert isinstance(changes, list), 'buildbot_changes must be a list' 362 assert isinstance(changes, list), 'buildbot_changes must be a list'
363 changes = map(self._normalize_change, changes) 363 changes = map(self._normalize_change, changes)
364 364
365 step.trigger(json.dumps({ 365 step.trigger(json.dumps({
366 'builderNames': [builder_name], 366 'builderNames': [builder_name],
367 'bucket': trig.bucket, 367 'bucket': trig.get('bucket'),
368 'changes': changes, 368 'changes': changes,
369 # if True and triggering fails asynchronously, fail entire build. 369 # if True and triggering fails asynchronously, fail entire build.
370 'critical': trig.critical, 370 'critical': trig.get('critical', True),
371 'properties': trig.properties, 371 'properties': trig.get('properties'),
372 'tags': trig.tags, 372 'tags': trig.get('tags'),
373 }, sort_keys=True)) 373 }, sort_keys=True))
374 374
375 def _normalize_change(self, change): 375 def _normalize_change(self, change):
376 assert isinstance(change, dict), 'Change is not a dict' 376 assert isinstance(change, dict), 'Change is not a dict'
377 change = change.copy() 377 change = change.copy()
378 378
379 # Convert when_timestamp to UNIX timestamp. 379 # Convert when_timestamp to UNIX timestamp.
380 when = change.get('when_timestamp') 380 when = change.get('when_timestamp')
381 if isinstance(when, datetime.datetime): 381 if isinstance(when, datetime.datetime):
382 when = calendar.timegm(when.utctimetuple()) 382 when = calendar.timegm(when.utctimetuple())
383 change['when_timestamp'] = when 383 change['when_timestamp'] = when
384 384
385 return change 385 return change
386 386
387 387
388 class SimulationStepRunner(StepRunner): 388 class SimulationStepRunner(StepRunner):
389 """Pretends to run steps, instead recording what would have been run. 389 """Pretends to run steps, instead recording what would have been run.
390 390
391 This is the main workhorse of recipes.py simulation_test. Returns the log of 391 This is the main workhorse of recipes.py simulation_test. Returns the log of
392 steps that would have been run in steps_ran. Uses test_data to mock return 392 steps that would have been run in steps_ran. Uses test_data to mock return
393 values. 393 values.
394 """ 394 """
395 395
396 # List of attributes in a recipe_api.StepConfig to omit when rendering
397 # step history.
398 _STEP_CONFIG_RENDER_BLACKLIST = set((
399 'nest_level',
400 'ok_ret',
401 'infra_step',
402 'step_test_data',
403 ))
404
396 def __init__(self, stream_engine, test_data, annotator): 405 def __init__(self, stream_engine, test_data, annotator):
397 self._test_data = test_data 406 self._test_data = test_data
398 self._stream_engine = stream_engine 407 self._stream_engine = stream_engine
399 self._annotator = annotator 408 self._annotator = annotator
400 self._step_history = collections.OrderedDict() 409 self._step_history = collections.OrderedDict()
401 410
402 @property 411 @property
403 def stream_engine(self): 412 def stream_engine(self):
404 return self._stream_engine 413 return self._stream_engine
405 414
(...skipping 17 matching lines...) Expand all
423 # Install a placeholder for order. 432 # Install a placeholder for order.
424 self._step_history[rendered_step.config.name] = None 433 self._step_history[rendered_step.config.name] = None
425 return construct_step_result(rendered_step, step_test.retcode) 434 return construct_step_result(rendered_step, step_test.retcode)
426 435
427 def finalize(inner): 436 def finalize(inner):
428 rs = rendered_step 437 rs = rendered_step
429 438
430 # note that '~' sorts after 'z' so that this will be last on each 439 # note that '~' sorts after 'z' so that this will be last on each
431 # step. also use _step to get access to the mutable step 440 # step. also use _step to get access to the mutable step
432 # dictionary. 441 # dictionary.
433 buf = self._annotator.step_buffer(rs.config.name) 442 buf = self._annotator.step_buffer(rendered_step.config.name)
434 lines = filter(None, buf.getvalue()).splitlines() 443 lines = filter(None, buf.getvalue()).splitlines()
435 lines = [stream.encode_str(x) for x in lines] 444 lines = [stream.encode_str(x) for x in lines]
436 if lines: 445 if lines:
437 # This magically floats into step_history, which we have already 446 # This magically floats into step_history, which we have already
438 # added step_config to. 447 # added step_config to.
439 rs = rs._replace(followup_annotations=lines) 448 rs = rs._replace(followup_annotations=lines)
440 step_stream.close() 449 step_stream.close()
441 self._step_history[rs.config.name] = rs 450 self._step_history[rendered_step.config.name] = rs
442 451
443 @property 452 @property
444 def stream(inner): 453 def stream(inner):
445 return step_stream 454 return step_stream
446 455
447 return ReturnOpenStep() 456 return ReturnOpenStep()
448 457
449 def run_recipe(self, universe, recipe, properties): 458 def run_recipe(self, universe, recipe, properties):
450 return self._test_data.depend_on_data.pop(types.freeze((recipe, properties), )) 459 return self._test_data.depend_on_data.pop(types.freeze((recipe, properties), ))
451 460
452 @contextlib.contextmanager 461 @contextlib.contextmanager
453 def run_context(self): 462 def run_context(self):
454 try: 463 try:
455 yield 464 yield
456 except Exception as ex: 465 except Exception as ex:
457 with self._test_data.should_raise_exception(ex) as should_raise: 466 with self._test_data.should_raise_exception(ex) as should_raise:
458 if should_raise: 467 if should_raise:
459 raise 468 raise
460 469
461 assert self._test_data.consumed, ( 470 assert self._test_data.consumed, (
462 "Unconsumed test data for steps: %s, (exception %s)" % ( 471 "Unconsumed test data for steps: %s, (exception %s)" % (
463 self._test_data.step_data.keys(), 472 self._test_data.step_data.keys(),
464 self._test_data.expected_exception)) 473 self._test_data.expected_exception))
465 474
466 def _rendered_step_to_dict(self, rs): 475 def _rendered_step_to_dict(self, rs):
467 d = rs.config.render_to_dict() 476 d = dict((k, v) for k, v in rs.config._asdict().iteritems()
477 if v and k not in self._STEP_CONFIG_RENDER_BLACKLIST)
468 if rs.followup_annotations: 478 if rs.followup_annotations:
469 d['~followup_annotations'] = rs.followup_annotations 479 d['~followup_annotations'] = rs.followup_annotations
470 return d 480 return d
471 481
472 @property 482 @property
473 def steps_ran(self): 483 def steps_ran(self):
474 return [self._rendered_step_to_dict(rs) 484 return [self._rendered_step_to_dict(rs)
475 for rs in self._step_history.itervalues()] 485 for rs in self._step_history.itervalues()]
476 486
477 487
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 supplied command, and only uses the |env| kwarg for modifying the environment 680 supplied command, and only uses the |env| kwarg for modifying the environment
671 of the child process. 681 of the child process.
672 """ 682 """
673 saved_path = os.environ['PATH'] 683 saved_path = os.environ['PATH']
674 try: 684 try:
675 if path is not None: 685 if path is not None:
676 os.environ['PATH'] = path 686 os.environ['PATH'] = path
677 yield 687 yield
678 finally: 688 finally:
679 os.environ['PATH'] = saved_path 689 os.environ['PATH'] = saved_path
OLDNEW
« no previous file with comments | « recipe_engine/run.py ('k') | recipe_engine/stream.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698