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

Side by Side Diff: recipe_engine/run.py

Issue 2245113002: Track step nesting in StreamEngine. (Closed) Base URL: https://github.com/luci/recipes-py@emit-initial-properties
Patch Set: Rebase, comments. 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 | « no previous file | recipe_engine/simulation_test.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 """Entry point for fully-annotated builds. 5 """Entry point for fully-annotated builds.
6 6
7 This script is part of the effort to move all builds to annotator-based 7 This script is part of the effort to move all builds to annotator-based
8 systems. Any builder configured to use the AnnotatorFactory.BaseFactory() 8 systems. Any builder configured to use the AnnotatorFactory.BaseFactory()
9 found in scripts/master/factory/annotator_factory.py executes a single 9 found in scripts/master/factory/annotator_factory.py executes a single
10 AddAnnotatedScript step. That step (found in annotator_commands.py) calls 10 AddAnnotatedScript step. That step (found in annotator_commands.py) calls
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 """ 290 """
291 Knows how to execute steps emitted by a recipe, holds global state such as 291 Knows how to execute steps emitted by a recipe, holds global state such as
292 step history and build properties. Each recipe module API has a reference to 292 step history and build properties. Each recipe module API has a reference to
293 this object. 293 this object.
294 294
295 Recipe modules that are aware of the engine: 295 Recipe modules that are aware of the engine:
296 * properties - uses engine.properties. 296 * properties - uses engine.properties.
297 * step - uses engine.create_step(...), and previous_step_result. 297 * step - uses engine.create_step(...), and previous_step_result.
298 """ 298 """
299 299
300 ActiveStep = collections.namedtuple('ActiveStep', 300 ActiveStep = collections.namedtuple('ActiveStep', (
301 'step step_result open_step nest_level') 301 'step', 'step_result', 'open_step', 'nest_level'))
302 302
303 def __init__(self, step_runner, properties, universe_view): 303 def __init__(self, step_runner, properties, universe_view):
304 """See run_steps() for parameter meanings.""" 304 """See run_steps() for parameter meanings."""
305 self._step_runner = step_runner 305 self._step_runner = step_runner
306 self._properties = properties 306 self._properties = properties
307 self._universe_view = universe_view 307 self._universe_view = universe_view
308 308
309 # A stack of ActiveStep objects, holding the most recently executed step at 309 # A stack of ActiveStep objects, holding the most recently executed step at
310 # each nest level (objects deeper in the stack have lower nest levels). 310 # each nest level (objects deeper in the stack have lower nest levels).
311 # When we pop from this stack, we close the corresponding step stream. 311 # When we pop from this stack, we close the corresponding step stream.
(...skipping 25 matching lines...) Expand all
337 337
338 This always returns the innermost nested step that is still open -- 338 This always returns the innermost nested step that is still open --
339 presumably the one that just failed if we are in an exception handler.""" 339 presumably the one that just failed if we are in an exception handler."""
340 if not self._step_stack: 340 if not self._step_stack:
341 raise ValueError( 341 raise ValueError(
342 "No steps have been run yet, and you are asking for a previous step" 342 "No steps have been run yet, and you are asking for a previous step"
343 " result. Check to make sure your code isn't doing incorrect logic" 343 " result. Check to make sure your code isn't doing incorrect logic"
344 " with try-finally blocks.") 344 " with try-finally blocks.")
345 return self._step_stack[-1].step_result 345 return self._step_stack[-1].step_result
346 346
347 def _close_to_level(self, level): 347 def _close_through_level(self, level):
348 """Close all open steps that are at least as deep as level.""" 348 """Close all open steps whose nest level is >= the supplied level.
349 while self._step_stack and level <= self._step_stack[-1].nest_level: 349
350 Args:
351 level (int): the nest level to close through.
352 """
353 while self._step_stack and self._step_stack[-1].nest_level >= level:
350 cur = self._step_stack.pop() 354 cur = self._step_stack.pop()
351 if cur.step_result: 355 if cur.step_result:
352 cur.step_result.presentation.finalize(cur.open_step.stream) 356 cur.step_result.presentation.finalize(cur.open_step.stream)
353 cur.open_step.finalize() 357 cur.open_step.finalize()
354 358
355 def run_step(self, step): 359 def run_step(self, step):
356 """ 360 """
357 Runs a step. 361 Runs a step.
358 362
359 Args: 363 Args:
360 step: The step to run. 364 step: The step to run.
361 365
362 Returns: 366 Returns:
363 A StepData object containing the result of running the step. 367 A StepData object containing the result of running the step.
364 """ 368 """
365 with util.raises((recipe_api.StepFailure, OSError), 369 with util.raises((recipe_api.StepFailure, OSError),
366 self._step_runner.stream_engine): 370 self._step_runner.stream_engine):
367 ok_ret = step.pop('ok_ret') 371 ok_ret = step.pop('ok_ret')
368 infra_step = step.pop('infra_step') 372 infra_step = step.pop('infra_step')
369 373
370 step_result = None 374 step_result = None
371 375
372 nest_level = step.pop('step_nest_level', 0) 376 nest_level = step.get('nest_level', 0)
373 self._close_to_level(nest_level) 377 self._close_through_level(nest_level)
374 378
375 open_step = self._step_runner.open_step(step) 379 open_step = self._step_runner.open_step(step)
376 self._step_stack.append(self.ActiveStep( 380 self._step_stack.append(self.ActiveStep(
377 step=step, 381 step=step,
378 step_result=None, 382 step_result=None,
379 open_step=open_step, 383 open_step=open_step,
380 nest_level=nest_level)) 384 nest_level=nest_level))
381 if nest_level:
382 open_step.stream.set_nest_level(nest_level)
383 385
384 step_result = open_step.run() 386 step_result = open_step.run()
385 self._step_stack[-1] = ( 387 self._step_stack[-1] = (
386 self._step_stack[-1]._replace(step_result=step_result)) 388 self._step_stack[-1]._replace(step_result=step_result))
387 389
388 if step_result.retcode in ok_ret: 390 if step_result.retcode in ok_ret:
389 step_result.presentation.status = 'SUCCESS' 391 step_result.presentation.status = 'SUCCESS'
390 return step_result 392 return step_result
391 else: 393 else:
392 if not infra_step: 394 if not infra_step:
(...skipping 29 matching lines...) Expand all
422 424
423 with self._step_runner.run_context(): 425 with self._step_runner.run_context():
424 try: 426 try:
425 try: 427 try:
426 recipe_result = recipe_script.run(api, api._engine.properties) 428 recipe_result = recipe_script.run(api, api._engine.properties)
427 result = { 429 result = {
428 "recipe_result": recipe_result, 430 "recipe_result": recipe_result,
429 "status_code": 0 431 "status_code": 0
430 } 432 }
431 finally: 433 finally:
432 self._close_to_level(0) 434 self._close_through_level(0)
433 except recipe_api.StepFailure as f: 435 except recipe_api.StepFailure as f:
434 result = { 436 result = {
435 # Include "recipe_result" so it doesn't get marked as infra failure. 437 # Include "recipe_result" so it doesn't get marked as infra failure.
436 "recipe_result": None, 438 "recipe_result": None,
437 "reason": f.reason, 439 "reason": f.reason,
438 "status_code": f.retcode or 1 440 "status_code": f.retcode or 1
439 } 441 }
440 except types.StepDataAttributeError as ex: 442 except types.StepDataAttributeError as ex:
441 result = { 443 result = {
442 "reason": "Invalid Step Data Access: %r" % ex, 444 "reason": "Invalid Step Data Access: %r" % ex,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 results.append( 504 results.append(
503 loader._invoke_with_properties( 505 loader._invoke_with_properties(
504 run_recipe, properties, recipe_script.PROPERTIES, 506 run_recipe, properties, recipe_script.PROPERTIES,
505 properties.keys())) 507 properties.keys()))
506 except TypeError as e: 508 except TypeError as e:
507 raise TypeError( 509 raise TypeError(
508 "Got %r while trying to call recipe %s with properties %r" % ( 510 "Got %r while trying to call recipe %s with properties %r" % (
509 e, recipe, properties)) 511 e, recipe, properties))
510 512
511 return results 513 return results
OLDNEW
« no previous file with comments | « no previous file | recipe_engine/simulation_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698