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

Side by Side Diff: recipe_engine/run.py

Issue 1421843006: Add simple depends_on API. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/recipes-py@master
Patch Set: Made it do properties and multi Created 5 years, 1 month 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
OLDNEW
1 # Copyright (c) 2013-2015 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2013-2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 65
66 import collections 66 import collections
67 import contextlib 67 import contextlib
68 import copy 68 import copy
69 import functools 69 import functools
70 import json 70 import json
71 import os 71 import os
72 import re 72 import re
73 import subprocess 73 import subprocess
74 import sys 74 import sys
75 import tempfile
75 import threading 76 import threading
76 import traceback 77 import traceback
77 78
78 import cStringIO 79 import cStringIO
79 80
80 81
81 from . import loader 82 from . import loader
82 from . import recipe_api 83 from . import recipe_api
83 from . import recipe_test_api 84 from . import recipe_test_api
85 from . import types
84 from . import util 86 from . import util
85 87
86 88
87 SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) 89 SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
88 90
89 BUILDBOT_MAGIC_ENV = set([ 91 BUILDBOT_MAGIC_ENV = set([
90 'BUILDBOT_BLAMELIST', 92 'BUILDBOT_BLAMELIST',
91 'BUILDBOT_BRANCH', 93 'BUILDBOT_BRANCH',
92 'BUILDBOT_BUILDBOTURL', 94 'BUILDBOT_BUILDBOTURL',
93 'BUILDBOT_BUILDERNAME', 95 'BUILDBOT_BUILDERNAME',
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 properties.pop('root', None) 428 properties.pop('root', None)
427 429
428 # TODO(iannucci): A much better way to do this would be to dynamically 430 # TODO(iannucci): A much better way to do this would be to dynamically
429 # detect if the mirrors are actually available during the execution of the 431 # detect if the mirrors are actually available during the execution of the
430 # recipe. 432 # recipe.
431 if ('use_mirror' not in properties and ( 433 if ('use_mirror' not in properties and (
432 'TESTING_MASTERNAME' in os.environ or 434 'TESTING_MASTERNAME' in os.environ or
433 'TESTING_SLAVENAME' in os.environ)): 435 'TESTING_SLAVENAME' in os.environ)):
434 properties['use_mirror'] = False 436 properties['use_mirror'] = False
435 437
436 engine = RecipeEngine(stream, properties, test_data) 438 engine = RecipeEngine(stream, properties, test_data, universe)
437 439
438 # Create all API modules and top level RunSteps function. It doesn't launch 440 # Create all API modules and top level RunSteps function. It doesn't launch
439 # any recipe code yet; RunSteps needs to be called. 441 # any recipe code yet; RunSteps needs to be called.
440 api = None 442 api = None
441 with stream.step('setup_build') as s: 443 with stream.step('setup_build') as s:
442 assert 'recipe' in properties 444 assert 'recipe' in properties
443 recipe = properties['recipe'] 445 recipe = properties['recipe']
444 446
445 properties_to_print = properties.copy() 447 properties_to_print = properties.copy()
446 if 'use_mirror' in properties: 448 if 'use_mirror' in properties:
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 Knows how to execute steps emitted by a recipe, holds global state such as 745 Knows how to execute steps emitted by a recipe, holds global state such as
744 step history and build properties. Each recipe module API has a reference to 746 step history and build properties. Each recipe module API has a reference to
745 this object. 747 this object.
746 748
747 Recipe modules that are aware of the engine: 749 Recipe modules that are aware of the engine:
748 * properties - uses engine.properties. 750 * properties - uses engine.properties.
749 * step_history - uses engine.step_history. 751 * step_history - uses engine.step_history.
750 * step - uses engine.create_step(...). 752 * step - uses engine.create_step(...).
751 753
752 """ 754 """
753 def __init__(self, stream, properties, test_data): 755 def __init__(self, stream, properties, test_data, universe):
754 self._stream = stream 756 self._stream = stream
755 self._properties = properties 757 self._properties = properties
756 self._test_data = test_data 758 self._test_data = test_data
757 self._step_history = collections.OrderedDict() 759 self._step_history = collections.OrderedDict()
760 self._universe = universe
758 761
759 self._previous_step_annotation = None 762 self._previous_step_annotation = None
760 self._previous_step_result = None 763 self._previous_step_result = None
761 self._api = None 764 self._api = None
762 765
766 def clone(self, stream=None, properties=None, universe=None):
767 return RecipeEngine(stream or self._stream, properties or self._properties,
768 self._test_data, universe or self._universe)
luqui 2015/11/16 20:48:00 Hmm, isn't test_data mutable, in order for example
martiniss 2015/11/18 01:00:00 Deleted this method. Not needed anymore.
769
763 @property 770 @property
764 def properties(self): 771 def properties(self):
765 return self._properties 772 return self._properties
766 773
767 @property 774 @property
768 def previous_step_result(self): 775 def previous_step_result(self):
769 """Allows api.step to get the active result from any context.""" 776 """Allows api.step to get the active result from any context."""
770 return self._previous_step_result 777 return self._previous_step_result
771 778
772 def _emit_results(self): 779 def _emit_results(self):
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 exc = recipe_api.InfraFailure 861 exc = recipe_api.InfraFailure
855 862
856 step_result.presentation.status = state 863 step_result.presentation.status = state
857 if step_test.enabled: 864 if step_test.enabled:
858 # To avoid cluttering the expectations, don't emit this in testmode. 865 # To avoid cluttering the expectations, don't emit this in testmode.
859 self._previous_step_annotation.emit( 866 self._previous_step_annotation.emit(
860 'step returned non-zero exit code: %d' % step_result.retcode) 867 'step returned non-zero exit code: %d' % step_result.retcode)
861 868
862 raise exc(step['name'], step_result) 869 raise exc(step['name'], step_result)
863 870
864
865 def run(self, recipe_script, api): 871 def run(self, recipe_script, api):
866 """Run a recipe represented by a recipe_script object. 872 """Run a recipe represented by a recipe_script object.
867 873
868 This function blocks until recipe finishes. 874 This function blocks until recipe finishes.
875 It mainly executes the recipe, and has some exception handling logic, and
876 adds the step history to the result.
869 877
870 Args: 878 Args:
871 recipe_script: The recipe to run, as represented by a RecipeScript object. 879 recipe_script: The recipe to run, as represented by a RecipeScript object.
872 api: The api, with loaded module dependencies. 880 api: The api, with loaded module dependencies.
873 Used by the some special modules. 881 Used by the some special modules.
874 882
875 Returns: 883 Returns:
876 RecipeExecutionResult which has status code, list of steps ran, 884 RecipeExecutionResult which has status code, list of steps ran,
877 and return value. 885 and return value.
878 """ 886 """
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 941
934 Args: 942 Args:
935 step: ConfigGroup object with information about the step, see 943 step: ConfigGroup object with information about the step, see
936 recipe_modules/step/config.py. 944 recipe_modules/step/config.py.
937 945
938 Returns: 946 Returns:
939 Opaque engine specific object that is understood by 'run_steps' method. 947 Opaque engine specific object that is understood by 'run_steps' method.
940 """ 948 """
941 return step.as_jsonish() 949 return step.as_jsonish()
942 950
951 def depend_on(self, recipe, properties, distributor=None):
952 return self.depend_on_multi(
953 ((recipe, properties),), distributor=distributor)
943 954
955 def depend_on_multi(self, dependencies, distributor=None):
956 if self._test_data.enabled:
957 # TODO(martiniss) test properties against the recipe
958 for recipe, properties in dependencies:
959 recipe_script = self._universe.load_recipe(recipe)
luqui 2015/11/16 20:48:00 This precludes one use case, which is that the rec
960 loader._invoke_with_properties(
961 lambda *args, **kwargs: None, properties, recipe_script.PROPERTIES,
962 properties.keys())
963
964 return self._test_data.depend_on_data[types.freeze((recipe, properties), )]
luqui 2015/11/16 20:48:00 line wrap
965
966 # TODO(martiniss) Add DM integration
967 for recipe, properties in dependencies:
968 recipes_py_loc = os.path.join(
969 self._universe.package_deps._context.repo_root, 'recipes.py')
970
971 with tempfile.NamedTemporaryFile() as f:
972 cmd = [sys.executable, recipes_py_loc,
973 '--package=%s' % self._universe._config_file, 'run',
974 '--result-file=%s' % f.name, recipe]
luqui 2015/11/16 20:48:00 The convention for this argument has been --output
martiniss 2015/11/18 01:00:00 Fixed.
975 cmd.extend(['%s=%s' % (k, v) for k, v in properties.iteritems()])
976
977 rval = subprocess.call(cmd)
estaab 2015/11/17 23:07:16 We should probably throw an exception when rval is
martiniss 2015/11/18 01:00:00 Good idea. Raising an InfraFailure.
978 return json.load(f)
979
980
981
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698