| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Entry point for fully-annotated builds. | 6 """Entry point for fully-annotated builds. |
| 7 | 7 |
| 8 This script is part of the effort to move all builds to annotator-based | 8 This script is part of the effort to move all builds to annotator-based |
| 9 systems. Any builder configured to use the AnnotatorFactory.BaseFactory() | 9 systems. Any builder configured to use the AnnotatorFactory.BaseFactory() |
| 10 found in scripts/master/factory/annotator_factory.py executes a single | 10 found in scripts/master/factory/annotator_factory.py executes a single |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 | 309 |
| 310 ret = run_steps(stream, opts.build_properties, opts.factory_properties) | 310 ret = run_steps(stream, opts.build_properties, opts.factory_properties) |
| 311 return ret.status_code | 311 return ret.status_code |
| 312 | 312 |
| 313 | 313 |
| 314 # Return value of run_steps and RecipeEngine.run. | 314 # Return value of run_steps and RecipeEngine.run. |
| 315 RecipeExecutionResult = collections.namedtuple( | 315 RecipeExecutionResult = collections.namedtuple( |
| 316 'RecipeExecutionResult', 'status_code steps_ran') | 316 'RecipeExecutionResult', 'status_code steps_ran') |
| 317 | 317 |
| 318 | 318 |
| 319 def get_recipe_properties(factory_properties, build_properties): |
| 320 """Constructs the recipe's properties from buildbot's properties. |
| 321 |
| 322 This merges factory_properties and build_properties. Furthermore, it |
| 323 tries to reconstruct the 'recipe' property from builders.pyl if it isn't |
| 324 already there, and in that case merges in properties form builders.pyl. |
| 325 """ |
| 326 properties = factory_properties.copy() |
| 327 properties.update(build_properties) |
| 328 |
| 329 # Try to reconstruct the recipe from builders.pyl if not given. |
| 330 if 'recipe' not in properties: |
| 331 mastername = properties['mastername'] |
| 332 buildername = properties['buildername'] |
| 333 |
| 334 master_path = chromium_utils.MasterPath(mastername) |
| 335 builders_file = os.path.join(master_path, 'builders.pyl') |
| 336 if os.path.isfile(builders_file): |
| 337 builders = chromium_utils.ReadBuildersFile(builders_file) |
| 338 assert buildername in builders['builders'], ( |
| 339 'buildername %s is not listed in %s' % (buildername, builders_file)) |
| 340 builder = builders['builders'][buildername] |
| 341 |
| 342 # Update properties with builders.pyl data. |
| 343 properties['recipe'] = builder['recipe'] |
| 344 properties.update(builder['properties']) |
| 345 else: |
| 346 raise LookupError('Cannot find recipe for %s on %s' % |
| 347 (build_properties['buildername'], |
| 348 build_properties['mastername'])) |
| 349 return properties |
| 350 |
| 351 |
| 319 def run_steps(stream, build_properties, factory_properties, | 352 def run_steps(stream, build_properties, factory_properties, |
| 320 test_data=recipe_test_api.DisabledTestData()): | 353 test_data=recipe_test_api.DisabledTestData()): |
| 321 """Returns a tuple of (status_code, steps_ran). | 354 """Returns a tuple of (status_code, steps_ran). |
| 322 | 355 |
| 323 Only one of these values will be set at a time. This is mainly to support the | 356 Only one of these values will be set at a time. This is mainly to support the |
| 324 testing interface used by unittests/recipes_test.py. | 357 testing interface used by unittests/recipes_test.py. |
| 325 """ | 358 """ |
| 326 stream.honor_zero_return_code() | 359 stream.honor_zero_return_code() |
| 327 | 360 |
| 328 # TODO(iannucci): Stop this when blamelist becomes sane data. | 361 # TODO(iannucci): Stop this when blamelist becomes sane data. |
| 329 if ('blamelist_real' in build_properties and | 362 if ('blamelist_real' in build_properties and |
| 330 'blamelist' in build_properties): | 363 'blamelist' in build_properties): |
| 331 build_properties['blamelist'] = build_properties['blamelist_real'] | 364 build_properties['blamelist'] = build_properties['blamelist_real'] |
| 332 del build_properties['blamelist_real'] | 365 del build_properties['blamelist_real'] |
| 333 | 366 |
| 334 # NOTE(iannucci): 'root' was a terribly bad idea and has been replaced by | 367 # NOTE(iannucci): 'root' was a terribly bad idea and has been replaced by |
| 335 # 'patch_project'. 'root' had Rietveld knowing about the implementation of | 368 # 'patch_project'. 'root' had Rietveld knowing about the implementation of |
| 336 # the builders. 'patch_project' lets the builder (recipe) decide its own | 369 # the builders. 'patch_project' lets the builder (recipe) decide its own |
| 337 # destiny. | 370 # destiny. |
| 338 build_properties.pop('root', None) | 371 build_properties.pop('root', None) |
| 339 | 372 |
| 340 properties = factory_properties.copy() | 373 properties = get_recipe_properties( |
| 341 properties.update(build_properties) | 374 factory_properties=factory_properties, |
| 375 build_properties=build_properties) |
| 342 | 376 |
| 343 # TODO(iannucci): A much better way to do this would be to dynamically | 377 # TODO(iannucci): A much better way to do this would be to dynamically |
| 344 # detect if the mirrors are actually available during the execution of the | 378 # detect if the mirrors are actually available during the execution of the |
| 345 # recipe. | 379 # recipe. |
| 346 if ('use_mirror' not in properties and ( | 380 if ('use_mirror' not in properties and ( |
| 347 'TESTING_MASTERNAME' in os.environ or | 381 'TESTING_MASTERNAME' in os.environ or |
| 348 'TESTING_SLAVENAME' in os.environ)): | 382 'TESTING_SLAVENAME' in os.environ)): |
| 349 properties['use_mirror'] = False | 383 properties['use_mirror'] = False |
| 350 | 384 |
| 351 # It's an integration point with a new recipe engine that can run steps | 385 # It's an integration point with a new recipe engine that can run steps |
| 352 # in parallel (that is not implemented yet). Use new engine only if explicitly | 386 # in parallel (that is not implemented yet). Use new engine only if explicitly |
| 353 # asked by setting 'engine' property to 'ParallelRecipeEngine'. | 387 # asked by setting 'engine' property to 'ParallelRecipeEngine'. |
| 354 engine = RecipeEngine.create(stream, properties, test_data) | 388 engine = RecipeEngine.create(stream, properties, test_data) |
| 355 | 389 |
| 356 # Create all API modules and an instance of top level GenSteps generator. | 390 # Create all API modules and an instance of top level GenSteps generator. |
| 357 # It doesn't launch any recipe code yet (generator needs to be iterated upon | 391 # It doesn't launch any recipe code yet (generator needs to be iterated upon |
| 358 # to start executing code). | 392 # to start executing code). |
| 359 api = None | 393 api = None |
| 360 with stream.step('setup_build') as s: | 394 with stream.step('setup_build') as s: |
| 361 assert 'recipe' in factory_properties | 395 assert 'recipe' in properties # Should be ensured by get_recipe_properties. |
| 362 recipe = factory_properties['recipe'] | 396 recipe = properties['recipe'] |
| 363 | 397 |
| 364 properties_to_print = properties.copy() | 398 properties_to_print = properties.copy() |
| 365 if 'use_mirror' in properties: | 399 if 'use_mirror' in properties: |
| 366 del properties_to_print['use_mirror'] | 400 del properties_to_print['use_mirror'] |
| 367 | 401 |
| 368 run_recipe_help_lines = [ | 402 run_recipe_help_lines = [ |
| 369 'To repro this locally, run the following line from a build checkout:', | 403 'To repro this locally, run the following line from a build checkout:', |
| 370 '', | 404 '', |
| 371 './scripts/tools/run_recipe.py %s --properties-file - <<EOF' % recipe, | 405 './scripts/tools/run_recipe.py %s --properties-file - <<EOF' % recipe, |
| 372 repr(properties_to_print), | 406 repr(properties_to_print), |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 | 697 |
| 664 def shell_main(argv): | 698 def shell_main(argv): |
| 665 if update_scripts(): | 699 if update_scripts(): |
| 666 return subprocess.call([sys.executable] + argv) | 700 return subprocess.call([sys.executable] + argv) |
| 667 else: | 701 else: |
| 668 return main(argv) | 702 return main(argv) |
| 669 | 703 |
| 670 | 704 |
| 671 if __name__ == '__main__': | 705 if __name__ == '__main__': |
| 672 sys.exit(shell_main(sys.argv)) | 706 sys.exit(shell_main(sys.argv)) |
| OLD | NEW |