OLD | NEW |
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 Loading... |
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 Loading... |
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('step_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 Loading... |
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 Loading... |
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 |
OLD | NEW |