| <!--- AUTOGENERATED BY `./recipes.py test train` --> |
| # Repo documentation for [recipe\_engine](https://chromium.googlesource.com/infra/luci/recipes-py.git) |
| ## Table of Contents |
| |
| **[Recipe Modules](#Recipe-Modules)** |
| * [archive](#recipe_modules-archive) (Python3 ✅) |
| * [assertions](#recipe_modules-assertions) (Python3 ✅) |
| * [bcid_reporter](#recipe_modules-bcid_reporter) (Python3 ✅) |
| * [buildbucket](#recipe_modules-buildbucket) (Python3 ✅) — API for interacting with the buildbucket service. |
| * [cas](#recipe_modules-cas) (Python3 ✅) — API for interacting with cas client. |
| * [cas_input](#recipe_modules-cas_input) (Python3 ✅) — Simple API for handling CAS inputs to a recipe. |
| * [change_verifier](#recipe_modules-change_verifier) (Python3 ✅) — Recipe API for LUCI Change Verifier. |
| * [cipd](#recipe_modules-cipd) (Python3 ✅) — API for interacting with CIPD. |
| * [commit_position](#recipe_modules-commit_position) (Python3 ✅) |
| * [context](#recipe_modules-context) (Python3 ✅) — The context module provides APIs for manipulating a few pieces of 'ambient' data that affect how steps are run. |
| * [cq](#recipe_modules-cq) (Python3 ✅) — Recipe API for LUCI CQ, the pre-commit testing system. |
| * [file](#recipe_modules-file) (Python3 ✅) — File manipulation (read/write/delete/glob) methods. |
| * [futures](#recipe_modules-futures) (Python3 ✅) — Implements in-recipe concurrency via green threads. |
| * [generator_script](#recipe_modules-generator_script) (Python3 ✅) — A simplistic method for running steps generated by an external script. |
| * [golang](#recipe_modules-golang) (Python3 ✅) |
| * [json](#recipe_modules-json) (Python3 ✅) — Methods for producing and consuming JSON. |
| * [led](#recipe_modules-led) (Python3 ✅) — An interface to call the led tool. |
| * [legacy_annotation](#recipe_modules-legacy_annotation) (Python3 ✅) — Legacy Annotation module provides support for running a command emitting legacy @@@annotation@@@ in the new luciexe mode. |
| * [milo](#recipe_modules-milo) (Python3 ✅) — API for specifying Milo behavior. |
| * [nodejs](#recipe_modules-nodejs) (Python3 ✅) |
| * [path](#recipe_modules-path) (Python3 ✅) — All functions related to manipulating paths in recipes. |
| * [platform](#recipe_modules-platform) (Python3 ✅) — Mockable system platform identity functions. |
| * [properties](#recipe_modules-properties) (Python3 ✅) — Provides access to the recipes input properties. |
| * [proto](#recipe_modules-proto) (Python3 ✅) — Methods for producing and consuming protobuf data to/from steps and the filesystem. |
| * [python](#recipe_modules-python) (Python3 ✅) — Provides methods for running python scripts correctly. |
| * [random](#recipe_modules-random) (Python3 ✅) — Allows randomness in recipes. |
| * [raw_io](#recipe_modules-raw_io) (Python3 ✅) — Provides objects for reading and writing raw data to and from steps. |
| * [resultdb](#recipe_modules-resultdb) (Python3 ✅) — API for interacting with the ResultDB service. |
| * [runtime](#recipe_modules-runtime) (Python3 ✅) |
| * [scheduler](#recipe_modules-scheduler) (Python3 ✅) — API for interacting with the LUCI Scheduler service. |
| * [service_account](#recipe_modules-service_account) (Python3 ✅) — API for getting OAuth2 access tokens for LUCI tasks or private keys. |
| * [step](#recipe_modules-step) (Python3 ✅) — Step is the primary API for running steps (external programs, etc. |
| * [swarming](#recipe_modules-swarming) (Python3 ✅) |
| * [time](#recipe_modules-time) (Python3 ✅) — Allows mockable access to the current time. |
| * [tricium](#recipe_modules-tricium) (Python3 ✅) — API for Tricium analyzers to use. |
| * [url](#recipe_modules-url) (Python3 ✅) — Methods for interacting with HTTP(s) URLs. |
| * [uuid](#recipe_modules-uuid) (Python3 ✅) — Allows test-repeatable access to a random UUID. |
| * [version](#recipe_modules-version) (Python3 ✅) — Thin API for parsing semver strings into comparable object. |
| * [warning](#recipe_modules-warning) (Python3 ✅) — Allows recipe modules to issue warnings in simulation test. |
| |
| **[Recipes](#Recipes)** |
| * [archive:examples/full](#recipes-archive_examples_full) (Python3 ✅) |
| * [assertions:tests/assert-raises](#recipes-assertions_tests_assert-raises) (Python3 ✅) |
| * [assertions:tests/assert_count_equal](#recipes-assertions_tests_assert_count_equal) (Python3 ✅) |
| * [assertions:tests/assertions](#recipes-assertions_tests_assertions) (Python3 ✅) |
| * [assertions:tests/attribute_error](#recipes-assertions_tests_attribute_error) (Python3 ✅) |
| * [assertions:tests/long_message](#recipes-assertions_tests_long_message) (Python3 ✅) |
| * [assertions:tests/max_diff](#recipes-assertions_tests_max_diff) (Python3 ✅) |
| * [bcid_reporter:examples/usage](#recipes-bcid_reporter_examples_usage) (Python3 ✅) |
| * [buildbucket:examples/full](#recipes-buildbucket_examples_full) (Python3 ✅) — This file is a recipe demonstrating the buildbucket recipe module. |
| * [buildbucket:run/multi](#recipes-buildbucket_run_multi) (Python3 ✅) — Launches multiple builds at the same revision. |
| * [buildbucket:tests/add_tags](#recipes-buildbucket_tests_add_tags) (Python3 ✅) |
| * [buildbucket:tests/build](#recipes-buildbucket_tests_build) (Python3 ✅) |
| * [buildbucket:tests/cancel](#recipes-buildbucket_tests_cancel) (Python3 ✅) |
| * [buildbucket:tests/collect](#recipes-buildbucket_tests_collect) (Python3 ✅) |
| * [buildbucket:tests/output_commit](#recipes-buildbucket_tests_output_commit) (Python3 ✅) — This recipe tests the buildbucket. |
| * [buildbucket:tests/schedule](#recipes-buildbucket_tests_schedule) (Python3 ✅) |
| * [buildbucket:tests/search](#recipes-buildbucket_tests_search) (Python3 ✅) |
| * [cas:examples/full](#recipes-cas_examples_full) (Python3 ✅) |
| * [cas_input:examples/full](#recipes-cas_input_examples_full) (Python3 ✅) |
| * [change_verifier:tests/search](#recipes-change_verifier_tests_search) (Python3 ✅) |
| * [cipd:examples/full](#recipes-cipd_examples_full) (Python3 ✅) |
| * [commit_position:examples/full](#recipes-commit_position_examples_full) (Python3 ✅) |
| * [context:examples/full](#recipes-context_examples_full) (Python3 ✅) |
| * [context:tests/cwd](#recipes-context_tests_cwd) (Python3 ✅) |
| * [context:tests/env](#recipes-context_tests_env) (Python3 ✅) |
| * [context:tests/greenlet](#recipes-context_tests_greenlet) (Python3 ✅) |
| * [context:tests/infra_step](#recipes-context_tests_infra_step) (Python3 ✅) |
| * [context:tests/luci_context](#recipes-context_tests_luci_context) (Python3 ✅) |
| * [cq:examples/ordered_cls](#recipes-cq_examples_ordered_cls) (Python3 ✅) |
| * [cq:examples/trigger_child_builds](#recipes-cq_examples_trigger_child_builds) (Python3 ✅) |
| * [cq:tests/cl_group_key](#recipes-cq_tests_cl_group_key) (Python3 ✅) |
| * [cq:tests/do_not_retry](#recipes-cq_tests_do_not_retry) (Python3 ✅) |
| * [cq:tests/experimental](#recipes-cq_tests_experimental) (Python3 ✅) |
| * [cq:tests/inactive](#recipes-cq_tests_inactive) (Python3 ✅) |
| * [cq:tests/mode_of_run](#recipes-cq_tests_mode_of_run) (Python3 ✅) |
| * [cq:tests/reuse](#recipes-cq_tests_reuse) (Python3 ✅) |
| * [cq:tests/triggered_build_ids](#recipes-cq_tests_triggered_build_ids) (Python3 ✅) |
| * [engine_tests/bad_subprocess](#recipes-engine_tests_bad_subprocess) (Python3 ✅) — Tests that daemons that hang on to STDOUT can't cause the engine to hang. |
| * [engine_tests/comprehensive_ui](#recipes-engine_tests_comprehensive_ui) (Python3 ✅) — A fast-running recipe which comprehensively covers all StepPresentation features available in the recipe engine. |
| * [engine_tests/config_operations](#recipes-engine_tests_config_operations) (Python3 ✅) — Tests that recipes can modify configuration options in various ways. |
| * [engine_tests/early_termination](#recipes-engine_tests_early_termination) (Python3 ✅) — Simple recipe which runs a bunch of subprocesses which react to early termination in different ways. |
| * [engine_tests/expect_exception](#recipes-engine_tests_expect_exception) (Python3 ✅) — Tests that step_data can accept multiple specs at once. |
| * [engine_tests/failure_results](#recipes-engine_tests_failure_results) (Python3 ✅) — Tests that run_steps is handling recipe failures correctly. |
| * [engine_tests/functools_partial](#recipes-engine_tests_functools_partial) (Python3 ✅) — Engine shouldn't explode when step_test_data gets functools. |
| * [engine_tests/incorrect_recipe_result](#recipes-engine_tests_incorrect_recipe_result) (Python3 ✅) — Tests that engine. |
| * [engine_tests/long_sleep](#recipes-engine_tests_long_sleep) (Python3 ✅) — Simple recipe which sleeps in a subprocess forever to facilitate early termination tests. |
| * [engine_tests/missing_start_dir](#recipes-engine_tests_missing_start_dir) (Python3 ✅) — Tests that deleting the current working directory doesn't immediately fail. |
| * [engine_tests/module_injection_site](#recipes-engine_tests_module_injection_site) (Python3 ✅) — This test serves to demonstrate that the ModuleInjectionSite object on recipe modules (i. |
| * [engine_tests/multi_test_data](#recipes-engine_tests_multi_test_data) (Python3 ✅) — Tests that step_data can accept multiple specs at once. |
| * [engine_tests/multiple_placeholders](#recipes-engine_tests_multiple_placeholders) (Python3 ✅) — Tests error checking around multiple placeholders in a single step. |
| * [engine_tests/nonexistent_command](#recipes-engine_tests_nonexistent_command) (Python3 ✅) |
| * [engine_tests/placeholder_exception](#recipes-engine_tests_placeholder_exception) (Python3 ✅) — Tests that placeholders can't wreck the world by exhausting the step stack. |
| * [engine_tests/proto_output_properties](#recipes-engine_tests_proto_output_properties) (Python3 ✅) — Tests that output properties can be a proto message. |
| * [engine_tests/proto_properties](#recipes-engine_tests_proto_properties) (Python3 ✅) |
| * [engine_tests/recipe_paths](#recipes-engine_tests_recipe_paths) (Python3 ✅) — Tests that recipes have access to names, resources and their repo. |
| * [engine_tests/sort_properties](#recipes-engine_tests_sort_properties) (Python3 ✅) — Tests that step presentation properties can be ordered. |
| * [engine_tests/undeclared_method](#recipes-engine_tests_undeclared_method) (Python3 ✅) |
| * [engine_tests/unicode](#recipes-engine_tests_unicode) (Python3 ✅) |
| * [engine_tests/whitelist_steps](#recipes-engine_tests_whitelist_steps) (Python3 ✅) — Tests that step_data can accept multiple specs at once. |
| * [file:examples/compute_hash](#recipes-file_examples_compute_hash) (Python3 ✅) |
| * [file:examples/copy](#recipes-file_examples_copy) (Python3 ✅) |
| * [file:examples/copytree](#recipes-file_examples_copytree) (Python3 ✅) |
| * [file:examples/error](#recipes-file_examples_error) (Python3 ✅) |
| * [file:examples/file_hash](#recipes-file_examples_file_hash) (Python3 ✅) |
| * [file:examples/flatten_single_directories](#recipes-file_examples_flatten_single_directories) (Python3 ✅) |
| * [file:examples/glob](#recipes-file_examples_glob) (Python3 ✅) |
| * [file:examples/handle_json_file](#recipes-file_examples_handle_json_file) (Python3 ✅) |
| * [file:examples/listdir](#recipes-file_examples_listdir) (Python3 ✅) |
| * [file:examples/raw_copy](#recipes-file_examples_raw_copy) (Python3 ✅) |
| * [file:examples/read_write_proto](#recipes-file_examples_read_write_proto) (Python3 ✅) |
| * [file:examples/symlink](#recipes-file_examples_symlink) (Python3 ✅) |
| * [file:examples/truncate](#recipes-file_examples_truncate) (Python3 ✅) |
| * [futures:examples/background_helper](#recipes-futures_examples_background_helper) (Python3 ✅) |
| * [futures:examples/extreme_namespaces](#recipes-futures_examples_extreme_namespaces) (Python3 ✅) |
| * [futures:examples/fan_out_in](#recipes-futures_examples_fan_out_in) (Python3 ✅) |
| * [futures:examples/lazy_fan_out_in](#recipes-futures_examples_lazy_fan_out_in) (Python3 ✅) |
| * [futures:examples/lazy_fan_out_in_early_abort](#recipes-futures_examples_lazy_fan_out_in_early_abort) (Python3 ✅) |
| * [futures:examples/lottasteps](#recipes-futures_examples_lottasteps) (Python3 ✅) — This tests the engine's ability to handle many simultaneously-started steps. |
| * [futures:examples/metadata](#recipes-futures_examples_metadata) (Python3 ✅) — This tests metadata features of the Future object. |
| * [futures:examples/result](#recipes-futures_examples_result) (Python3 ✅) |
| * [futures:examples/semaphore](#recipes-futures_examples_semaphore) (Python3 ✅) |
| * [generator_script:examples/full](#recipes-generator_script_examples_full) (Python3 ✅) |
| * [golang:examples/full](#recipes-golang_examples_full) (Python3 ✅) |
| * [json:examples/full](#recipes-json_examples_full) (Python3 ✅) |
| * [json:tests/add_json_log](#recipes-json_tests_add_json_log) (Python3 ✅) |
| * [led:tests/full](#recipes-led_tests_full) (Python3 ✅) |
| * [led:tests/no_exist](#recipes-led_tests_no_exist) (Python3 ✅) |
| * [led:tests/trigger_build](#recipes-led_tests_trigger_build) (Python3 ✅) |
| * [legacy_annotation:examples/full](#recipes-legacy_annotation_examples_full) (Python3 ✅) |
| * [milo:examples/full](#recipes-milo_examples_full) (Python3 ✅) |
| * [nodejs:examples/full](#recipes-nodejs_examples_full) (Python3 ✅) |
| * [path:examples/full](#recipes-path_examples_full) (Python3 ✅) |
| * [placeholder](#recipes-placeholder) (Python3 ✅) |
| * [platform:examples/full](#recipes-platform_examples_full) (Python3 ✅) |
| * [properties:examples/full](#recipes-properties_examples_full) (Python3 ✅) |
| * [proto:tests/encode_decode](#recipes-proto_tests_encode_decode) (Python3 ✅) |
| * [proto:tests/placeholders](#recipes-proto_tests_placeholders) (Python3 ✅) |
| * [random:tests/full](#recipes-random_tests_full) (Python3 ✅) |
| * [raw_io:examples/full](#recipes-raw_io_examples_full) (Python3 ✅) |
| * [raw_io:tests/output_mismatch](#recipes-raw_io_tests_output_mismatch) (Python3 ✅) |
| * [resultdb:examples/exonerate](#recipes-resultdb_examples_exonerate) (Python3 ✅) |
| * [resultdb:examples/get_included_invocations](#recipes-resultdb_examples_get_included_invocations) (Python3 ✅) |
| * [resultdb:examples/include](#recipes-resultdb_examples_include) (Python3 ✅) |
| * [resultdb:examples/query](#recipes-resultdb_examples_query) (Python3 ✅) |
| * [resultdb:examples/query_test_result_statistics](#recipes-resultdb_examples_query_test_result_statistics) (Python3 ✅) |
| * [resultdb:examples/result_history](#recipes-resultdb_examples_result_history) (Python3 ✅) |
| * [resultdb:examples/resultsink](#recipes-resultdb_examples_resultsink) (Python3 ✅) |
| * [resultdb:examples/test_presentation](#recipes-resultdb_examples_test_presentation) (Python3 ✅) |
| * [resultdb:examples/test_presentation_default](#recipes-resultdb_examples_test_presentation_default) (Python3 ✅) |
| * [resultdb:examples/upload_invocation_artifacts](#recipes-resultdb_examples_upload_invocation_artifacts) (Python3 ✅) |
| * [runtime:tests/full](#recipes-runtime_tests_full) (Python3 ✅) |
| * [scheduler:examples/emit_triggers](#recipes-scheduler_examples_emit_triggers) (Python3 ✅) — This file is a recipe demonstrating emitting triggers to LUCI Scheduler. |
| * [scheduler:examples/info](#recipes-scheduler_examples_info) (Python3 ✅) — This file is a recipe demonstrating reading/mocking scheduler host. |
| * [scheduler:examples/triggers](#recipes-scheduler_examples_triggers) (Python3 ✅) — This file is a recipe demonstrating reading triggers of the current build. |
| * [service_account:examples/full](#recipes-service_account_examples_full) (Python3 ✅) |
| * [step:examples/full](#recipes-step_examples_full) (Python3 ✅) |
| * [step:tests/active_result](#recipes-step_tests_active_result) (Python3 ✅) |
| * [step:tests/defer](#recipes-step_tests_defer) (Python3 ✅) |
| * [step:tests/empty](#recipes-step_tests_empty) (Python3 ✅) |
| * [step:tests/inject_paths](#recipes-step_tests_inject_paths) (Python3 ✅) |
| * [step:tests/nested](#recipes-step_tests_nested) (Python3 ✅) |
| * [step:tests/raise_on_failure](#recipes-step_tests_raise_on_failure) (Python3 ✅) |
| * [step:tests/stdio](#recipes-step_tests_stdio) (Python3 ✅) |
| * [step:tests/step_call_args](#recipes-step_tests_step_call_args) (Python3 ✅) |
| * [step:tests/step_cost](#recipes-step_tests_step_cost) (Python3 ✅) |
| * [step:tests/sub_build](#recipes-step_tests_sub_build) (Python3 ✅) |
| * [step:tests/timeout](#recipes-step_tests_timeout) (Python3 ✅) |
| * [swarming:examples/full](#recipes-swarming_examples_full) (Python3 ✅) |
| * [swarming:examples/this_task](#recipes-swarming_examples_this_task) (Python3 ✅) |
| * [swarming:tests/copy](#recipes-swarming_tests_copy) (Python3 ✅) |
| * [swarming:tests/realms](#recipes-swarming_tests_realms) (Python3 ✅) |
| * [swarming:tests/task_request_from_jsonish](#recipes-swarming_tests_task_request_from_jsonish) (Python3 ✅) |
| * [time:examples/full](#recipes-time_examples_full) (Python3 ✅) |
| * [tricium:examples/add_comment](#recipes-tricium_examples_add_comment) (Python3 ✅) |
| * [tricium:examples/wrapper](#recipes-tricium_examples_wrapper) (Python3 ✅) — An example of a recipe wrapping legacy analyzers. |
| * [tricium:tests/add_comment_validation](#recipes-tricium_tests_add_comment_validation) (Python3 ✅) |
| * [tricium:tests/enforce_comments_num_limit](#recipes-tricium_tests_enforce_comments_num_limit) (Python3 ✅) |
| * [url:examples/full](#recipes-url_examples_full) (Python3 ✅) |
| * [url:tests/join](#recipes-url_tests_join) (Python3 ✅) |
| * [url:tests/validate_url](#recipes-url_tests_validate_url) (Python3 ✅) |
| * [uuid:examples/full](#recipes-uuid_examples_full) (Python3 ✅) |
| * [version:examples/full](#recipes-version_examples_full) (Python3 ✅) |
| * [warning:tests/fakes](#recipes-warning_tests_fakes) (Python3 ✅) — This is a fake recipe to trick the simulation and make it believes that this module has tests. |
| ## Recipe Modules |
| |
| ### *recipe_modules* / [archive](/recipe_modules/archive) |
| |
| [DEPS](/recipe_modules/archive/__init__.py#7): [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| #### **class [ArchiveApi](/recipe_modules/archive/api.py#8)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| Provides steps to manipulate archive files (tar, zip, etc.). |
| |
| — **def [extract](/recipe_modules/archive/api.py#42)(self, step_name, archive_file, output, mode='safe', include_files=(), archive_type=None):** |
| |
| Step to uncompress |archive_file| into |output| directory. |
| |
| Archive will be unpacked to |output| so that root of an archive is in |
| |output|, i.e. archive.tar/file.txt will become |output|/file.txt. |
| |
| Step will FAIL if |output| already exists. |
| |
| Args: |
| |
| * step_name (str): display name of a step. |
| * archive_file (Path): path to an archive file to uncompress, MUST exist. |
| * output (Path): path to a directory to unpack to. The output directory |
| MAY exist, in which case the extract will unpack on-top-of the existing |
| files. It's an error for one of the extracted files to overlap with an |
| already-present file, however. |
| * mode (str): Must be either 'safe' or 'unsafe'. In safe mode, if the |
| archive attempts to extract files which would escape the extraction |
| `output` location, the extraction will fail (raise StepException) |
| which contains a member `StepException.archive_skipped_files` (all |
| other files will be extracted normally). If 'unsafe', then tarfiles |
| containing paths escaping `output` will be extracted as-is. |
| * include_files (List[str]) - A list of globs matching files within the |
| archive. Any files not matching any of these globs will be skipped. |
| If omitted, all files are extracted (the default). Globs are matched |
| with the `fnmatch` module. If a file "filename" in the archive exists, |
| include_files with "file*" will match it. All paths for the matcher |
| are converted to posix style (forward slash). |
| * archive_type (str): archive_file's archive type ("zip" or "tar"). This |
| allows overriding the default detected type (based on file extension). |
| |
| — **def [package](/recipe_modules/archive/api.py#13)(self, root):** |
| |
| Returns Package object that can be used to compress a set of files. |
| |
| Usage: |
| |
| # Archive root/file and root/directory/** |
| (api.archive.package(root). |
| with_file(root.join('file')). |
| with_dir(root.join('directory')). |
| archive('archive step', output, 'tbz')) |
| |
| # Archive root/** |
| zip_path = ( |
| api.archive.package(root). |
| archive('archive step', api.path['start_dir'].join('output.zip')) |
| ) |
| |
| Args: |
| |
| * root: a directory that would become root of a package, all files added |
| to an archive must be Paths which are under this directory. If no |
| files or directories are added with 'with_file' or 'with_dir', the |
| entire root directory is packaged. |
| |
| Returns: |
| Package object. |
| ### *recipe_modules* / [assertions](/recipe_modules/assertions) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| #### **class [AssertionsApi](/recipe_modules/assertions/api.py#55)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| Provides access to the assertion methods of the python unittest module. |
| |
| Asserting non-step aspects of code (return values, non-step side effects) is |
| expressed more naturally by making assertions within the RunSteps function of |
| the test recipe. This api provides access to the assertion methods of |
| unittest.TestCase to be used within test recipes. |
| |
| All non-deprecated assertion methods of unittest.TestCase can be used. |
| |
| An enhancement to the assertion methods is that if a custom msg is used, |
| values for the non-msg arguments can be substituted into the message using |
| named substitution with the format method of strings. |
| e.g. self.AssertEqual(0, 1, '{first} should be {second}') will raise an |
| AssertionError with the message: '0 should be 1'. |
| |
| The attributes longMessage and maxDiff are supported and have the same |
| behavior as the unittest module. |
| |
| Example (.../recipe_modules/my_module/tests/foo.py): |
| ``` |
| DEPS = [ |
| 'my_module', |
| 'recipe_engine/assertions', |
| 'recipe_engine/properties', |
| 'recipe_engine/runtime', |
| ] |
| |
| def RunSteps(api): |
| '''Behavior of foo depends on whether build is experimental''' |
| value = api.my_module.foo() |
| expected_value = api.properties.get('expected_value') |
| api.assertions.assertEqual(value, expected_value) |
| |
| def GenTests(api): |
| yield ( |
| api.test('basic') |
| + api.properties(expected_value='normal value') |
| ) |
| |
| yield ( |
| api.test('experimental') |
| + api.properties(expected_value='experimental value') |
| + api.runtime(is_experimental=True) |
| ) |
| ``` |
| ### *recipe_modules* / [bcid\_reporter](/recipe_modules/bcid_reporter) |
| |
| [DEPS](/recipe_modules/bcid_reporter/__init__.py#7): [cipd](#recipe_modules-cipd), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| #### **class [BcidReporterApi](/recipe_modules/bcid_reporter/api.py#13)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| API for interacting with Provenance server using the broker tool. |
| |
|   **@property**<br>— **def [bcid\_reporter\_path](/recipe_modules/bcid_reporter/api.py#25)(self):** |
| |
| Returns the path to the broker binary. |
| |
| When the property is accessed the first time, the latest stable, released |
| broker will be installed using cipd. |
| |
| — **def [report\_cipd](/recipe_modules/bcid_reporter/api.py#72)(self, digest, pkg, iid, server_url=None):** |
| |
| Reports cipd digest to local local provenance server. |
| |
| This is used to report produced artifacts hash and metadata to server, it is |
| used to generate provenance. |
| |
| Args: |
| * digest (str) - The hash of the artifact. |
| * pkg (str) - Name of the cipd package built. |
| * iid (str) - Instance ID of the package. |
| * server_url (Optional[str]) - URL for the local proveance server, the |
| broker tool will use default if not specified. |
| |
| — **def [report\_gcs](/recipe_modules/bcid_reporter/api.py#101)(self, digest, guri, server_url=None):** |
| |
| Reports cipd digest to local local provenance server. |
| |
| This is used to report produced artifacts hash and metadata to proveance, it |
| is used to generate provenance. |
| |
| Args: |
| * digest (str) - The hash of the artifact. |
| * guri (str) - Name of the GCS artifact built. This is the unique GCS URI, |
| e.g. gs://bucket/path/to/binary. |
| * server_url (Optional[str]) - URL for the local proveance server, the |
| broker tool will use default if not specified. |
| |
| — **def [report\_stage](/recipe_modules/bcid_reporter/api.py#41)(self, stage, server_url=None):** |
| |
| Reports task stage to local provenance server. |
| |
| Args: |
| * stage (str) - The stage at which task is executing currently, e.g. |
| "start". Concept of task stage is native to Provenance service, this is |
| a way of self-reporting phase of a task's lifecycle. This information is |
| used in conjunction with process-inspected data to make security policy |
| decisions. |
| Valid stages: (start, fetch, compile, upload, upload-complete, test). |
| * server_url (Optional[str]) - URL for the local proveance server, the |
| broker tool will use default if not specified. |
| ### *recipe_modules* / [buildbucket](/recipe_modules/buildbucket) |
| |
| [DEPS](/recipe_modules/buildbucket/__init__.py#7): [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [raw\_io](#recipe_modules-raw_io), [resultdb](#recipe_modules-resultdb), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step), [uuid](#recipe_modules-uuid) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| API for interacting with the buildbucket service. |
| |
| Requires `buildbucket` command in `$PATH`: |
| https://godoc.org/go.chromium.org/luci/buildbucket/client/cmd/buildbucket |
| |
| `url_title_fn` parameter used in this module is a function that accepts a |
| `build_pb2.Build` and returns a link title. |
| If it returns `None`, the link is not reported. Default link title is build id. |
| |
| #### **class [BuildbucketApi](/recipe_modules/buildbucket/api.py#32)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| A module for interacting with buildbucket. |
| |
| — **def [add\_tags\_to\_current\_build](/recipe_modules/buildbucket/api.py#244)(self, tags):** |
| |
| Adds arbitrary tags during the runtime of a build. |
| |
| Args: |
| * tags(list of common_pb2.StringPair): tags to add. May contain duplicates. |
| Empty tag values won't remove existing tags with matching keys, since tags |
| can only be added. |
| |
|   **@property**<br>— **def [bucket\_v1](/recipe_modules/buildbucket/api.py#958)(self):** |
| |
| Returns bucket name in v1 format. |
| |
| Mostly useful for scheduling new builds using V1 API. |
| |
|   **@property**<br>— **def [build](/recipe_modules/buildbucket/api.py#131)(self):** |
| |
| Returns current build as a `buildbucket.v2.Build` protobuf message. |
| |
| For value format, see `Build` message in |
| [build.proto](https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/build.proto). |
| |
| DO NOT MODIFY the returned value. |
| Do not implement conditional logic on returned tags; they are for indexing. |
| Use returned `build.input` instead. |
| |
| Pure Buildbot support: to simplify transition to buildbucket, returns a |
| message even if the current build is not a buildbucket build. Provides as |
| much information as possible. Some fields may be left empty, violating |
| the rules described in the .proto files. |
| If the current build is not a buildbucket build, returned `build.id` is 0. |
| |
|   **@property**<br>— **def [build\_id](/recipe_modules/buildbucket/api.py#969)(self):** |
| |
| *** note |
| **DEPRECATED**: use build.id instead. |
| *** |
| |
|   **@property**<br>— **def [build\_input](/recipe_modules/buildbucket/api.py#974)(self):** |
| |
| *** note |
| **DEPRECATED**: use build.input instead. |
| *** |
| |
| — **def [build\_url](/recipe_modules/buildbucket/api.py#168)(self, host=None, build_id=None):** |
| |
| Returns url to a build. Defaults to current build. |
| |
|   **@property**<br>— **def [builder\_cache\_path](/recipe_modules/buildbucket/api.py#269)(self):** |
| |
| Path to the builder cache directory. |
| |
| Such directory can be used to cache builder-specific data. |
| It remains on the bot from build to build. |
| See "Builder cache" in |
| https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/project_config.proto |
| |
|   **@property**<br>— **def [builder\_id](/recipe_modules/buildbucket/api.py#979)(self):** |
| |
| *** note |
| **DEPRECATED**: Use build.builder instead. |
| *** |
| |
|   **@property**<br>— **def [builder\_name](/recipe_modules/buildbucket/api.py#150)(self):** |
| |
| Returns builder name. Shortcut for `.build.builder.builder`. |
| |
|   **@property**<br>— **def [builder\_realm](/recipe_modules/buildbucket/api.py#155)(self):** |
| |
| Returns the LUCI realm name of the current build. |
| |
| Raises `InfraFailure` if the build proto doesn't have `project` or `bucket` |
| set. This can happen in tests that don't properly mock build proto. |
| |
| — **def [cancel\_build](/recipe_modules/buildbucket/api.py#687)(self, build_id, reason=' ', step_name=None):** |
| |
| Cancel the build associated with the provided build id. |
| |
| Args: |
| * `build_id` (int|str): a buildbucket build ID. |
| It should be either an integer(e.g. 123456789 or '123456789') |
| or the numeric value in string format. |
| * `reason` (str): reason for canceling the given build. |
| Can't be None or Empty. Markdown is supported. |
| |
| Returns: |
| None if build is successfully canceled. Otherwise, an InfraFailure will |
| be raised |
| |
| — **def [collect\_build](/recipe_modules/buildbucket/api.py#789)(self, build_id, \*\*kwargs):** |
| |
| Shorthand for `collect_builds` below, but for a single build only. |
| |
| Args: |
| * build_id: Integer ID of the build to wait for. |
| |
| Returns: |
| [Build](https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/build.proto). |
| for the ended build. |
| |
| — **def [collect\_builds](/recipe_modules/buildbucket/api.py#802)(self, build_ids, interval=None, timeout=None, step_name=None, raise_if_unsuccessful=False, url_title_fn=None, mirror_status=False, fields=DEFAULT_FIELDS):** |
| |
| Waits for a set of builds to end and returns their details. |
| |
| Args: |
| * `build_ids`: List of build IDs to wait for. |
| * `interval`: Delay (in secs) between requests while waiting for build to |
| end. Defaults to 1m. |
| * `timeout`: Maximum time to wait for builds to end. Defaults to 1h. |
| * `step_name`: Custom name for the generated step. |
| * `raise_if_unsuccessful`: if any build being collected did not succeed, |
| raise an exception. |
| * `url_title_fn`: generates build URL title. See module docstring. |
| * `mirror_status`: mark the step as failed/infra-failed if any of the builds |
| did not succeed. Ignored if raise_if_unsuccessful is True. |
| * `fields`: a list of fields to include in the response, names relative |
| to `build_pb2.Build` (e.g. ["tags", "infra.swarming"]). |
| |
| Returns: |
| A map from integer build IDs to the corresponding |
| [Build](https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/build.proto) |
| for all specified builds. |
| |
| — **def [get](/recipe_modules/buildbucket/api.py#768)(self, build_id, url_title_fn=None, step_name=None, fields=DEFAULT_FIELDS):** |
| |
| Gets a build. |
| |
| Args: |
| * `build_id`: a buildbucket build ID. |
| * `url_title_fn`: generates build URL title. See module docstring. |
| * `step_name`: name for this step. |
| * `fields`: a list of fields to include in the response, names relative |
| to `build_pb2.Build` (e.g. ["tags", "infra.swarming"]). |
| |
| Returns: |
| A build_pb2.Build. |
| |
| — **def [get\_multi](/recipe_modules/buildbucket/api.py#725)(self, build_ids, url_title_fn=None, step_name=None, fields=DEFAULT_FIELDS):** |
| |
| Gets multiple builds. |
| |
| Args: |
| * `build_ids`: a list of build IDs. |
| * `url_title_fn`: generates build URL title. See module docstring. |
| * `step_name`: name for this step. |
| * `fields`: a list of fields to include in the response, names relative |
| to `build_pb2.Build` (e.g. ["tags", "infra.swarming"]). |
| |
| Returns: |
| A dict {build_id: build_pb2.Build}. |
| |
|   **@property**<br>— **def [gitiles\_commit](/recipe_modules/buildbucket/api.py#173)(self):** |
| |
| Returns input gitiles commit. Shortcut for `.build.input.gitiles_commit`. |
| |
| For value format, see |
| [`GitilesCommit` message](https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/build.proto). |
| |
| Never returns None, but sub-fields may be empty. |
| |
| — **def [hide\_current\_build\_in\_gerrit](/recipe_modules/buildbucket/api.py#265)(self):** |
| |
| Hides the build in UI |
| |
|   **@host.setter**<br>— **def [host](/recipe_modules/buildbucket/api.py#99)(self, value):** |
| |
| — **def [is\_critical](/recipe_modules/buildbucket/api.py#184)(self, build=None):** |
| |
| Returns True if the build is critical. Build defaults to the current one. |
| |
| |
| — **def [run](/recipe_modules/buildbucket/api.py#290)(self, schedule_build_requests, collect_interval=None, timeout=None, url_title_fn=None, step_name=None, raise_if_unsuccessful=False):** |
| |
| Runs builds and returns results. |
| |
| A shortcut for schedule() and collect_builds(). |
| See their docstrings. |
| |
| Returns: |
| A list of completed |
| [Builds](https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/build.proto) |
| in the same order as schedule_build_requests. |
| |
| — **def [schedule](/recipe_modules/buildbucket/api.py#516)(self, schedule_build_requests, url_title_fn=None, step_name=None, include_sub_invs=True):** |
| |
| Schedules a batch of builds. |
| |
| Example: |
| ```python |
| req = api.buildbucket.schedule_request(builder='linux') |
| api.buildbucket.schedule([req]) |
| ``` |
| |
| Hint: when scheduling builds for CQ, let CQ know about them: |
| ```python |
| api.cq.record_triggered_builds(*api.buildbucket.schedule([req1, req2])) |
| ``` |
| |
| Args: |
| * schedule_build_requests: a list of `buildbucket.v2.ScheduleBuildRequest` |
| protobuf messages. Create one by calling `schedule_request` method. |
| * url_title_fn: generates a build URL title. See module docstring. |
| * step_name: name for this step. |
| * include_sub_invs: flag for including the scheduled builds' ResultDB |
| invocations into the current build's invocation. Default is True. |
| |
| Returns: |
| A list of |
| [`Build`](https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/build.proto) |
| messages in the same order as requests. |
| |
| Raises: |
| `InfraFailure` if any of the requests fail. |
| |
| — **def [schedule\_request](/recipe_modules/buildbucket/api.py#318)(self, builder, project=INHERIT, bucket=INHERIT, properties=None, experimental=INHERIT, experiments=None, gitiles_commit=INHERIT, gerrit_changes=INHERIT, tags=None, inherit_buildsets=True, swarming_parent_run_id=None, dimensions=None, priority=INHERIT, critical=INHERIT, exe_cipd_version=None, fields=DEFAULT_FIELDS, can_outlive_parent=None):** |
| |
| Creates a new `ScheduleBuildRequest` message with reasonable defaults. |
| |
| This is a convenient function to create a `ScheduleBuildRequest` message. |
| |
| Among args, messages can be passed as dicts of the same structure. |
| |
| Example: |
| |
| request = api.buildbucket.schedule_request( |
| builder='linux', |
| tags=api.buildbucket.tags(a='b'), |
| ) |
| build = api.buildbucket.schedule([request])[0] |
| |
| Args: |
| * builder (str): name of the destination builder. |
| * project (str|INHERIT): project containing the destinaiton builder. |
| Defaults to the project of the current build. |
| * bucket (str|INHERIT): bucket containing the destination builder. |
| Defaults to the bucket of the current build. |
| * properties (dict): input properties for the new build. |
| * experimental (common_pb2.Trinary|INHERIT): whether the build is allowed |
| to affect prod. |
| Defaults to the value of the current build. |
| Read more about |
| [`experimental` field](https://cs.chromium.org/chromium/infra/go/src/go.chromium.org/luci/buildbucket/proto/build.proto?q="bool experimental"). |
| * experiments (Dict[str, bool]|None): enabled and disabled experiments |
| for the new build. Overrides the result computed from experiments defined |
| in builder config. |
| * gitiles_commit (common_pb2.GitilesCommit|INHERIT): input commit. |
| Defaults to the input commit of the current build. |
| Read more about |
| [`gitiles_commit`](https://cs.chromium.org/chromium/infra/go/src/go.chromium.org/luci/buildbucket/proto/build.proto?q=Input.gitiles_commit). |
| * gerrit_changes (list of common_pb2.GerritChange|INHERIT): list of input |
| CLs. |
| Defaults to gerrit changes of the current build. |
| Read more about |
| [`gerrit_changes`](https://cs.chromium.org/chromium/infra/go/src/go.chromium.org/luci/buildbucket/proto/build.proto?q=Input.gerrit_changes). |
| * tags (list of common_pb2.StringPair): tags for the new build. |
| * inherit_buildsets (bool): if `True` (default), the returned request will |
| include buildset tags from the current build. |
| * swarming_parent_run_id (str|NoneType): associate the new build as child of |
| the given swarming run id. |
| Defaults to `None` meaning no association. |
| If passed, must be a valid swarming *run* id (specific execution of a |
| task) for the swarming instance on which build will execute. Typically, |
| you'd want to set it to |
| [`api.swarming.task_id`](https://cs.chromium.org/chromium/infra/recipes-py/recipe_modules/swarming/api.py?type=cs&q=recipe_modules/swarming/api.py+%22def+task_id%22&sq=package:chromium&g=0&l=924). |
| Read more about |
| [`parent_run_id`](https://cs.chromium.org/chromium/infra/go/src/go.chromium.org/luci/buildbucket/proto/rpc.proto?type=cs&q="string+parent_run_id"). |
| * dimensions (list of common_pb2.RequestedDimension): override dimensions |
| defined on the server. |
| * priority (int|NoneType|INHERIT): Swarming task priority. |
| The lower the more important. Valid values are `[20..255]`. |
| Defaults to the value of the current build. |
| Pass `None` to use the priority of the destination builder. |
| * critical (bool|common_pb2.Trinary|INHERIT): whether the build status |
| should not be used to assess correctness of the commit/CL. |
| Defaults to .build.critical. |
| See also Build.critical in |
| https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/build.proto |
| * exe_cipd_version (NoneType|str|INHERIT): CIPD version of the LUCI |
| Executable (e.g. recipe) to use. Pass `None` to use the server configured |
| one. |
| * fields (list of strs): a list of fields to include in the response, names |
| relative to `build_pb2.Build` (e.g. ["tags", "infra.swarming"]). |
| * can_outlive_parent: flag for if the scheduled child build can outlive |
| the current build or not (as enforced by Buildbucket; |
| swarming_parent_run_id currently ALSO applies). |
| Default is None. For now |
| * if `luci.buildbucket.manage_parent_child_relationship` is not in the |
| current build's experiments, can_outlive_parent is always True. |
| * Otherwise if can_outlive_parent is None, |
| ScheduleBuildRequest.can_outlive_parent will be determined by |
| swarming_parent_run_id. |
| TODO(crbug.com/1031205): remove swarming_parent_run_id. |
| |
| — **def [search](/recipe_modules/buildbucket/api.py#611)(self, predicate, limit=None, url_title_fn=None, report_build=True, step_name=None, fields=DEFAULT_FIELDS):** |
| |
| Searches for builds. |
| |
| Example: find all builds of the current CL. |
| |
| ```python |
| from PB.go.chromium.org.luci.buildbucket.proto import rpc as builds_service_pb2 |
| |
| related_builds = api.buildbucket.search(builds_service_pb2.BuildPredicate( |
| gerrit_changes=list(api.buildbucket.build.input.gerrit_changes), |
| )) |
| ``` |
| |
| Args: |
| * predicate: a `builds_service_pb2.BuildPredicate` object or a list |
| thereof. If a list, the predicates are connected with logical OR. |
| * limit: max number of builds to return. Defaults to 1000. |
| * url_title_fn: generates a build URL title. See module docstring. |
| * report_build: whether to report build search results in step |
| presentation. Defaults to True. |
| * fields: a list of fields to include in the response, names relative |
| to `build_pb2.Build` (e.g. ["tags", "infra.swarming"]). |
| |
| Returns: |
| A list of builds ordered newest-to-oldest. |
| |
| — **def [set\_buildbucket\_host](/recipe_modules/buildbucket/api.py#103)(self, host):** |
| |
| *** note |
| **DEPRECATED**: Use host property. |
| *** |
| |
| — **def [set\_output\_gitiles\_commit](/recipe_modules/buildbucket/api.py#190)(self, gitiles_commit):** |
| |
| Sets `buildbucket.v2.Build.output.gitiles_commit` field. |
| |
| This will tell other systems, consuming the build, what version of the code |
| was actually used in this build and what is the position of this build |
| relative to other builds of the same builder. |
| |
| Args: |
| * gitiles_commit(buildbucket.common_pb2.GitilesCommit): the commit that was |
| actually checked out. Must have host, project and id. |
| ID must match r'^[0-9a-f]{40}$' (git revision). |
| If position is present, the build can be ordered along commits. |
| Position requires ref. |
| Ref, if not empty, must start with `refs/`. |
| |
| Can be called at most once per build. |
| |
|   **@staticmethod**<br>— **def [tags](/recipe_modules/buildbucket/api.py#239)(\*\*tags):** |
| |
| Alias for tags in util.py. See doc there. |
| |
| — **def [use\_service\_account\_key](/recipe_modules/buildbucket/api.py#117)(self, key_path):** |
| |
| Tells this module to start using given service account key for auth. |
| |
| Otherwise the module is using the default account (when running on LUCI or |
| locally), or no auth at all (when running on Buildbot). |
| |
| Exists mostly to support Buildbot environment. Recipe for LUCI environment |
| should not use this. |
| |
| Args: |
| * key_path (str): a path to JSON file with service account credentials. |
| |
|   **@contextmanager**<br>— **def [with\_host](/recipe_modules/buildbucket/api.py#107)(self, host):** |
| |
| Set the buildbucket host while in context, then reverts it. |
| ### *recipe_modules* / [cas](/recipe_modules/cas) |
| |
| [DEPS](/recipe_modules/cas/__init__.py#9): [cipd](#recipe_modules-cipd), [context](#recipe_modules-context), [file](#recipe_modules-file), [path](#recipe_modules-path), [raw\_io](#recipe_modules-raw_io), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| API for interacting with cas client. |
| |
| #### **class [CasApi](/recipe_modules/cas/api.py#10)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| A module for interacting with cas client. |
| |
| — **def [archive](/recipe_modules/cas/api.py#94)(self, step_name, root, \*paths, \*\*kwargs):** |
| |
| Archives given paths to a cas server. |
| |
| Args: |
| * step_name (str): name of the step. |
| * root (str|Path): root directory of archived tree, should be absolute |
| path. |
| * paths (list(str|Path)): |
| path to archived files/dirs, should be absolute path. If empty, [root] |
| will be used. |
| * log_level (str): logging level to use, rarely needed but helpful for |
| debugging. |
| |
| Returns: |
| digest (str): digest of uploaded root directory. |
| |
| — **def [download](/recipe_modules/cas/api.py#65)(self, step_name, digest, output_dir):** |
| |
| Downloads a directory tree from a cas server. |
| |
| Args: |
| |
| * step_name (str): name of the step. |
| * digest (str): the digest of a cas tree. |
| * output_dir (Path): path to an output directory. |
| |
|   **@property**<br>— **def [instance](/recipe_modules/cas/api.py#20)(self):** |
| |
| — **def [viewer\_url](/recipe_modules/cas/api.py#85)(self, digest):** |
| |
| Return URL of cas viewer. |
| ### *recipe_modules* / [cas\_input](/recipe_modules/cas_input) |
| |
| [DEPS](/recipe_modules/cas_input/__init__.py#9): [cas](#recipe_modules-cas), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Simple API for handling CAS inputs to a recipe. |
| |
| Recipes sometimes need files as part of their execution which don't live in |
| source control (for example, they're generated elsewhere but tested in the |
| recipe). In that case, there needs to be an easy way to give these files as an |
| input to a recipe, so that the recipe can use them somehow. This module makes |
| this easy. |
| |
| This module has input properties which contains a list of CAS inputs to |
| download. These can easily be download to disk with the 'download_caches' |
| method, and subsequently used by a recipe in whatever relevant manner. |
| |
| #### **class [CasInputApi](/recipe_modules/cas_input/api.py#20)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| A module for downloading CAS inputs to a recipe. |
| |
| — **def [download\_caches](/recipe_modules/cas_input/api.py#32)(self, output_dir, caches=None):** |
| |
| Downloads RBE-CAS caches and puts them in a given directory. |
| |
| Args: |
| output_dir: The output directory to download the caches to. If you're |
| unsure of what directory to use, self.m.path['start_dir'] is a directory |
| the recipe engine sets up for you that you can use. |
| caches: A CasCache proto message containing the caches which should be |
| downloaded. See properties.proto for the message definition. |
| If unset, it uses the caches in this recipe module properties. |
| Returns: |
| The output directory as a Path object which contains all the cache data. |
| |
|   **@property**<br>— **def [input\_caches](/recipe_modules/cas_input/api.py#28)(self):** |
| ### *recipe_modules* / [change\_verifier](/recipe_modules/change_verifier) |
| |
| [DEPS](/recipe_modules/change_verifier/__init__.py#7): [proto](#recipe_modules-proto), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Recipe API for LUCI Change Verifier. |
| |
| LUCI Change Verifier is the pre-commit verification service that will replace |
| CQ daemon. See: |
| https://chromium.googlesource.com/infra/luci/luci-go/+/HEAD/cv |
| |
| This recipe module depends on the prpc binary being available in $PATH: |
| https://godoc.org/go.chromium.org/luci/grpc/cmd/prpc |
| |
| his recipe module depends on experimental API provided by LUCI CV and may |
| subject to change in the future. Please reach out to the LUCI team first if you |
| want to use this recipe module; file a ticket at: |
| https://bugs.chromium.org/p/chromium/issues/entry?components=Infra%3ELUCI%3EBuildService%3EPresubmit%3ECV |
| |
| #### **class [ChangeVerifierApi](/recipe_modules/change_verifier/api.py#28)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| This module provides recipe API of LUCI Change Verifier. |
| |
| — **def [search\_runs](/recipe_modules/change_verifier/api.py#34)(self, project, cls=None, limit=None, step_name=None, dev=False):** |
| |
| Searches for Runs. |
| |
| Args: |
| * project: LUCI project name. |
| * cls (list[tuple[str, int]]|tuple[str, int]|None): CLs, specified as |
| (host, change number) tuples. A single tuple may also be passed. All |
| Runs returned must include all of the given CLs, and Runs may also |
| contain other CLs. |
| * limit (int): max number of Runs to return. Defaults to 32. |
| * step_name (string): optional custom step name in RPC steps. |
| * dev (bool): whether to use the dev instance of Change Verifier. |
| |
| Returns: |
| A list of CV Runs ordered newest to oldest that match the given criteria. |
| ### *recipe_modules* / [cipd](/recipe_modules/cipd) |
| |
| [DEPS](/recipe_modules/cipd/__init__.py#7): [context](#recipe_modules-context), [file](#recipe_modules-file), [futures](#recipe_modules-futures), [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step), [url](#recipe_modules-url) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| API for interacting with CIPD. |
| |
| Depends on 'cipd' binary available in PATH: |
| https://godoc.org/go.chromium.org/luci/cipd/client/cmd/cipd |
| |
| #### **class [CIPDApi](/recipe_modules/cipd/api.py#265)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| CIPDApi provides basic support for CIPD. |
| |
| This assumes that `cipd` (or `cipd.exe` or `cipd.bat` on windows) has been |
| installed somewhere in $PATH. |
| |
| Attributes: |
| * max_threads (int) - Number of worker threads for extracting packages. |
| If 0, uses CPU count. |
| |
| — **def [acl\_check](/recipe_modules/cipd/api.py#358)(self, pkg_path, reader=True, writer=False, owner=False):** |
| |
| Checks whether the caller has a given roles in a package. |
| |
| Args: |
| * pkg_path (str) - The package subpath. |
| * reader (bool) - Check for READER role. |
| * writer (bool) - Check for WRITER role. |
| * owner (bool) - Check for OWNER role. |
| |
| Returns True if the caller has given roles, False otherwise. |
| |
| — **def [add\_instance\_link](/recipe_modules/cipd/api.py#619)(self, step_result):** |
| |
| — **def [build](/recipe_modules/cipd/api.py#453)(self, input_dir, output_package, package_name, compression_level=None, install_mode=None, preserve_mtime=False, preserve_writable=False):** |
| |
| Builds, but does not upload, a cipd package from a directory. |
| |
| Args: |
| * input_dir (Path) - The directory to build the package from. |
| * output_package (Path) - The file to write the package to. |
| * package_name (str) - The name of the cipd package as it would appear |
| when uploaded to the cipd package server. |
| * compression_level (None|[0-9]) - Deflate compression level. If None, |
| defaults to 5 (0 - disable, 1 - best speed, 9 - best compression). |
| * install_mode (None|'copy'|'symlink') - The mechanism that the cipd |
| client should use when installing this package. If None, defaults to the |
| platform default ('copy' on windows, 'symlink' on everything else). |
| * preserve_mtime (bool) - Preserve file's modification time. |
| * preserve_writable (bool) - Preserve file's writable permission bit. |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [build\_from\_pkg](/recipe_modules/cipd/api.py#433)(self, pkg_def, output_package, compression_level=None):** |
| |
| Builds a package based on a PackageDefinition object. |
| |
| Args: |
| * pkg_def (PackageDefinition) - The description of the package we want to |
| create. |
| * output_package (Path) - The file to write the package to. |
| * compression_level (None|[0-9]) - Deflate compression level. If None, |
| defaults to 5 (0 - disable, 1 - best speed, 9 - best compression). |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [build\_from\_yaml](/recipe_modules/cipd/api.py#407)(self, pkg_def, output_package, pkg_vars=None, compression_level=None):** |
| |
| Builds a package based on on-disk YAML package definition file. |
| |
| Args: |
| * pkg_def (Path) - The path to the yaml file. |
| * output_package (Path) - The file to write the package to. |
| * pkg_vars (dict[str]str) - A map of var name -> value to use for vars |
| referenced in package definition file. |
| * compression_level (None|[0-9]) - Deflate compression level. If None, |
| defaults to 5 (0 - disable, 1 - best speed, 9 - best compression). |
| |
| Returns the CIPDApi.Pin instance. |
| |
|   **@contextlib.contextmanager**<br>— **def [cache\_dir](/recipe_modules/cipd/api.py#331)(self, directory):** |
| |
| Sets the cache dir to use with CIPD by setting the $CIPD_CACHE_DIR |
| environment variable. |
| |
| If directory is "None", will use no cache directory. |
| |
| — **def [create\_from\_pkg](/recipe_modules/cipd/api.py#663)(self, pkg_def, refs=None, tags=None, metadata=None, compression_level=None, verification_timeout=None):** |
| |
| Builds and uploads a package based on a PackageDefinition object. |
| |
| This builds and uploads the package in one step. |
| |
| Args: |
| * pkg_def (PackageDefinition) - The description of the package we want to |
| create. |
| * refs (list[str]) - A list of ref names to set for the package instance. |
| * tags (dict[str]str) - A map of tag name -> value to set for the |
| package instance. |
| * metadata (list[Metadata]) - A list of metadata entries to attach. |
| * compression_level (None|[0-9]) - Deflate compression level. If None, |
| defaults to 5 (0 - disable, 1 - best speed, 9 - best compression). |
| * verification_timeout (str) - Duration string that controls the time to |
| wait for backend-side package hash verification. Valid time units are |
| "s", "m", "h". Default is "5m". |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [create\_from\_yaml](/recipe_modules/cipd/api.py#625)(self, pkg_def, refs=None, tags=None, metadata=None, pkg_vars=None, compression_level=None, verification_timeout=None):** |
| |
| Builds and uploads a package based on on-disk YAML package definition |
| file. |
| |
| This builds and uploads the package in one step. |
| |
| Args: |
| * pkg_def (Path) - The path to the yaml file. |
| * refs (list[str]) - A list of ref names to set for the package instance. |
| * tags (dict[str]str) - A map of tag name -> value to set for the |
| package instance. |
| * metadata (list[Metadata]) - A list of metadata entries to attach. |
| * pkg_vars (dict[str]str) - A map of var name -> value to use for vars |
| referenced in package definition file. |
| * compression_level (None|[0-9]) - Deflate compression level. If None, |
| defaults to 5 (0 - disable, 1 - best speed, 9 - best compression). |
| * verification_timeout (str) - Duration string that controls the time to |
| wait for backend-side package hash verification. Valid time units are |
| "s", "m", "h". Default is "5m". |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [describe](/recipe_modules/cipd/api.py#882)(self, package_name, version, test_data_refs=None, test_data_tags=None):** |
| |
| Returns information about a package instance given its version: |
| who uploaded the instance and when and a list of attached tags. |
| |
| Args: |
| * package_name (str) - The name of the cipd package. |
| * version (str) - The package version to point the ref to. |
| * test_data_refs (seq[str]) - The list of refs for this call to return |
| by default when in test mode. |
| * test_data_tags (seq[str]) - The list of tags (in 'name:val' form) for |
| this call to return by default when in test mode. |
| |
| Returns the CIPDApi.Description instance describing the package. |
| |
| — **def [ensure](/recipe_modules/cipd/api.py#698)(self, root, ensure_file, name='ensure_installed'):** |
| |
| Ensures that packages are installed in a given root dir. |
| |
| Args: |
| * root (Path) - Path to installation site root directory. |
| * ensure_file (EnsureFile|Path) - List of packages to install. |
| * name (str) - Step display name. |
| |
| Returns the map of subdirectories to CIPDApi.Pin instances. |
| |
| — **def [ensure\_file\_resolve](/recipe_modules/cipd/api.py#740)(self, ensure_file, name='cipd ensure-file-resolve'):** |
| |
| Resolves versions of all packages for all verified platforms in an |
| ensure file. |
| |
| Args: |
| * ensure_file (EnsureFile|Path) - Ensure file to resolve. |
| |
| — **def [ensure\_tool](/recipe_modules/cipd/api.py#1008)(self, package, version, executable_path=None):** |
| |
| Downloads an executable from CIPD. |
| |
| Given a package named "name/of/some_exe/${platform}" and version |
| "someversion", this will install the package at the directory |
| "[START_DIR]/cipd_tool/name/of/some_exe/someversion". It will then return the |
| absolute path to the executable within that directory. |
| |
| This operation is idempotent, and will only run steps to download the |
| package if it hasn't already been installed in the same build. |
| |
| Args: |
| * package (str) - The full name of the CIPD package. |
| * version (str) - The version of the package to download. |
| * executable_path (str|None) - The path within the package of the desired |
| executable. Defaults to the basename of the package (the final |
| non-variable component of the package name). Must use forward-slashes, |
| even on Windows. |
| |
| Returns a Path to the executable. |
| |
| Future-safe; Multiple concurrent calls for the same (package, version) will |
| block on a single ensure step. |
| |
|   **@property**<br>— **def [executable](/recipe_modules/cipd/api.py#343)(self):** |
| |
| — **def [instances](/recipe_modules/cipd/api.py#917)(self, package_name, limit=None):** |
| |
| Lists instances of a package, most recently uploaded first. |
| |
| Args: |
| * package_name (str) - The name of the cipd package. |
| * limit (None|int) - The number of instances to return. 0 for all. |
| If None, default value of 'cipd' binary will be used (20). |
| |
| Returns the list of CIPDApi.Instance instance. |
| |
| — **def [pkg\_deploy](/recipe_modules/cipd/api.py#984)(self, root, package_file):** |
| |
| Deploys the specified package to root. |
| |
| ADVANCED METHOD: You shouldn't need this unless you're doing advanced |
| things with CIPD. Typically you should use the `ensure` method here to |
| fetch+install packages to the disk. |
| |
| Args: |
| * package_file (Path) - Path to a package file to install. |
| * root (Path) - Path to a CIPD root. |
| |
| Returns a Pin for the deployed package. |
| |
| — **def [pkg\_fetch](/recipe_modules/cipd/api.py#954)(self, destination, package_name, version):** |
| |
| Downloads the specified package to destination. |
| |
| ADVANCED METHOD: You shouldn't need this unless you're doing advanced things |
| with CIPD. Typically you should use the `ensure` method here to |
| fetch+install packages to the disk. |
| |
| Args: |
| * destination (Path) - Path to a file location which will be (over)written |
| with the package file contents. |
| * package_name (str) - The package name (or pattern with e.g. |
| ${platform}) |
| * version (str) - The CIPD version to fetch |
| |
| Returns a Pin for the downloaded package. |
| |
| — **def [register](/recipe_modules/cipd/api.py#549)(self, package_name, package_path, refs=None, tags=None, metadata=None, verification_timeout=None):** |
| |
| Uploads and registers package instance in the package repository. |
| |
| Args: |
| * package_name (str) - The name of the cipd package. |
| * package_path (Path) - The path to package instance file. |
| * refs (list[str]) - A list of ref names to set for the package instance. |
| * tags (dict[str]basestring) - A map of tag name -> value to set for the |
| package instance. |
| * metadata (list[Metadata]) - A list of metadata entries to attach. |
| * verification_timeout (str) - Duration string that controls the time to |
| wait for backend-side package hash verification. Valid time units are |
| "s", "m", "h". Default is "5m". |
| |
| Returns: |
| The CIPDApi.Pin instance. |
| |
| — **def [search](/recipe_modules/cipd/api.py#850)(self, package_name, tag, test_instances=None):** |
| |
| Searches for package instances by tag, optionally constrained by package |
| name. |
| |
| Args: |
| * package_name (str) - The name of the cipd package. |
| * tag (str) - The cipd package tag. |
| * test_instances (None|int|List[str]) - Default test data for this step: |
| * None - Search returns a single default pin. |
| * int - Search generates `test_instances` number of testing ids |
| `instance_id_%d` and returns pins for those. |
| * List[str] - Returns pins for the given testing ids. |
| |
| Returns the list of CIPDApi.Pin instances. |
| |
| — **def [set\_metadata](/recipe_modules/cipd/api.py#798)(self, package_name, version, metadata):** |
| |
| Attaches metadata to a package instance. |
| |
| Args: |
| * package_name (str) - The name of the cipd package. |
| * version (str) - The package version to attach metadata to. |
| * metadata (list[Metadata]) - A list of metadata entries to attach. |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [set\_ref](/recipe_modules/cipd/api.py#824)(self, package_name, version, refs):** |
| |
| Moves a ref to point to a given version. |
| |
| Args: |
| * package_name (str) - The name of the cipd package. |
| * version (str) - The package version to point the ref to. |
| * refs (list[str]) - A list of ref names to set for the package instance. |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [set\_tag](/recipe_modules/cipd/api.py#770)(self, package_name, version, tags):** |
| |
| Tags package of a specific version. |
| |
| Args: |
| * package_name (str) - The name of the cipd package. |
| * version (str) - The package version to resolve. Could also be itself a |
| tag or ref. |
| * tags (dict[str]str) - A map of tag name -> value to set for the |
| package instance. |
| |
| Returns the CIPDApi.Pin instance. |
| ### *recipe_modules* / [commit\_position](/recipe_modules/commit_position) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| #### **class [CommitPositionApi](/recipe_modules/commit_position/api.py#10)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| Recipe module providing commit position parsing and formatting. |
| |
|   **@classmethod**<br>— **def [format](/recipe_modules/commit_position/api.py#26)(cls, ref, revision_number):** |
| |
| Returns a commit position string. |
| |
| ref must start with 'refs/'. |
| |
|   **@classmethod**<br>— **def [parse](/recipe_modules/commit_position/api.py#16)(cls, value):** |
| |
| Returns (ref, revision_number) tuple. |
| ### *recipe_modules* / [context](/recipe_modules/context) |
| |
| [DEPS](/recipe_modules/context/__init__.py#7): [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| The context module provides APIs for manipulating a few pieces of 'ambient' |
| data that affect how steps are run. |
| |
| The pieces of information which can be modified are: |
| * cwd - The current working directory. |
| * env - The environment variables. |
| * infra_step - Whether or not failures should be treated as infrastructure |
| failures vs. normal failures. |
| |
| The values here are all scoped using Python's `with` statement; there's no |
| mechanism to make an open-ended adjustment to these values (i.e. there's no way |
| to change the cwd permanently for a recipe, except by surrounding the entire |
| recipe with a with statement). This is done to avoid the surprises that |
| typically arise with things like os.environ or os.chdir in a normal python |
| program. |
| |
| Example: |
| ```python |
| with api.context(cwd=api.path['start_dir'].join('subdir')): |
| # this step is run inside of the subdir directory. |
| api.step("cat subdir/foo", ['cat', './foo']) |
| ``` |
| |
| #### **class [ContextApi](/recipe_modules/context/api.py#80)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
|   **@contextmanager**<br>— **def [\_\_call\_\_](/recipe_modules/context/api.py#112)(self, cwd=None, env_prefixes=None, env_suffixes=None, env=None, infra_steps=None, luciexe=None, realm=None, deadline=None):** |
| |
| Allows adjustment of multiple context values in a single call. |
| |
| Args: |
| * cwd (Path) - the current working directory to use for all steps. |
| To 'reset' to the original cwd at the time recipes started, pass |
| `api.path['start_dir']`. |
| * env_prefixes (dict) - Environmental variable prefix augmentations. See |
| below for more info. |
| * env_suffixes (dict) - Environmental variable suffix augmentations. See |
| below for more info. |
| * env (dict) - Environmental variable overrides. See below for more info. |
| * infra_steps (bool) - if steps in this context should be considered |
| infrastructure steps. On failure, these will raise InfraFailure |
| exceptions instead of StepFailure exceptions. |
| * luciexe (sections_pb2.LUCIExe) - The override value for 'luciexe' |
| section in LUCI_CONTEXT. This is currently used to modify the |
| `cache_dir` for all launched LUCI Executable (via |
| `api.step.sub_build(...)`). |
| * realm (str) - allows changing the current LUCI realm. It is used when |
| creating new LUCI resources (e.g. spawning new Swarming tasks). Pass an |
| empty string to disassociate the context from a realm, emulating an |
| environment prior to LUCI realms. This is useful during the transitional |
| period. |
| * deadline (sections_pb2.Deadline) - Deadline information to set; See |
| LUCI_CONTEXT documentation for how this section works. Automatically |
| adjusted by steps with `timeout` set. |
| |
| Environmental Variable Overrides: |
| |
| Env is a mapping of environment variable name to the value you want that |
| environment variable to have. The value is one of: |
| * None, indicating that the environment variable should be removed from |
| the environment when the step runs. |
| * A string value. Note that string values will be %-formatted with the |
| current value of the environment at the time the step runs. This means |
| that you can have a value like: |
| "/path/to/my/stuff:%(PATH)s" |
| Which, at the time the step executes, will inject the current value of |
| $PATH. |
| |
| "env_prefix" and "env_suffix" are a list of Path or strings that get |
| prefixed (or suffixed) to their respective environment variables, delimited |
| with the system's path separator. This can be used to add entries to |
| environment variables such as "PATH" and "PYTHONPATH". If prefixes are |
| specified and a value is also defined in "env", the value will be installed |
| as the last path component if it is not empty. |
| |
| Look at the examples in "examples/" for examples of context module usage. |
| |
|   **@property**<br>— **def [cwd](/recipe_modules/context/api.py#255)(self):** |
| |
| Returns the current working directory that steps will run in. |
| |
| **Returns (Path|None)** - The current working directory. A value of None is |
| equivalent to api.path['start_dir'], though only occurs if no cwd has been |
| set (e.g. in the outermost context of RunSteps). |
| |
|   **@property**<br>— **def [deadline](/recipe_modules/context/api.py#348)(self):** |
| |
| Returns the current value (sections_pb2.Deadline) of deadline section in |
| the current LUCI_CONTEXT. Returns `{grace_period: 30}` if deadline is not |
| defined, per LUCI_CONTEXT spec. |
| |
|   **@property**<br>— **def [env](/recipe_modules/context/api.py#265)(self):** |
| |
| Returns modifications to the environment. |
| |
| By default this is empty. If you want to observe the program's startup |
| environment, see `ENV_PROPERTIES` in |
| https://chromium.googlesource.com/infra/luci/recipes-py/+/refs/heads/main/doc/user_guide.md#properties-and-env_properties |
| |
| **Returns (dict)** - The env-key -> value mapping of current environment |
| modifications. |
| |
|   **@property**<br>— **def [env\_prefixes](/recipe_modules/context/api.py#280)(self):** |
| |
| Returns Path prefix modifications to the environment. |
| |
| This will return a mapping of environment key to Path tuple for Path |
| prefixes registered with the environment. |
| |
| **Returns (dict)** - The env-key -> value(Path) mapping of current |
| environment prefix modifications. |
| |
|   **@property**<br>— **def [env\_suffixes](/recipe_modules/context/api.py#294)(self):** |
| |
| Returns Path suffix modifications to the environment. |
| |
| This will return a mapping of environment key to Path tuple for Path |
| suffixes registered with the environment. |
| |
| **Returns (dict)** - The env-key -> value(Path) mapping of current |
| environment suffix modifications. |
| |
|   **@property**<br>— **def [infra\_step](/recipe_modules/context/api.py#308)(self):** |
| |
| Returns the current value of the infra_step setting. |
| |
| **Returns (bool)** - True iff steps are currently considered infra steps. |
| |
| — **def [initialize](/recipe_modules/context/api.py#90)(self):** |
| |
|   **@property**<br>— **def [luci\_context](/recipe_modules/context/api.py#316)(self):** |
| |
| Returns the currently tracked LUCI_CONTEXT sections as a dict of proto |
| messages. |
| |
| Only contains `luciexe`, `realm`, 'resultdb' and `deadline`. |
| |
|   **@property**<br>— **def [luciexe](/recipe_modules/context/api.py#328)(self):** |
| |
| Returns the current value (sections_pb2.LUCIExe) of luciexe section in |
| the current LUCI_CONTEXT. Returns None if luciexe is not defined. |
| |
|   **@property**<br>— **def [realm](/recipe_modules/context/api.py#338)(self):** |
| |
| Returns the LUCI realm of the current context. |
| |
| May return None if the task is not running in the realm-aware mode. This is |
| a transitional period. Eventually all tasks will be associated with realms. |
| |
|   **@property**<br>— **def [resultdb\_invocation\_name](/recipe_modules/context/api.py#359)(self):** |
| |
| Returns the ResultDB invocation name of the current context. |
| |
| Returns None if resultdb is not defined. |
| ### *recipe_modules* / [cq](/recipe_modules/cq) |
| |
| [DEPS](/recipe_modules/cq/__init__.py#9): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Recipe API for LUCI CQ, the pre-commit testing system. |
| |
| #### **class [CQApi](/recipe_modules/cq/api.py#18)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| This module provides recipe API of LUCI CQ, aka pre-commit testing system. |
| |
| The CQ service is being replaced with a service now named LUCI Change |
| Verifier (CV); for more information see: |
| https://chromium.googlesource.com/infra/luci/luci-go/+/HEAD/cv |
| |
| TODO(qyearsley): Rename parts of this from CQ -> CV as appropriate. |
| |
|   **@property**<br>— **def [active](/recipe_modules/cq/api.py#52)(self):** |
| |
| Returns whether CQ is active for this build. |
| |
| — **def [allow\_reuse\_for](/recipe_modules/cq/api.py#223)(self, \*modes):** |
| |
| Instructs CQ that this build can be reused in a future Run if |
| and only if its mode is in the provided modes. |
| |
| Overwrites all previously set values. |
| |
|   **@property**<br>— **def [allowed\_reuse\_modes](/recipe_modules/cq/api.py#219)(self):** |
| |
|   **@property**<br>— **def [cl\_group\_key](/recipe_modules/cq/api.py#135)(self):** |
| |
| Returns a string that is unique for a current set of Gerrit change |
| patchsets (or, equivalently, buildsets). |
| |
| The same `cl_group_key` will be used if another Attempt is made for the |
| same set of changes at a different time. |
| |
| Raises: |
| CQInactive if CQ is not active for this build. |
| |
|   **@property**<br>— **def [do\_not\_retry\_build](/recipe_modules/cq/api.py#201)(self):** |
| |
|   **@property**<br>— **def [equivalent\_cl\_group\_key](/recipe_modules/cq/api.py#148)(self):** |
| |
| Returns a string that is unique for a given set of Gerrit changes |
| disregarding trivial patchset differences. |
| |
| For example, when a new "trivial" patchset is uploaded, then the |
| cl_group_key will change but the equivalent_cl_group_key will stay the same. |
| |
| Raises: |
| CQInactive if CQ is not active for this build. |
| |
|   **@property**<br>— **def [experimental](/recipe_modules/cq/api.py#67)(self):** |
| |
| Returns whether this build is triggered for a CQ experimental builder. |
| |
| See `Builder.experiment_percentage` doc in [CQ |
| config](https://chromium.googlesource.com/infra/luci/luci-go/+/main/cv/api/config/v2/config.proto) |
| |
| Raises: |
| CQInactive if CQ is not active for this build. |
| |
| — **def [initialize](/recipe_modules/cq/api.py#42)(self):** |
| |
|   **@property**<br>— **def [ordered\_gerrit\_changes](/recipe_modules/cq/api.py#92)(self):** |
| |
| Returns list[bb_common_pb2.GerritChange] in order in which CLs should be |
| applied or submitted. |
| |
| Raises: |
| CQInactive if CQ is not active for this build. |
| |
|   **@property**<br>— **def [props\_for\_child\_build](/recipe_modules/cq/api.py#106)(self):** |
| |
| Returns properties dict meant to be passed to child builds. |
| |
| These will preserve the CQ context of the current build in the |
| about-to-be-triggered child build. |
| |
| ```python |
| properties = {'foo': bar, 'protolike': proto_message} |
| properties.update(api.cq.props_for_child_build) |
| req = api.buildbucket.schedule_request( |
| builder='child', |
| gerrit_changes=list(api.buildbucket.build.input.gerrit_changes), |
| properties=properties) |
| child_builds = api.buildbucket.schedule([req]) |
| api.cq.record_triggered_builds(*child_builds) |
| ``` |
| |
| The contents of returned dict should be treated as opaque blob, |
| it may be changed without notice. |
| |
| — **def [record\_triggered\_build\_ids](/recipe_modules/cq/api.py#183)(self, \*build_ids):** |
| |
| Adds given Buildbucket build ids to the list of triggered builds for CQ |
| to wait on corresponding build completion later. |
| |
| Must be called after some step. |
| |
| Args: |
| * build_id (int or string): Buildbucket build id. |
| |
| — **def [record\_triggered\_builds](/recipe_modules/cq/api.py#166)(self, \*builds):** |
| |
| Adds given Buildbucket builds to the list of triggered builds for CQ |
| to wait on corresponding build completion later. |
| |
| Must be called after some step. |
| |
| Expected usage: |
| ```python |
| api.cq.record_triggered_builds(*api.buildbucket.schedule([req1, req2])) |
| ``` |
| |
| Args: |
| * [`Build`](https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/build.proto) |
| objects, typically returned by `api.buildbucket.schedule`. |
| |
|   **@property**<br>— **def [run\_mode](/recipe_modules/cq/api.py#57)(self):** |
| |
| Returns the mode(str) of the CQ Run that triggers this build. |
| |
| Raises: |
| CQInactive if CQ is not active for this build. |
| |
| — **def [set\_do\_not\_retry\_build](/recipe_modules/cq/api.py#205)(self):** |
| |
| Instruct CQ to not retry this build. |
| |
| This mechanism is used to reduce duration of CQ attempt and save testing |
| capacity if retrying will likely return an identical result. |
| |
|   **@property**<br>— **def [top\_level](/recipe_modules/cq/api.py#80)(self):** |
| |
| Returns whether CQ triggered this build directly. |
| |
| Can be spoofed. *DO NOT USE FOR SECURITY CHECKS.* |
| |
| Raises: |
| CQInactive if CQ is not active for this build. |
| |
|   **@property**<br>— **def [triggered\_build\_ids](/recipe_modules/cq/api.py#161)(self):** |
| |
| Returns recorded Buildbucket build IDs as a list of integers. |
| ### *recipe_modules* / [file](/recipe_modules/file) |
| |
| [DEPS](/recipe_modules/file/__init__.py#7): [json](#recipe_modules-json), [path](#recipe_modules-path), [proto](#recipe_modules-proto), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| File manipulation (read/write/delete/glob) methods. |
| |
| #### **class [FileApi](/recipe_modules/file/api.py#85)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| — **def [compute\_hash](/recipe_modules/file/api.py#214)(self, name, paths, base_path, test_data=''):** |
| |
| Computes hash of contents of a directory/file. |
| |
| This function will compute hash by including following info of a file: |
| * str(len(path)) // path is relative to base_path |
| * path // path is relative to base_path |
| * str(len(file)) |
| * file_content |
| |
| Each of these components are separated by a newline character. For example, |
| for file = "hello" and the contents "world" the hash would be over: |
| ``` |
| 5 |
| |
| hello |
| |
| 5 |
| |
| world |
| |
| ``` |
| |
| Args: |
| * name (str): The name of the step. |
| * paths (list[Path|str]): Path of directory/file(s) to compute hash. |
| * base_path (Path|str): Base directory to calculating hash relative to |
| absolute path. For e.g. `start_dir` of a recipe execution can be used. |
| * test_data (str): Some default data for this step to return when running |
| under simulation. If no test data is provided, we compute test_data as |
| sha256 of concatenated relative paths passed. |
| |
| Returns (str): |
| Hex encoded hash of directory/file content. |
| |
| Raises: |
| file.Error and ValueError if passed paths input is not str or Path. |
| |
| — **def [copy](/recipe_modules/file/api.py#126)(self, name, source, dest):** |
| |
| Copies a file (including mode bits) from source to destination on the |
| local filesystem. |
| |
| Behaves identically to shutil.copy. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path|Placeholder): The path to the file you want to copy. |
| * dest (Path|Placeholder): The path to the destination file name. If this |
| path exists and is a directory, the basename of `source` will be |
| appended to derive a path to a destination file. |
| |
| Raises: file.Error |
| |
| — **def [copytree](/recipe_modules/file/api.py#146)(self, name, source, dest, symlinks=False):** |
| |
| Recursively copies a directory tree. |
| |
| Behaves identically to shutil.copytree. |
| `dest` must not exist. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The path of the directory to copy. |
| * dest (Path): The place where you want the recursive copy to show up. |
| This must not already exist. |
| * symlinks (bool): Preserve symlinks. No effect on Windows. |
| |
| Raises: file.Error |
| |
| — **def [ensure\_directory](/recipe_modules/file/api.py#541)(self, name, dest, mode=511):** |
| |
| Ensures that `dest` exists and is a directory. |
| |
| Args: |
| * name (str): The name of the step. |
| * dest (Path): The directory to ensure. |
| * mode (int): The mode to use if the directory doesn't exist. This method |
| does not ensure the mode if the directory already exists (if you need |
| that behaviour, file a bug). |
| |
| Raises: file.Error if the path exists but is not a directory. |
| |
| — **def [file\_hash](/recipe_modules/file/api.py#185)(self, file_path, test_data=''):** |
| |
| Computes hash of contents of a single file. |
| |
| Args: |
| * file_path (Path|str): Path of file to compute hash. |
| * test_data (str): Some default data for this step to return when running |
| under simulation. If no test data is provided, we compute test_data as |
| sha256 of path passed. |
| |
| Returns (str): |
| Hex encoded hash of file content. |
| |
| Raises: |
| file.Error and ValueError if passed paths input is not str or Path. |
| |
| — **def [filesizes](/recipe_modules/file/api.py#557)(self, name, files, test_data=None):** |
| |
| Returns list of filesizes for the given files. |
| |
| Args: |
| * name (str): The name of the step. |
| * files (list[Path]): Paths to files. |
| |
| Returns list[int], size of each file in bytes. |
| |
| — **def [flatten\_single\_directories](/recipe_modules/file/api.py#697)(self, name, path):** |
| |
| Flattens singular directories, starting at path. |
| |
| Example: |
| |
| $ mkdir -p dir/which_has/some/singular/subdirs/ |
| $ touch dir/which_has/some/singular/subdirs/with |
| $ touch dir/which_has/some/singular/subdirs/files |
| $ flatten_single_directories(dir) |
| $ ls dir |
| with |
| files |
| |
| This can be useful when you just want the 'meat' of a very sparse directory |
| structure. For example, some tarballs like `foo-1.2.tar.gz` extract all |
| their contents into a subdirectory `foo-1.2/`. |
| |
| Using this function would essentially move all the actual contents of the |
| extracted archive up to the top level directory, removing the need to e.g. |
| hard-code/find the subfolder name after extraction (not all archives are |
| even named after the subfolder they extract to). |
| |
| Args: |
| * name (str): The name of the step. |
| * path (Path|str): The absolute path to begin flattening. |
| |
| Raises: file.Error |
| |
| — **def [glob\_paths](/recipe_modules/file/api.py#449)(self, name, source, pattern, include_hidden=False, test_data=()):** |
| |
| Performs glob expansion on `pattern`. |
| |
| glob rules for `pattern` follow the same syntax as for the `python-glob2` |
| module, which supports '**' syntax. |
| |
| ``` |
| e.g. 'a/**/*.py' |
| |
| a/b/foo.py => MATCH |
| a/b/c/foo.py => MATCH |
| a/foo.py => MATCH |
| a/b/c/d/e/f/g/h/i/j/foo.py => MATCH |
| other/foo.py => NO MATCH |
| ``` |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The directory whose contents should be globbed. |
| * pattern (str): The glob pattern to apply under `source`. |
| * include_hidden (bool): Include files beginning with `.`. |
| * test_data (iterable[str]): Some default data for this step to return |
| when running under simulation. This should be the list of file items |
| found in this directory. |
| |
| Returns (list[Path]): All paths found. |
| |
| Raises: file.Error. |
| |
| — **def [listdir](/recipe_modules/file/api.py#511)(self, name, source, recursive=False, test_data=()):** |
| |
| Lists all files inside a directory. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The directory to list. |
| * recursive (bool): If True, do not emit subdirectory entries but recurse |
| into them instead, emitting paths relative to `source`. Doesn't follow |
| symlinks. Very slow for large directories. |
| * test_data (iterable[str]): Some default data for this step to return |
| when running under simulation. This should be the list of relative paths |
| found in this directory. |
| |
| Returns list[Path] |
| |
| Raises: file.Error. |
| |
| — **def [move](/recipe_modules/file/api.py#167)(self, name, source, dest):** |
| |
| Moves a file or directory. |
| |
| Behaves identically to shutil.move. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The path of the item to move. |
| * dest (Path): The new name of the item. |
| |
| Raises: file.Error |
| |
| — **def [read\_json](/recipe_modules/file/api.py#341)(self, name, source, test_data='', include_log=True):** |
| |
| Reads a file as UTF-8 encoded json. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The path of the file to read. |
| * test_data (object): Some default json serializable data for this step |
| to return when running under simulation. |
| * include_log (bool): Include step log of read json. |
| |
| Returns (object): The content of the file. |
| |
| Raise file.Error |
| |
| — **def [read\_proto](/recipe_modules/file/api.py#377)(self, name, source, msg_class, codec, test_proto=None, include_log=True, encoding_kwargs=None):** |
| |
| Reads a file into a proto message. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The path of the file to read. |
| * msg_class (protobuf Message subclass): The message type to be read. |
| * codec ('BINARY'|'JSONPB'|'TEXTPB'): The encoder to use. |
| * test_proto (protobuf Message): A default proto message for this step to |
| return when running under simulation. |
| * include_log (bool): Include step log of read proto. |
| * encoding_kwargs (dict): Passed directly to the chosen encoder. See proto |
| module for details. |
| |
| — **def [read\_raw](/recipe_modules/file/api.py#265)(self, name, source, test_data=''):** |
| |
| Reads a file as raw data. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The path of the file to read. |
| * test_data (str): Some default data for this step to return when running |
| under simulation. |
| |
| Returns (str): The unencoded (binary) contents of the file. |
| |
| Raises: file.Error |
| |
| — **def [read\_text](/recipe_modules/file/api.py#299)(self, name, source, test_data='', include_log=True):** |
| |
| Reads a file as UTF-8 encoded text. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The path of the file to read. |
| * test_data (str): Some default data for this step to return when running |
| under simulation. |
| * include_log (bool): Include step log of read text. |
| |
| Returns (str): The content of the file. |
| |
| Raises: file.Error |
| |
| — **def [remove](/recipe_modules/file/api.py#496)(self, name, source):** |
| |
| Removes a file. |
| |
| Does not raise Error if the file doesn't exist. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The file to remove. |
| |
| Raises: file.Error. |
| |
| — **def [rmcontents](/recipe_modules/file/api.py#596)(self, name, source):** |
| |
| Similar to rmtree, but removes only contents not the directory. |
| |
| This is useful e.g. when removing contents of current working directory. |
| Deleting current working directory makes all further getcwd calls fail |
| until chdir is called. chdir would be tricky in recipes, so we provide |
| a call that doesn't delete the directory itself. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The directory whose contents should be removed. |
| |
| Raises: file.Error. |
| |
| — **def [rmglob](/recipe_modules/file/api.py#614)(self, name, source, pattern, recursive=True, include_hidden=True):** |
| |
| Removes all entries in `source` matching the glob `pattern`. |
| |
| glob rules for `pattern` follow the same syntax as for the `python-glob2` |
| module, which supports '**' syntax. |
| |
| ``` |
| e.g. 'a/**/*.py' |
| |
| a/b/foo.py => MATCH |
| a/b/c/foo.py => MATCH |
| a/foo.py => MATCH |
| a/b/c/d/e/f/g/h/i/j/foo.py => MATCH |
| other/foo.py => NO MATCH |
| ``` |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The directory whose contents should be filtered and |
| removed. |
| * pattern (str): The glob pattern to apply under `source`. Anything |
| matching this pattern will be removed. |
| * recursive (bool): Recursively remove entries under `source`. |
| TODO: Remove this option. Use `**` syntax instead. |
| * include_hidden (bool): Include files beginning with `.`. |
| TODO: Set to False by default to be consistent with file.glob. |
| |
| Raises: file.Error. |
| |
| — **def [rmtree](/recipe_modules/file/api.py#579)(self, name, source):** |
| |
| Recursively removes a directory. |
| |
| This uses a native python on Linux/Mac, and uses `rd` on Windows to avoid |
| issues w.r.t. path lengths and read-only attributes. If the directory is |
| gone already, this returns without error. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path): The directory to remove. |
| |
| Raises: file.Error. |
| |
| — **def [symlink](/recipe_modules/file/api.py#659)(self, name, source, linkname):** |
| |
| Creates a symlink on the local filesystem. |
| |
| Behaves identically to os.symlink. |
| |
| Args: |
| * name (str): The name of the step. |
| * source (Path|Placeholder): The path to link from. |
| * linkname (Path|Placeholder): The destination to link to. |
| |
| Raises: file.Error |
| |
| — **def [symlink\_tree](/recipe_modules/file/api.py#676)(self, root):** |
| |
| Creates a SymlinkTree, given a root directory. |
| |
| Args: |
| * root (Path): root of a tree of symlinks. |
| |
| — **def [truncate](/recipe_modules/file/api.py#684)(self, name, path, size_mb=100):** |
| |
| Creates an empty file with path and size_mb on the local filesystem. |
| |
| Args: |
| * name (str): The name of the step. |
| * path (Path|str): The absolute path to create. |
| * size_mb (int): The size of the file in megabytes. Defaults to 100 |
| |
| Raises: file.Error |
| |
| — **def [write\_json](/recipe_modules/file/api.py#361)(self, name, dest, data, indent=None, include_log=True):** |
| |
| Write the given json serializable `data` to `dest`. |
| |
| Args: |
| * name (str): The name of the step. |
| * dest (Path): The path of the file to write. |
| * data (object): Json serializable data to write. |
| * indent (None|int|str): The indent of the written JSON. See |
| https://docs.python.org/3/library/json.html#json.dump for more details. |
| * include_log (bool): Include step log of written json. |
| |
| Raises: file.Error. |
| |
| — **def [write\_proto](/recipe_modules/file/api.py#418)(self, name, dest, proto_msg, codec, include_log=True, encoding_kwargs=None):** |
| |
| Writes the given proto message to `dest`. |
| |
| Args: |
| * name (str): The name of thhe step. |
| * dest (Path): The path of the file to write. |
| * proto_msg (protobuf Message): Message to write. |
| * codec ('BINARY'|'JSONPB'|'TEXTPB'): The encoder to use. |
| * include_log (bool): Include step log of written proto. |
| * encoding_kwargs (dict): Passed directly to the chosen encoder. See |
| proto module for details. |
| |
| — **def [write\_raw](/recipe_modules/file/api.py#285)(self, name, dest, data):** |
| |
| Write the given `data` to `dest`. |
| |
| Args: |
| * name (str): The name of the step. |
| * dest (Path): The path of the file to write. |
| * data (str): The data to write. |
| |
| Raises: file.Error. |
| |
| — **def [write\_text](/recipe_modules/file/api.py#323)(self, name, dest, text_data, include_log=True):** |
| |
| Write the given UTF-8 encoded `text_data` to `dest`. |
| |
| Args: |
| * name (str): The name of the step. |
| * dest (Path): The path of the file to write. |
| * text_data (str): The UTF-8 encoded data to write. |
| * include_log (bool): Include step log of written text. |
| |
| Raises: file.Error. |
| ### *recipe_modules* / [futures](/recipe_modules/futures) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Implements in-recipe concurrency via green threads. |
| |
| #### **class [FuturesApi](/recipe_modules/futures/api.py#43)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| Provides access to the Recipe concurrency primitives. |
| |
|   **@staticmethod**<br>— **def [iwait](/recipe_modules/futures/api.py#306)(futures, timeout=None, count=None):** |
| |
| Iteratively yield up to `count` Futures as they become done. |
| |
| |
| This is analogous to `gevent.iwait`. |
| |
| Usage: |
| |
| for future in api.futures.iwait(futures): |
| # consume future |
| |
| If you are not planning to consume the entire iwait iterator, you can |
| avoid the resource leak by doing, for example: |
| |
| with api.futures.iwait(a, b, c) as iter: |
| for future in iter: |
| if future is a: |
| break |
| |
| You might want to use `iwait` over `wait` if you want to process a group |
| of Futures in the order in which they complete. Compare: |
| |
| for task in iwait(swarming_tasks): |
| # task is done, do something with it |
| |
| vs |
| |
| while swarming_tasks: |
| task = wait(swarming_tasks, count=1)[0] # some task is done |
| swarming_tasks.remove(task) |
| # do something with it |
| |
| Args: |
| * futures (List[Future]) - The Future objects to wait for. |
| * timeout (None|seconds) - How long to wait for the Futures to be done. |
| * count (None|int) - The number of Futures to yield. If None, |
| yields all of them. |
| |
| Yields futures in the order in which they complete until we hit the |
| timeout or count. May also be used with a context manager to avoid |
| leaking resources if you don't plan on consuming the entire iterable. |
| |
| — **def [make\_bounded\_semaphore](/recipe_modules/futures/api.py#155)(self, value=1):** |
| |
| Returns a gevent.BoundedSemaphore with depth `value`. |
| |
| This can be used as a context-manager to create concurrency-limited sections |
| like: |
| |
| def worker(api, sem, i): |
| with api.step.nest('worker %d' % i): |
| with sem: |
| api.step('one at a time', ...) |
| |
| api.step('unrestricted concurrency' , ...) |
| |
| sem = api.future.make_semaphore() |
| for i in xrange(100): |
| api.futures.spawn(fn, sem, i) |
| |
| *** promo |
| NOTE: If you use the BoundedSemaphore without the context-manager syntax, it |
| could lead to difficult-to-debug deadlocks in your recipe. |
| *** |
| |
| *** promo |
| NOTE: This method will raise ValueError if used with @@@annotation@@@ mode. |
| *** |
| |
| — **def [make\_channel](/recipe_modules/futures/api.py#182)(self):** |
| |
| Returns a single-slot communication device for passing data and control |
| between concurrent functions. |
| |
| This is useful for running 'background helper' type concurrent processes. |
| |
| *** promo |
| NOTE: It is strongly discouraged to pass Channel objects outside of a recipe |
| module. Access to the channel should be mediated via |
| a class/contextmanager/function which you return to the caller, and the |
| caller can call in a makes-sense-for-your-moudle's-API way. |
| *** |
| |
| See ./tests/background_helper.py for an example of how to use a Channel |
| correctly. |
| |
| It is VERY RARE to need to use a Channel. You should avoid using this unless |
| you carefully consider and avoid the possibility of introducing deadlocks. |
| |
| *** promo |
| NOTE: This method will raise ValueError if used with @@@annotation@@@ mode. |
| *** |
| |
|   **@escape_all_warnings**<br>— **def [spawn](/recipe_modules/futures/api.py#206)(self, func, \*args, \*\*kwargs):** |
| |
| Prepares a Future to run `func(*args, **kwargs)` concurrently. |
| |
| Any steps executed in `func` will only have manipulable StepPresentation |
| within the scope of the executed function. |
| |
| Because this will spawn a greenlet on the same OS thread (and not, |
| for example a different OS thread or process), `func` can easily be an |
| inner function, closure, lambda, etc. In particular, func, args and kwargs |
| do not need to be pickle-able. |
| |
| This function does NOT switch to the greenlet (you'll have to block on a |
| future/step for that to happen). In particular, this means that the |
| following pattern is safe: |
| |
| # self._my_future check + spawn + assignment is atomic because |
| # no switch points occur. |
| if not self._my_future: |
| self._my_future = api.futures.spawn(func) |
| |
| *** promo |
| NOTE: If used in @@@annotator@@@ mode, this will block on the completion of |
| the Future before returning it. |
| *** |
| |
| Kwargs: |
| |
| * __name (str) - If provided, will assign this name to the spawned |
| greenlet. Useful if this greenlet ends up raising an exception, this |
| name will appear in the stderr logging for the engine. See |
| `Future.name` for more information. |
| * __meta (any) - If provided, will assign this metadata to the returned |
| Future. This field is for your exclusive use. |
| * Everything else is passed to `func`. |
| |
| Returns a Future of `func`'s result. |
| |
|   **@escape_all_warnings**<br>— **def [spawn\_immediate](/recipe_modules/futures/api.py#256)(self, func, \*args, \*\*kwargs):** |
| |
| Returns a Future to the concurrently running `func(*args, **kwargs)`. |
| |
| This is like `spawn`, except that it IMMEDIATELY switches to the new |
| Greenlet. You may want to use this if you want to e.g. launch a background |
| step and then another step which waits for the daemon. |
| |
| Kwargs: |
| |
| * __name (str) - If provided, will assign this name to the spawned |
| greenlet. Useful if this greenlet ends up raising an exception, this |
| name will appear in the stderr logging for the engine. See |
| `Future.name` for more information. |
| * __meta (any) - If provided, will assign this metadata to the returned |
| Future. This field is for your exclusive use. |
| * Everything else is passed to `func`. |
| |
| Returns a Future of `func`'s result. |
| |
|   **@staticmethod**<br>— **def [wait](/recipe_modules/futures/api.py#287)(futures, timeout=None, count=None):** |
| |
| Blocks until `count` `futures` are done (or timeout occurs) then |
| returns the list of done futures. |
| |
| This is analogous to `gevent.wait`. |
| |
| Args: |
| * futures (List[Future]) - The Future objects to wait for. |
| * timeout (None|seconds) - How long to wait for the Futures to be done. |
| If we hit the timeout, wait will return even if we haven't reached |
| `count` Futures yet. |
| * count (None|int) - The number of Futures to wait to be done. If None, |
| waits for all of them. |
| |
| Returns the list of done Futures, in the order in which they were done. |
| ### *recipe_modules* / [generator\_script](/recipe_modules/generator_script) |
| |
| [DEPS](/recipe_modules/generator_script/__init__.py#7): [context](#recipe_modules-context), [json](#recipe_modules-json), [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| A simplistic method for running steps generated by an external script. |
| |
| This module was created before there was a way to put recipes directly into |
| another repo. It is not recommended to use this, and it will be removed in the |
| near future. |
| |
| #### **class [GeneratorScriptApi](/recipe_modules/generator_script/api.py#16)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| — **def [\_\_call\_\_](/recipe_modules/generator_script/api.py#44)(self, path_to_script, \*args):** |
| |
| Run a script and generate the steps emitted by that script. |
| |
| The script will be invoked with --output-json /path/to/file.json. The script |
| is expected to exit 0 and write steps into that file. Once the script |
| outputs all of the steps to that file, the recipe will read the steps from |
| that file and execute them in order. Any *args specified will be |
| additionally passed to the script. |
| |
| The step data is formatted as a list of JSON objects. Each object |
| corresponds to one step, and contains the following keys: |
| * name: the name of this step. |
| * cmd: a list of strings that indicate the command to run (e.g. argv) |
| * env: a {key:value} dictionary of the environment variables to override. |
| every value is formatted with the current environment with the python |
| % operator, so a value of "%(PATH)s:/some/other/path" would resolve to |
| the current PATH value, concatenated with ":/some/other/path" |
| * cwd: an absolute path to the current working directory for this script. |
| * always_run: a bool which indicates that this step should run, even if |
| some previous step failed. |
| * outputs_presentation_json: a bool which indicates that this step will |
| emit a presentation json file. If this is True, the cmd will be extended |
| with a `--presentation-json /path/to/file.json`. This file will be used |
| to update the step's presentation on the build status page. The file |
| will be expected to contain a single json object, with any of the |
| following keys: |
| * logs: {logname: [lines]} specifies one or more auxiliary logs. |
| * links: {link_name: link_content} to add extra links to the step. |
| * step_summary_text: A string to set as the step summary. |
| * step_text: A string to set as the step text. |
| * properties: {prop: value} build_properties to add to the build |
| status page. Note that these are write-only: The only way to read |
| them is via the status page. There is intentionally no mechanism to |
| read them back from inside of the recipes. |
| ### *recipe_modules* / [golang](/recipe_modules/golang) |
| |
| [DEPS](/recipe_modules/golang/__init__.py#7): [cipd](#recipe_modules-cipd), [context](#recipe_modules-context), [path](#recipe_modules-path), [platform](#recipe_modules-platform) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| #### **class [GolangApi](/recipe_modules/golang/api.py#10)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
|   **@contextlib.contextmanager**<br>— **def [\_\_call\_\_](/recipe_modules/golang/api.py#15)(self, version, path=None, cache=None):** |
| |
| Installs a Golang SDK and activates it in the environment. |
| |
| Installs it under the given `path`, defaulting to `[CACHE]/golang`. Various |
| cache directories used by Go are placed under `cache`, defaulting to |
| `[CACHE]/gocache`. |
| |
| `version` will be used to construct CIPD package version for packages under |
| https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/go/. |
| |
| To reuse the Go SDK deployment and caches across builds, declare the |
| corresponding named caches in Buildbucket configs. E.g. when using defaults: |
| |
| luci.builder( |
| ... |
| caches = [ |
| swarming.cache("golang"), |
| swarming.cache("gocache"), |
| ], |
| ) |
| |
| Note: CGO is disabled on Windows currently, since Windows doesn't have |
| a C compiler available by default. |
| |
| Args: |
| * version (str) - a Go version to install (e.g. `1.16.10`). |
| * path (Path) - a path to install Go into. |
| * cache (Path) - a path to put Go caches under. |
| ### *recipe_modules* / [json](/recipe_modules/json) |
| |
| [DEPS](/recipe_modules/json/__init__.py#7): [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Methods for producing and consuming JSON. |
| |
| #### **class [JsonApi](/recipe_modules/json/api.py#134)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
|   **@staticmethod**<br>— **def [dumps](/recipe_modules/json/api.py#135)(\*args, \*\*kwargs):** |
| |
| Works like `json.dumps`. |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>— **def [input](/recipe_modules/json/api.py#158)(self, data):** |
| |
| A placeholder which will expand to a file path containing <data>. |
| |
| — **def [is\_serializable](/recipe_modules/json/api.py#150)(self, obj):** |
| |
| Returns True if the object is JSON-serializable. |
| |
|   **@staticmethod**<br>— **def [loads](/recipe_modules/json/api.py#140)(data, \*\*kwargs):** |
| |
| Works like `json.loads`, but: |
| * strips out unicode objects (replacing them with utf8-encoded str |
| objects). |
| * replaces 'int-like' floats with ints. These are floats whose magnitude |
| is less than (2**53-1) and which don't have a decimal component. |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>— **def [output](/recipe_modules/json/api.py#163)(self, add_json_log=True, name=None, leak_to=None):** |
| |
| A placeholder which will expand to '/tmp/file'. |
| |
| If leak_to is provided, it must be a Path object. This path will be used in |
| place of a random temporary file, and the file will not be deleted at the |
| end of the step. |
| |
| Args: |
| * add_json_log (True|False|'on_failure') - Log a copy of the output json |
| to a step link named `name`. If this is 'on_failure', only create this |
| log when the step has a non-SUCCESS status. |
| |
| — **def [read](/recipe_modules/json/api.py#178)(self, name, path, add_json_log=True, output_name=None, \*\*kwargs):** |
| |
| Returns a step that reads a JSON file. |
| |
| *** note |
| **DEPRECATED**: Use file.read_json instead. |
| *** |
| ### *recipe_modules* / [led](/recipe_modules/led) |
| |
| [DEPS](/recipe_modules/led/__init__.py#7): [cipd](#recipe_modules-cipd), [context](#recipe_modules-context), [json](#recipe_modules-json), [path](#recipe_modules-path), [proto](#recipe_modules-proto), [step](#recipe_modules-step), [swarming](#recipe_modules-swarming) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| An interface to call the led tool. |
| |
| #### **class [LedApi](/recipe_modules/led/api.py#21)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| Interface to the led tool. |
| |
| "led" stands for LUCI editor. It allows users to debug and modify LUCI jobs. |
| It can be used to modify many aspects of a LUCI build, most commonly |
| including the recipes used. |
| |
| The main interface this module provides is a direct call to the led binary: |
| |
| led_result = api.led( |
| 'get-builder', ['luci.chromium.try:chromium_presubmit']) |
| final_data = led_result.then('edit-recipe-bundle').result |
| |
| See the led binary for full documentation of commands. |
| |
| — **def [\_\_call\_\_](/recipe_modules/led/api.py#158)(self, \*cmd):** |
| |
| Runs led with the given arguments. Wraps result in a `LedResult`. |
| |
|   **@property**<br>— **def [cipd\_input](/recipe_modules/led/api.py#150)(self):** |
| |
| The versioned CIPD package containing the recipes code being run. |
| |
| If set, it will be an `InputProperties.CIPDInput` protobuf; otherwise None. |
| |
| — **def [initialize](/recipe_modules/led/api.py#112)(self):** |
| |
| — **def [inject\_input\_recipes](/recipe_modules/led/api.py#162)(self, led_result):** |
| |
| Sets the version of recipes used by led to correspond to the version |
| currently being used. |
| |
| If neither the `rbe_cas_input` nor the `cipd_input` property is set, |
| this is a no-op. |
| |
| Args: |
| * led_result: The `LedResult` whose job.Definition will be passed into the |
| edit command. |
| |
|   **@property**<br>— **def [launched\_by\_led](/recipe_modules/led/api.py#128)(self):** |
| |
| Whether the current build is a led job. |
| |
|   **@property**<br>— **def [rbe\_cas\_input](/recipe_modules/led/api.py#141)(self):** |
| |
| The location of the rbe-cas containing the recipes code being run. |
| |
| If set, it will be a `swarming.v1.CASReference` protobuf; |
| otherwise, None. |
| |
|   **@property**<br>— **def [run\_id](/recipe_modules/led/api.py#133)(self):** |
| |
| A unique string identifier for this led job. |
| |
| If the current build is *not* a led job, value will be an empty string. |
| |
| — **def [trigger\_builder](/recipe_modules/led/api.py#187)(self, project_name, bucket_name, builder_name, properties):** |
| |
| Trigger a builder using led. |
| |
| This can be used by recipes instead of buildbucket or scheduler triggers |
| in case the running build was triggered by led. |
| |
| This is equivalent to: |
| led get-builder project/bucket:builder | <inject_input_recipes> | led edit <properties> | led launch |
| |
| Args: |
| * project_name - The project that defines the builder. |
| * bucket_name - The bucket that configures the builder. |
| * builder_name - Name of the builder to trigger. |
| * properties - Dict with properties to pass to the triggered build. |
| ### *recipe_modules* / [legacy\_annotation](/recipe_modules/legacy_annotation) |
| |
| [DEPS](/recipe_modules/legacy_annotation/__init__.py#7): [cipd](#recipe_modules-cipd), [context](#recipe_modules-context), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Legacy Annotation module provides support for running a command emitting |
| legacy @@@annotation@@@ in the new luciexe mode. |
| |
| The output annotations is converted to a build proto and all steps in the build |
| will appear as the child steps of the launched cmd/step in the current running |
| build (using the Merge Step feature from luciexe protocol). This is the |
| replacement for allow_subannotation feature in the legacy annotate mode. |
| |
| #### **class [LegacyAnnotationApi](/recipe_modules/legacy_annotation/api.py#24)([RecipeApiPlain](/recipe_engine/recipe_api.py#738)):** |
| |
| — **def [\_\_call\_\_](/recipe_modules/legacy_annotation/api.py#28)(self, name, cmd, timeout=None, step_test_data=None, cost=_ResourceCost(), legacy_global_namespace=False):** |
| |
| Runs cmd that is emitting legacy @@@annotation@@@. |
| |
| Currently, it will run the command as sub_build if running in luciexe |
| mode or simulation mode. Otherwise, it will fall back to launch a step |
| with allow_subannotation set to true. |
| |
| If `legacy_global_namespace` is True, this enables an even more-legacy |
| global namespace merging mode. Do not enable this. See crbug.com/1310155. |
| ### *recipe_modules* / [milo](/recipe_modules/milo) |
| |
| [DEPS](/recipe_modules/milo/__init__.py#7): [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [raw\_io](#recipe_modules-raw_io), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step), [uuid](#recipe_modules-uuid) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| API for specifying Milo behavior. |
| |
| #### **class [MiloApi](/recipe_modules/milo/api.py#17)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| A module for interacting with Milo. |
| |
| — **def [show\_blamelist\_for](/recipe_modules/milo/api.py#20)(self, gitiles_commits):** |
| |
| Specifies which commits and repos Milo should show a blamelist for. |
| |
| If not set, Milo will only show a blamelist for the main repo in which this |
| build was run. |
| |
| Args: |
| gitiles_commits: A list of buildbucket.common_pb2.GitilesCommit messages |
| or dicts of the same structure. |
| Each commit must have host, project and id. |
| ID must match r'^[0-9a-f]{40}$' (git revision). |
| ### *recipe_modules* / [nodejs](/recipe_modules/nodejs) |
| |
| [DEPS](/recipe_modules/nodejs/__init__.py#7): [cipd](#recipe_modules-cipd), [context](#recipe_modules-context), [path](#recipe_modules-path), [platform](#recipe_modules-platform) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| #### **class [NodeJSApi](/recipe_modules/nodejs/api.py#10)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
|   **@contextlib.contextmanager**<br>— **def [\_\_call\_\_](/recipe_modules/nodejs/api.py#15)(self, version, path=None, cache=None):** |
| |
| Installs a Node.js toolchain and activates it in the environment. |
| |
| Installs it under the given `path`, defaulting to `[CACHE]/nodejs`. Various |
| cache directories used by npm are placed under `cache`, defaulting to |
| `[CACHE]/npmcache`. |
| |
| `version` will be used to construct CIPD package version for packages under |
| https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/nodejs/. |
| |
| To reuse the Node.js toolchain deployment and npm caches across builds, |
| declare the corresponding named caches in Buildbucket configs. E.g. when |
| using defaults: |
| |
| luci.builder( |
| ... |
| caches = [ |
| swarming.cache("nodejs"), |
| swarming.cache("npmcache"), |
| ], |
| ) |
| |
| Args: |
| * version (str) - a Node.js version to install (e.g. `17.1.0`). |
| * path (Path) - a path to install Node.js into. |
| * cache (Path) - a path to put Node.js caches under. |
| ### *recipe_modules* / [path](/recipe_modules/path) |
| |
| [DEPS](/recipe_modules/path/__init__.py#7): [platform](#recipe_modules-platform) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| All functions related to manipulating paths in recipes. |
| |
| Recipes handle paths a bit differently than python does. All path manipulation |
| in recipes revolves around Path objects. These objects store a base path (always |
| absolute), plus a list of components to join with it. New paths can be derived |
| by calling the .join method with additional components. |
| |
| In this way, all paths in Recipes are absolute, and are constructed from a small |
| collection of anchor points. The built-in anchor points are: |
| * `api.path['start_dir']` - This is the directory that the recipe started in. |
| it's similar to `cwd`, except that it's constant. |
| * `api.path['cache']` - This directory is provided by whatever's running the |
| recipe. Files and directories created under here /may/ be evicted in between |
| runs of the recipe (i.e. to relieve disk pressure). |
| * `api.path['cleanup']` - This directory is provided by whatever's running the |
| recipe. Files and directories created under here /are guaranteed/ to be |
| evicted in between runs of the recipe. Additionally, this directory is |
| guaranteed to be empty when the recipe starts. |
| * `api.path['tmp_base']` - This directory is the system-configured temp dir. |
| This is a weaker form of 'cleanup', and its use should be avoided. This may |
| be removed in the future (or converted to an alias of 'cleanup'). |
| * `api.path['checkout']` - This directory is set by various 'checkout' modules |
| in recipes. It was originally intended to make recipes easier to read and |
| make code somewhat generic or homogeneous, but this was a mistake. New code |
| should avoid 'checkout', and instead just explicitly pass paths around. This |
| path may be removed in the future. |
| |
| There are other anchor points which can be defined (e.g. by the |
| `depot_tools/infra_paths` module). Refer to those modules for additional |
| documentation. |
| |
| #### **class [PathApi](/recipe_modules/path/api.py#225)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| — **def [\_\_getitem\_\_](/recipe_modules/path/api.py#464)(self, name):** |
| |
| Gets the base path named `name`. See module docstring for more |
| information. |
| |
| — **def [abs\_to\_path](/recipe_modules/path/api.py#391)(self, abs_string_path):** |
| |
| Converts an absolute path string `string_path` to a real Path object, |
| using the most appropriate known base path. |
| |
| * abs_string_path MUST be an absolute path |
| * abs_string_path MUST be rooted in one of the configured base paths known |
| to the path module. |
| |
| This method will find the longest match in all the following: |
| * module resource paths |
| * recipe resource paths |
| * repo paths |
| * dynamic_paths |
| * base_paths |
| |
| Example: |
| ``` |
| # assume [START_DIR] == "/basis/dir/for/recipe" |
| api.path.abs_to_path("/basis/dir/for/recipe/some/other/dir") -> |
| Path("[START_DIR]/some/other/dir") |
| ``` |
| |
| Raises an ValueError if the preconditions are not met, otherwise returns the |
| Path object. |
| |
| — **def [abspath](/recipe_modules/path/api.py#487)(self, path):** |
| |
| Equivalent to os.path.abspath. |
| |
| — **def [assert\_absolute](/recipe_modules/path/api.py#330)(self, path):** |
| |
| Raises AssertionError if the given path is not an absolute path. |
| |
| Args: |
| * path (Path|str) - The path to check. |
| |
| — **def [basename](/recipe_modules/path/api.py#491)(self, path):** |
| |
| Equivalent to os.path.basename. |
| |
| — **def [dirname](/recipe_modules/path/api.py#495)(self, path):** |
| |
| For "foo/bar/baz", return "foo/bar". |
| |
| This corresponds to os.path.dirname(). |
| |
| The type of the return value matches the type of the argument. |
| |
| Args: |
| path (Path or str): path to take directory name of |
| |
| Returns dirname of path |
| |
| — **def [exists](/recipe_modules/path/api.py#592)(self, path):** |
| |
| Equivalent to os.path.exists. |
| |
| The presence or absence of paths can be mocked during the execution of the |
| recipe by using the mock_* methods. |
| |
| — **def [expanduser](/recipe_modules/path/api.py#583)(self, path):** |
| |
| Do not use this, use `api.path['home']` instead. |
| |
| This ONLY handles `path` == "~", and returns `str(api.path['home'])`. |
| |
| — **def [get](/recipe_modules/path/api.py#457)(self, name, default=None):** |
| |
| Gets the base path named `name`. See module docstring for more |
| information. |
| |
| — **def [get\_config\_defaults](/recipe_modules/path/api.py#228)(self):** |
| |
| Internal recipe implementation function. |
| |
| — **def [initialize](/recipe_modules/path/api.py#294)(self):** |
| |
| Internal recipe implementation function. |
| |
| — **def [isdir](/recipe_modules/path/api.py#600)(self, path):** |
| |
| Equivalent to os.path.isdir. |
| |
| The presence or absence of paths can be mocked during the execution of the |
| recipe by using the mock_* methods. |
| |
| — **def [isfile](/recipe_modules/path/api.py#608)(self, path):** |
| |
| Equivalent to os.path.isfile. |
| |
| The presence or absence of paths can be mocked during the execution of the |
| recipe by using the mock_* methods. |
| |
| — **def [join](/recipe_modules/path/api.py#514)(self, path, \*paths):** |
| |
| Equivalent to os.path.join. |
| |
| Note that Path objects returned from this module (e.g. |
| api.path['start_dir']) have a built-in join method (e.g. |
| new_path = p.join('some', 'name')). Many recipe modules expect Path objects |
| rather than strings. Using this `join` method gives you raw path joining |
| functionality and returns a string. |
| |
| If your path is rooted in one of the path module's root paths (i.e. those |
| retrieved with api.path[something]), then you can convert from a string path |
| back to a Path with the `abs_to_path` method. |
| |
| — **def [mkdtemp](/recipe_modules/path/api.py#339)(self, prefix=tempfile.template):** |
| |
| Makes a new temporary directory, returns Path to it. |
| |
| Args: |
| * prefix (str) - a tempfile template for the directory name (defaults |
| to "tmp"). |
| |
| Returns a Path to the new directory. |
| |
| — **def [mkstemp](/recipe_modules/path/api.py#364)(self, prefix=tempfile.template):** |
| |
| Makes a new temporary file, returns Path to it. |
| |
| Args: |
| * prefix (str) - a tempfile template for the file name (defaults to |
| "tmp"). |
| |
| Returns a Path to the new file. Unlike tempfile.mkstemp, the file's file |
| descriptor is closed. |
| |
| — **def [mock\_add\_directory](/recipe_modules/path/api.py#625)(self, path):** |
| |
| For testing purposes, mark that directory |path| exists. |
| |
| — **def [mock\_add\_file](/recipe_modules/path/api.py#621)(self, path):** |
| |
| For testing purposes, mark that file |path| exists. |
| |
| — **def [mock\_add\_paths](/recipe_modules/path/api.py#616)(self, path, kind=FILE):** |
| |
| For testing purposes, mark that |path| exists. |
| |
| — **def [mock\_copy\_paths](/recipe_modules/path/api.py#629)(self, source, dest):** |
| |
| For testing purposes, copy |source| to |dest|. |
| |
| — **def [mock\_remove\_paths](/recipe_modules/path/api.py#634)(self, path, filt=(lambda p: True)):** |
| |
| For testing purposes, assert that |path| doesn't exist. |
| |
| Args: |
| * path (str|Path): The path to remove. |
| * filt (func[str] bool): Called for every candidate path. Return |
| True to remove this path. |
| |
|   **@property**<br>— **def [pardir](/recipe_modules/path/api.py#472)(self):** |
| |
| Equivalent to os.path.pardir. |
| |
|   **@property**<br>— **def [pathsep](/recipe_modules/path/api.py#482)(self):** |
| |
| Equivalent to os.path.pathsep. |
| |
| — **def [realpath](/recipe_modules/path/api.py#571)(self, path):** |
| |
| Equivalent to os.path.realpath. |
| |
| — **def [relpath](/recipe_modules/path/api.py#575)(self, path, start):** |
| |
| Roughly equivalent to os.path.relpath. |
| |
| Unlike os.path.relpath, `start` is _required_. If you want the 'current |
| directory', use the `recipe_engine/context` module's `cwd` property. |
| |
|   **@property**<br>— **def [sep](/recipe_modules/path/api.py#477)(self):** |
| |
| Equivalent to os.path.sep. |
| |
| — **def [split](/recipe_modules/path/api.py#529)(self, path):** |
| |
| For "foo/bar/baz", return ("foo/bar", "baz"). |
| |
| This corresponds to os.path.split(). |
| |
| The type of the first item in the return value matches the type of the |
| argument. |
| |
| Args: |
| path (Path or str): path to split into directory name and basename |
| |
| Returns (dirname(path), basename(path)). |
| |
| — **def [splitext](/recipe_modules/path/api.py#550)(self, path):** |
| |
| For "foo/bar.baz", return ("foo/bar", ".baz"). |
| |
| This corresponds to os.path.splitext(). |
| |
| The type of the first item in the return value matches the type of the |
| argument. |
| |
| Args: |
| path (Path or str): path to split into name and extension |
| |
| Returns (name, extension_including_dot). |
| ### *recipe_modules* / [platform](/recipe_modules/platform) |
| |
| [DEPS](/recipe_modules/platform/__init__.py#7): [version](#recipe_modules-version) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Mockable system platform identity functions. |
| |
| #### **class [PlatformApi](/recipe_modules/platform/api.py#24)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| Provides host-platform-detection properties. |
| |
| Mocks: |
| * name (str): A value equivalent to something that might be returned by |
| sys.platform. |
| * bits (int): Either 32 or 64. |
| |
|   **@property**<br>— **def [arch](/recipe_modules/platform/api.py#122)(self):** |
| |
| Returns the current CPU architecture. |
| |
| Can return "arm" or "intel". |
| |
|   **@property**<br>— **def [bits](/recipe_modules/platform/api.py#112)(self):** |
| |
| Returns the bitness of the userland for the current system (either 32 or |
| 64 bit). |
| |
| TODO: If anyone needs to query for the kernel bitness, another accessor |
| should be added. |
| |
|   **@property**<br>— **def [cpu\_count](/recipe_modules/platform/api.py#139)(self):** |
| |
| The number of logical CPU cores (i.e. including hyper-threaded cores), |
| according to `psutil.cpu_count(True)`. |
| |
| — **def [initialize](/recipe_modules/platform/api.py#34)(self):** |
| |
|   **@property**<br>— **def [is\_linux](/recipe_modules/platform/api.py#98)(self):** |
| |
| Returns True iff the recipe is running on Linux. |
| |
|   **@property**<br>— **def [is\_mac](/recipe_modules/platform/api.py#83)(self):** |
| |
| Returns True iff the recipe is running on OS X. |
| |
|   **@property**<br>— **def [is\_win](/recipe_modules/platform/api.py#78)(self):** |
| |
| Returns True iff the recipe is running on Windows. |
| |
|   **@property**<br>— **def [mac\_release](/recipe_modules/platform/api.py#88)(self):** |
| |
| The current OS X release version number (like "10.13.5") as a |
| pkg_resources Version object, or None, if the current platform is not mac. |
| |
| Use the "recipe_engine/version" module to parse symvers to compare to this |
| Version object. |
| |
|   **@property**<br>— **def [name](/recipe_modules/platform/api.py#103)(self):** |
| |
| Returns the current platform name which will be in: |
| * win |
| * mac |
| * linux |
| |
|   **@staticmethod**<br>— **def [normalize\_platform\_name](/recipe_modules/platform/api.py#145)(plat):** |
| |
| One of python's sys.platform values -> 'win', 'linux' or 'mac'. |
| |
|   **@property**<br>— **def [total\_memory](/recipe_modules/platform/api.py#130)(self):** |
| |
| The total physical memory in MiB. |
| |
| Return type is int. |
| This is equivalent to `psutil.virtual_memory().total / (1024 ** 2)`. |
| ### *recipe_modules* / [properties](/recipe_modules/properties) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Provides access to the recipes input properties. |
| |
| Every recipe is run with a JSON object called "properties". These contain all |
| inputs to the recipe. Some common examples would be properties like "revision", |
| which the build scheduler sets to tell a recipe to build/test a certain |
| revision. |
| |
| The properties that affect a particular recipe are defined by the recipe itself, |
| and this module provides access to them. |
| |
| Recipe properties are read-only; the values obtained via this API reflect the |
| values provided to the recipe engine at the beginning of execution. There is |
| intentionally no API to write property values (lest they become a kind of |
| random-access global variable). |
| |
| #### **class [PropertiesApi](/recipe_modules/properties/api.py#30)([RecipeApiPlain](/recipe_engine/recipe_api.py#738), collections.Mapping):** |
| |
| PropertiesApi implements all the standard Mapping functions, so you |
| can use it like a read-only dict. |
| |
| — **def [legacy](/recipe_modules/properties/api.py#56)(self):** |
| |
| *** note |
| **DEPRECATED**: Returns a set of properties, possibly used by legacy |
| scripts. |
| *** |
| |
| This excludes any recipe module-specific properties (i.e. those beginning |
| with `$`). |
| |
| Instead of passing all of the properties as a blob, please consider passing |
| specific arguments to scripts that need them. Doing this makes it much |
| easier to debug and diagnose which scripts use which properties. |
| |
| — **def [thaw](/recipe_modules/properties/api.py#80)(self):** |
| |
| Returns a read-write copy of all of the properties. |
| ### *recipe_modules* / [proto](/recipe_modules/proto) |
| |
| [DEPS](/recipe_modules/proto/__init__.py#7): [raw\_io](#recipe_modules-raw_io) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Methods for producing and consuming protobuf data to/from steps and the |
| filesystem. |
| |
| #### **class [ProtoApi](/recipe_modules/proto/api.py#83)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
|   **@staticmethod**<br>— **def [decode](/recipe_modules/proto/api.py#161)(data, msg_class, codec, \*\*decoding_kwargs):** |
| |
| Decodes a proto message from a string. |
| |
| Args: |
| * msg_class (protobuf Message subclass) - The message type to decode. |
| * codec ('BINARY'|'JSONPB'|'TEXTPB') - The encoder to use. |
| * decoding_kwargs - Passed directly to the chosen decoder. See input |
| placeholder for details. |
| |
| Returns the decoded proto object. |
| |
|   **@staticmethod**<br>— **def [encode](/recipe_modules/proto/api.py#146)(proto_msg, codec, \*\*encoding_kwargs):** |
| |
| Encodes a proto message to a string. |
| |
| Args: |
| * codec ('BINARY'|'JSONPB'|'TEXTPB') - The encoder to use. |
| * encoding_kwargs - Passed directly to the chosen encoder. See output |
| placeholder for details. |
| |
| Returns the encoded proto message. |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>— **def [input](/recipe_modules/proto/api.py#85)(self, proto_msg, codec, \*\*encoding_kwargs):** |
| |
| A placeholder which will expand to a file path containing the encoded |
| `proto_msg`. |
| |
| Example: |
| proto_msg = MyMessage(field=10) |
| api.step('step name', ['some_cmd', api.proto.input(proto_msg)]) |
| # some_cmd sees "/path/to/random.pb" |
| |
| Args: |
| * proto_msg (message.Message) - The message data to encode. |
| * codec ('BINARY'|'JSONPB'|'TEXTPB') - The encoder to use. |
| * encoding_kwargs - Passed directly to the chosen encoder. See: |
| - BINARY: google.protobuf.message.Message.SerializeToString |
| * 'deterministic' defaults to True. |
| - JSONPB: google.protobuf.json_format.MessageToJson |
| * 'preserving_proto_field_name' defaults to True. |
| * 'sort_keys' defaults to True. |
| * 'indent' defaults to 0. |
| - TEXTPB: google.protobuf.text_format.MessageToString |
| |
| Returns an InputPlaceholder. |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>— **def [output](/recipe_modules/proto/api.py#116)(self, msg_class, codec, add_json_log=True, name=None, leak_to=None, \*\*decoding_kwargs):** |
| |
| A placeholder which expands to a file path and then reads an encoded |
| proto back from that location when the step finishes. |
| |
| Args: |
| * msg_class (protobuf Message subclass) - The message type to decode. |
| * codec ('BINARY'|'JSONPB'|'TEXTPB') - The encoder to use. |
| * add_json_log (True|False|'on_failure') - Log a copy of the parsed proto |
| in JSONPB form to a step link named `name`. If this is 'on_failure', |
| only create this log when the step has a non-SUCCESS status. |
| * leak_to (Optional[Path]) - This path will be used in place of a random |
| temporary file, and the file will not be deleted at the end of the step. |
| * decoding_kwargs - Passed directly to the chosen decoder. See: |
| - BINARY: google.protobuf.message.Message.Parse |
| - JSONPB: google.protobuf.json_format.Parse |
| * 'ignore_unknown_fields' defaults to True. |
| - TEXTPB: google.protobuf.text_format.Parse |
| ### *recipe_modules* / [python](/recipe_modules/python) |
| |
| [DEPS](/recipe_modules/python/__init__.py#11): [context](#recipe_modules-context), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step), [warning](#recipe_modules-warning) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Provides methods for running python scripts correctly. |
| |
| This includes support for `vpython`, and knows how to specify parameters |
| correctly for bots (e.g. ensuring that python is working on Windows, passing the |
| unbuffered flag, etc.) |
| |
| #### **class [PythonApi](/recipe_modules/python/api.py#20)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| *** note |
| **DEPRECATED**: Directly invoke python instead of using this module. |
| |
| *** |
| |
| — **def [\_\_call\_\_](/recipe_modules/python/api.py#24)(self, name, script, args=None, unbuffered=True, venv=None, \*\*kwargs):** |
| |
| Return a step to run a python script with arguments. |
| |
| **TODO**: We should just use a single "args" list. Having "script" |
| separate but required/first leads to weird things like: |
| |
| (... script='-m', args=['module']) |
| |
| Args: |
| * name (str): The name of the step. |
| * script (str or Path): The Path of the script to run, or the first |
| command-line argument to pass to Python. |
| * args (list or None): If not None, additional arguments to pass to the |
| Python command. |
| * unbuffered (bool): If True, run Python in unbuffered mode. |
| * venv (None or False or True or Path): If True, run the script through |
| "vpython". This will, by default, probe the target script for a |
| configured VirtualEnv and, failing that, use an empty VirtualEnv. If a |
| Path, this is a path to an explicit "vpython" VirtualEnv spec file to |
| use. If False or None (default), the script will be run through the |
| standard Python interpreter. |
| * kwargs: Additional keyword arguments to forward to "step". |
| |
| **Returns (`step_data.StepData`)** - The StepData object as returned by |
| api.step. |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/PYTHON_RESULT_STEP_DEPRECATED')**<br>— **def [failing\_step](/recipe_modules/python/api.py#141)(self, name, text, as_log=None):** |
| |
| Runs a failing step (exits 1). |
| |
| *** note |
| **DEPRECATED**: crbug.com/1276131 |
| *** |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/PYTHON_RESULT_STEP_DEPRECATED')**<br>— **def [infra\_failing\_step](/recipe_modules/python/api.py#151)(self, name, text, as_log=None):** |
| |
| Runs an infra-failing step (exits 1). |
| |
| *** note |
| **DEPRECATED**: crbug.com/1276131 |
| *** |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/PYTHON_CALL_DEPRECATED')**<br>— **def [inline](/recipe_modules/python/api.py#69)(self, name, program, add_python_log=True, \*\*kwargs):** |
| |
| Run an inline python program as a step. |
| |
| Program is output to a temp file and run when this step executes. |
| |
| Args: |
| * name (str) - The name of the step |
| * program (str) - The literal python program text. This will be dumped to |
| a file and run like `python /path/to/file.py` |
| * add_python_log (bool) - Whether to add a 'python.inline' link on this |
| step on the build page. If true, the link will point to a log with |
| a copy of `program`. |
| |
| **Returns (`step_data.StepData`)** - The StepData object as returned by |
| api.step. |
| |
| — **def [result\_step](/recipe_modules/python/api.py#103)(self, name, text, retcode, as_log=None, \*\*kwargs):** |
| |
| Runs a no-op step that exits with a specified return code. |
| |
| *** note |
| **DEPRECATED**: crbug.com/1276131 |
| *** |
| |
| The recipe engine will raise an exception when seeing a return code != 0. |
| |
| The text is expected to be str. Passing a list of lines(str) works but is |
| discouraged and may be deprecated in the future. Please concatenate the |
| lines with newline character instead. |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/PYTHON_RESULT_STEP_DEPRECATED')**<br>— **def [succeeding\_step](/recipe_modules/python/api.py#131)(self, name, text, as_log=None):** |
| |
| Runs a succeeding step (exits 0). |
| |
| *** note |
| **DEPRECATED**: crbug.com/1276131 |
| *** |
| ### *recipe_modules* / [random](/recipe_modules/random) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Allows randomness in recipes. |
| |
| This module sets up an internal instance of 'random.Random'. In tests, this is |
| seeded with `1234`, or a seed of your choosing (using the test_api's `seed()` |
| method) |
| |
| All members of `random.Random` are exposed via this API with getattr. |
| |
| *** promo |
| NOTE: This is based on the python `random` module, and so all caveats which |
| apply there also apply to this (i.e. don't use it for anything resembling |
| crypto). |
| *** |
| |
| Example: |
| |
| def RunSteps(api): |
| my_list = range(100) |
| api.random.shuffle(my_list) |
| # my_list is now random! |
| |
| #### **class [RandomApi](/recipe_modules/random/api.py#56)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| — **def [\_\_getattr\_\_](/recipe_modules/random/api.py#63)(self, name):** |
| |
| Access a member of `random.Random`. |
| ### *recipe_modules* / [raw\_io](/recipe_modules/raw_io) |
| |
| [DEPS](/recipe_modules/raw_io/__init__.py#7): [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Provides objects for reading and writing raw data to and from steps. |
| |
| #### **class [RawIOApi](/recipe_modules/raw_io/api.py#330)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>  **@staticmethod**<br>— **def [input](/recipe_modules/raw_io/api.py#331)(data, suffix='', name=None):** |
| |
| Returns a Placeholder for use as a step argument. |
| |
| This placeholder can be used to pass data to steps. The recipe engine will |
| dump the 'data' into a file, and pass the filename to the command line |
| argument. |
| |
| data MUST be either of type 'bytes' (recommended) or type 'str' in Python 3. |
| Respectively, 'str' or 'unicode' in Python 2. |
| |
| If the provided data is of type 'str', it is encoded to bytes assuming |
| utf-8 encoding. Please switch to `input_text(...)` instead in this case. |
| |
| If 'suffix' is not '', it will be used when the engine calls |
| tempfile.mkstemp. |
| |
| See examples/full.py for usage example. |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>  **@staticmethod**<br>— **def [input\_text](/recipe_modules/raw_io/api.py#358)(data, suffix='', name=None):** |
| |
| Returns a Placeholder for use as a step argument. |
| |
| Similar to input(), but ensures that 'data' is valid utf-8 text. Any |
| non-utf-8 characters will be replaced with �. |
| |
| data MUST be either of type 'bytes' or type 'str' (recommended) in Python 3. |
| Respectively, 'str' or 'unicode' in Python 2. |
| |
| If the provided data is of type 'bytes', it is expected to be valid utf-8 |
| encoded data. Note that, the support of type 'bytes' is for backwards |
| compatibility to Python 2, we may drop this support in the future after |
| recipe becomes Python 3 only. |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>  **@staticmethod**<br>— **def [output](/recipe_modules/raw_io/api.py#381)(suffix='', leak_to=None, name=None, add_output_log=False):** |
| |
| Returns a Placeholder for use as a step argument, or for std{out,err}. |
| |
| If 'leak_to' is None, the placeholder is backed by a temporary file with |
| a suffix 'suffix'. The file is deleted when the step finishes. |
| |
| If 'leak_to' is not None, then it should be a Path and placeholder |
| redirects IO to a file at that path. Once step finishes, the file is |
| NOT deleted (i.e. it's 'leaking'). 'suffix' is ignored in that case. |
| |
| Args: |
| * add_output_log (True|False|'on_failure') - Log a copy of the output |
| to a step link named `name`. If this is 'on_failure', only create this |
| log when the step has a non-SUCCESS status. |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>— **def [output\_dir](/recipe_modules/raw_io/api.py#419)(self, leak_to=None, name=None):** |
| |
| Returns a directory Placeholder for use as a step argument. |
| |
| If `leak_to` is None, the placeholder is backed by a temporary dir. |
| |
| Otherwise `leak_to` must be a Path; if the path doesn't exist, it will be |
| created. |
| |
| The placeholder value attached to the step will be a dictionary-like mapping |
| of relative paths to the contents of the file. The actual reading of the |
| file data is done lazily (i.e. on first access). |
| |
| Relative paths are stored with the native slash delimitation (i.e. forward |
| slash on *nix, backslash on Windows). |
| |
| Example: |
| |
| ```python |
| result = api.step('name', [..., api.raw_io.output_dir()]) |
| |
| # some time later; The read of 'some/file' happens now: |
| some_file = api.path.join('some', 'file') |
| assert result.raw_io.output_dir[some_file] == 'contents of some/file' |
| |
| # data for 'some/file' is cached now; To free it from memory (and make |
| # all further reads of 'some/file' an error): |
| del result.raw_io.output_dir[some_file] |
| |
| result.raw_io.output_dir[some_file] -> raises KeyError |
| ``` |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#156)**<br>  **@staticmethod**<br>— **def [output\_text](/recipe_modules/raw_io/api.py#401)(suffix='', leak_to=None, name=None, add_output_log=False):** |
| |
| Returns a Placeholder for use as a step argument, or for std{out,err}. |
| |
| Similar to output(), but uses an OutputTextPlaceholder, which expects utf-8 |
| encoded text. |
| Similar to input(), but tries to decode the resulting data as utf-8 text, |
| replacing any decoding errors with �. |
| |
| Args: |
| * add_output_log (True|False|'on_failure') - Log a copy of the output |
| to a step link named `name`. If this is 'on_failure', only create this |
| log when the step has a non-SUCCESS status. |
| ### *recipe_modules* / [resultdb](/recipe_modules/resultdb) |
| |
| [DEPS](/recipe_modules/resultdb/__init__.py#7): [context](#recipe_modules-context), [futures](#recipe_modules-futures), [json](#recipe_modules-json), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step), [time](#recipe_modules-time), [uuid](#recipe_modules-uuid) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| API for interacting with the ResultDB service. |
| |
| Requires `rdb` command in `$PATH`: |
| https://godoc.org/go.chromium.org/luci/resultdb/cmd/rdb |
| |
| #### **class [ResultDBAPI](/recipe_modules/resultdb/api.py#29)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| A module for interacting with ResultDB. |
| |
| — **def [assert\_enabled](/recipe_modules/resultdb/api.py#51)(self):** |
| |
| — **def [config\_test\_presentation](/recipe_modules/resultdb/api.py#563)(self, column_keys=(), grouping_keys=('status',)):** |
| |
| Specifies how the test results should be rendered. |
| |
| Args: |
| column_keys: |
| A list of keys that will be rendered as 'columns'. status is always the |
| first column and name is always the last column (you don't need to |
| specify them). A key must be one of the following: |
| 1. 'v.{variant_key}': variant.def[variant_key] of the test variant (e.g. |
| v.gpu). |
| |
| grouping_keys: |
| A list of keys that will be used for grouping tests. A key must be one |
| of the following: |
| 1. 'status': status of the test variant. |
| 2. 'name': name of the test variant. |
| 3. 'v.{variant_key}': variant.def[variant_key] of the test variant (e.g. |
| v.gpu). |
| Caveat: test variants with only expected results are not affected by |
| this setting and are always in their own group. |
| |
|   **@property**<br>— **def [current\_invocation](/recipe_modules/resultdb/api.py#43)(self):** |
| |
|   **@property**<br>— **def [enabled](/recipe_modules/resultdb/api.py#47)(self):** |
| |
| — **def [exclude\_invocations](/recipe_modules/resultdb/api.py#62)(self, invocations, step_name=None):** |
| |
| Shortcut for resultdb.update_included_invocations(). |
| |
| — **def [exonerate](/recipe_modules/resultdb/api.py#128)(self, test_exonerations, step_name=None):** |
| |
| Exonerates test variants in the current invocation. |
| |
| Args: |
| test_exonerations (list): A list of test_result_pb2.TestExoneration. |
| step_name (str): name of the step. |
| |
| — **def [get\_included\_invocations](/recipe_modules/resultdb/api.py#103)(self, inv_name=None, step_name=None):** |
| |
| Returns names of included invocations of the input invocation. |
| |
| Args: |
| inv_name (str): the name of the input invocation. If input is None, will |
| use current invocation. |
| step_name (str): name of the step. |
| |
| Returns: |
| A list of invocation name strs. |
| |
| — **def [get\_test\_result\_history](/recipe_modules/resultdb/api.py#254)(self, realm, test_id_regexp, variant_predicate=None, time_range=None, page_size=10, page_token=None, step_name=None):** |
| |
| Receive test results for a given configuration. |
| |
| Makes a call to GetTestResultHistory rpc. Allows for test retrieval for |
| all invocations with the specified configurations. |
| |
| Args: |
| realm (str): the realm that the data being queried exists in. |
| Example: "chromium:ci". |
| test_id_regexp (str): the subset of test ids to request history for. |
| variant_predicate (resultdb.proto.v1.predicate.VariantPredicate): |
| the subset of test variants to request history for. Defaults to None, |
| but specifying will improve runtime. |
| time_range (common_v1.TimeRange): a range of timestamps in which to |
| request history from. If no time_range is specified, it defaults to the |
| past day. |
| page_size (int): the number of results per page in the response. If the |
| number of results satisfying the given configuration exceeds this |
| number, only the page_size results will be available in the response. |
| Defaults to 10 results. |
| page_token (str): for instances in which the results span multiple pages, |
| each response will contain a page token for the next page, which can be |
| passed in to the next request. Defaults to None, which returns the first |
| page. |
| step_name (str): name of the step. |
| |
| Returns: |
| A GetTestResultHistoryResponse proto message with entries for each test |
| matching the configuration. |
| |
| For value format, see [`GetTestResultHistoryResponse` message] |
| (https://bit.ly/3bSXxU1) |
| |
| — **def [include\_invocations](/recipe_modules/resultdb/api.py#57)(self, invocations, step_name=None):** |
| |
| Shortcut for resultdb.update_included_invocations(). |
| |
| — **def [invocation\_ids](/recipe_modules/resultdb/api.py#170)(self, inv_names):** |
| |
| Returns invocation ids by parsing invocation names. |
| |
| Args: |
| inv_names (list of str): resultdb invocation names. |
| |
| Returns: |
| A list of invocation_ids. |
| |
| — **def [query](/recipe_modules/resultdb/api.py#186)(self, inv_ids, variants_with_unexpected_results=False, merge=False, limit=None, step_name=None, tr_fields=None):** |
| |
| Returns test results in the invocations. |
| |
| Most users will be interested only in results of test variants that had |
| unexpected results. This can be achieved by passing |
| variants_with_unexpected_results=True. This significantly reduces output |
| size and latency. |
| |
| Example: |
| results = api.resultdb.query( |
| [ |
| # invocation id for a swarming task. |
| 'task-chromium-swarm.appspot.com-deadbeef', |
| # invocation id for a buildbucket build. |
| 'build-234298374982' |
| ], |
| variants_with_unexpected_results=True, |
| ) |
| |
| Args: |
| inv_ids (list of str): ids of the invocations. |
| variants_with_unexpected_results (bool): if True, return only test |
| results from variants that have unexpected results. |
| merge (bool): if True, return test results as if all invocations |
| are one, otherwise, results will be ordered by invocation. |
| limit (int): maximum number of test results to return. |
| Unlimited if 0. Defaults to 1000. |
| step_name (str): name of the step. |
| tr_fields (list of str): test result fields in the response. |
| Test result name will always be included regardless of this param value. |
| Returns: |
| A dict {invocation_id: api.Invocation}. |
| |
| — **def [query\_test\_result\_statistics](/recipe_modules/resultdb/api.py#324)(self, invocations=None, step_name=None):** |
| |
| Retrieve stats of test results for the given invocations. |
| |
| Makes a call to the QueryTestResultStatistics API. Returns stats for all |
| given invocations, including those included indirectly. |
| |
| Args: |
| invocations (list): A list of the invocations to query statistics for. |
| If None, the current invocation will be used. |
| step_name (str): name of the step. |
| |
| Returns: |
| A QueryTestResultStatisticsResponse proto message with statistics for the |
| queried invocations. |
| |
| — **def [update\_included\_invocations](/recipe_modules/resultdb/api.py#67)(self, add_invocations=None, remove_invocations=None, step_name=None):** |
| |
| Add and/or remove included invocations to/from the current invocation. |
| |
| Args: |
| add_invocations (list of str): invocation id's to add to the current |
| invocation. |
| remove_invocations (list of str): invocation id's to remove from the |
| current invocation. |
| |
| This updates the inclusions of the current invocation specified in the |
| LUCI_CONTEXT. |
| |
| — **def [upload\_invocation\_artifacts](/recipe_modules/resultdb/api.py#357)(self, artifacts, parent_inv=None, step_name=None):** |
| |
| Create artifacts with the given content type and contents or gcs_uri. |
| |
| Makes a call to the BatchCreateArtifacts API. Returns the created |
| artifacts. |
| |
| Args: |
| artifacts (dict): a collection of artifacts to create. Each key is an |
| artifact id, with the corresponding value being a dict containing: |
| 'content_type' (optional) |
| one of 'contents' (binary string) or 'gcs_uri' (str) |
| parent_inv (str): the name of the invocation to create the artifacts |
| under. If None, the current invocation will be used. |
| step_name (str): name of the step. |
| |
| Returns: |
| A BatchCreateArtifactsResponse proto message listing the artifacts that |
| were created. |
| |
| — **def [wrap](/recipe_modules/resultdb/api.py#464)(self, cmd, test_id_prefix='', base_variant=None, test_location_base='', base_tags=None, coerce_negative_duration=False, include=False, realm='', location_tags_file='', require_build_inv=True, exonerate_unexpected_pass=False):** |
| |
| Wraps the command with ResultSink. |
| |
| Returns a command that, when executed, runs cmd in a go/result-sink |
| environment. For example: |
| |
| api.step('test', api.resultdb.wrap(['./my_test'])) |
| |
| Args: |
| cmd (list of strings): the command line to run. |
| test_id_prefix (str): a prefix to prepend to test IDs of test results |
| reported by cmd. |
| base_variant (dict): variant key-value pairs to attach to all test results |
| reported by cmd. If both base_variant and a reported variant have a |
| value for the same key, the reported one wins. |
| Example: |
| base_variant={ |
| 'bucket': api.buildbucket.build.builder.bucket, |
| 'builder': api.buildbucket.builder_name, |
| } |
| test_location_base (str): the base path to prepend to the test location |
| file name with a relative path. The value must start with "//". |
| base_tags (list of (string, string)): tags to attach to all test results |
| reported by cmd. Each element is a tuple of (key, value), and a key |
| may be repeated. |
| coerce_negative_duration (bool): If true, negative duration values will |
| be coerced to 0. If false, tests results with negative duration values |
| will be rejected with an error. |
| include (bool): If true, a new invocation will be created and included |
| in the parent invocation. |
| realm (str): realm used for the new invocation created if `include=True`. |
| Default is the current realm used in buildbucket. |
| location_tags_file (str): path to the file that contains test location |
| tags in JSON format. |
| require_build_inv(bool): flag to control if the build is required to have |
| an invocation. |
| exonerate_unexpected_pass(bool): flag to control if automatically |
| exonerate unexpected passes. |
| ### *recipe_modules* / [runtime](/recipe_modules/runtime) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| #### **class [RuntimeApi](/recipe_modules/runtime/api.py#10)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| This module assists in experimenting with production recipes. |
| |
| For example, when migrating builders from Buildbot to pure LUCI stack. |
| |
|   **@property**<br>— **def [in\_global\_shutdown](/recipe_modules/runtime/api.py#33)(self):** |
| |
| True iff this recipe is currently in the 'grace_period' specified by |
| `LUCI_CONTEXT['deadline']`. |
| |
| This can occur when: |
| * The LUCI_CONTEXT has hit the 'soft_deadline'; OR |
| * The LUCI_CONTEXT has been 'canceled' and the recipe_engine has recieved |
| a SIGTERM (on *nix) or Ctrl-Break (on Windows). |
| |
| As of 2021Q2, while the recipe is in the grace_period, it can do anything |
| _except_ for starting new steps (but it can e.g. update presentation of open |
| steps, or return RawResult from RunSteps). Attempting to start a step while |
| in the grace_period will cause the step to skip execution. When a signal is |
| recieved or the soft_deadline is hit, all currently running steps will be |
| signaled in turn (according to the `LUCI_CONTEXT['deadline']` protocol). |
| |
| It is good practice to ensure that recipes exit cleanly when canceled or |
| time out, and this could be used anywhere to skip 'cleanup' behavior in |
| 'finally' clauses or context managers. |
| |
| https://chromium.googlesource.com/infra/luci/luci-py/+/HEAD/client/LUCI_CONTEXT.md |
| |
|   **@property**<br>— **def [is\_experimental](/recipe_modules/runtime/api.py#20)(self):** |
| |
| True if this recipe is currently running in experimental mode. |
| |
| Typical usage is to modify steps which produce external side-effects so that |
| non-production runs of the recipe do not affect production data. |
| |
| Examples: |
| * Uploading to an alternate google storage file name when in non-prod mode |
| * Appending a 'non-production' tag to external RPCs |
| ### *recipe_modules* / [scheduler](/recipe_modules/scheduler) |
| |
| [DEPS](/recipe_modules/scheduler/__init__.py#12): [buildbucket](#recipe_modules-buildbucket), [json](#recipe_modules-json), [platform](#recipe_modules-platform), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step), [time](#recipe_modules-time) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| API for interacting with the LUCI Scheduler service. |
| |
| Depends on 'prpc' binary available in $PATH: |
| https://godoc.org/go.chromium.org/luci/grpc/cmd/prpc |
| Documentation for scheduler API is in |
| https://chromium.googlesource.com/infra/luci/luci-go/+/main/scheduler/api/scheduler/v1/scheduler.proto |
| RPCExplorer available at |
| https://luci-scheduler.appspot.com/rpcexplorer/services/scheduler.Scheduler |
| |
| #### **class [SchedulerApi](/recipe_modules/scheduler/api.py#28)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| A module for interacting with LUCI Scheduler service. |
| |
| — **def [emit\_trigger](/recipe_modules/scheduler/api.py#221)(self, trigger, project, jobs, step_name=None):** |
| |
| Emits trigger to one or more jobs of a given project. |
| |
| Args: |
| trigger (Trigger): defines payload to trigger jobs with. |
| project (str): name of the project in LUCI Config service, which is used |
| by LUCI Scheduler instance. See https://luci-config.appspot.com/. |
| jobs (iterable of str): job names per LUCI Scheduler config for the given |
| project. These typically are the same as builder names. |
| |
| — **def [emit\_triggers](/recipe_modules/scheduler/api.py#233)(self, trigger_project_jobs, timestamp_usec=None, step_name=None):** |
| |
| Emits a batch of triggers spanning one or more projects. |
| |
| Up to date documentation is at |
| https://chromium.googlesource.com/infra/luci/luci-go/+/main/scheduler/api/scheduler/v1/scheduler.proto |
| |
| Args: |
| trigger_project_jobs (iterable of tuples(trigger, project, jobs)): |
| each tuple corresponds to parameters of `emit_trigger` API above. |
| timestamp_usec (int): unix timestamp in microseconds. |
| Useful for idempotency of calls if your recipe is doing its own retries. |
| https://chromium.googlesource.com/infra/luci/luci-go/+/main/scheduler/api/scheduler/v1/triggers.proto |
| |
|   **@property**<br>— **def [host](/recipe_modules/scheduler/api.py#52)(self):** |
| |
| Returns the backend hostname used by this module. |
| |
|   **@property**<br>— **def [invocation\_id](/recipe_modules/scheduler/api.py#73)(self):** |
| |
| Returns the invocation ID of the current build as an int64 integer. |
| |
| Returns None if the current build was not triggered by the scheduler. |
| |
|   **@property**<br>— **def [job\_id](/recipe_modules/scheduler/api.py#65)(self):** |
| |
| Returns the job ID of the current build as "<project>/<job>". |
| |
| Returns None if the current build was not triggered by the scheduler. |
| |
| — **def [set\_host](/recipe_modules/scheduler/api.py#57)(self, host):** |
| |
| Changes the backend hostname used by this module. |
| |
| Args: |
| host (str): server host (e.g. 'luci-scheduler.appspot.com'). |
| |
|   **@property**<br>— **def [triggers](/recipe_modules/scheduler/api.py#44)(self):** |
| |
| Returns a list of triggers that triggered the current build. |
| |
| A trigger is an instance of triggers_pb2.Trigger. |
| ### *recipe_modules* / [service\_account](/recipe_modules/service_account) |
| |
| [DEPS](/recipe_modules/service_account/__init__.py#7): [path](#recipe_modules-path), [platform](#recipe_modules-platform), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| API for getting OAuth2 access tokens for LUCI tasks or private keys. |
| |
| This is a thin wrapper over the luci-auth go executable ( |
| https://godoc.org/go.chromium.org/luci/auth/client/cmd/luci-auth). |
| |
| Depends on luci-auth to be in PATH. |
| |
| #### **class [ServiceAccountApi](/recipe_modules/service_account/api.py#16)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| — **def [default](/recipe_modules/service_account/api.py#57)(self):** |
| |
| Returns an account associated with the task. |
| |
| On LUCI, this is default account exposed through LUCI_CONTEXT["local_auth"] |
| protocol. When running locally this is an account the user logged in via |
| "luci-auth login ..." command prior to running the recipe. |
| |
| — **def [from\_credentials\_json](/recipe_modules/service_account/api.py#66)(self, key_path):** |
| |
| Returns a service account based on a JSON credentials file. |
| |
| This is the file generated by Cloud Console when creating a service account |
| key. It contains the private key inside. |
| |
| Args: |
| key_path: (str|Path) object pointing to a service account JSON key. |
| ### *recipe_modules* / [step](/recipe_modules/step) |
| |
| [DEPS](/recipe_modules/step/__init__.py#10): [context](#recipe_modules-context), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [proto](#recipe_modules-proto) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Step is the primary API for running steps (external programs, etc.) |
| |
| #### **class [StepApi](/recipe_modules/step/api.py#26)([RecipeApiPlain](/recipe_engine/recipe_api.py#738)):** |
| |
|   **@property**<br>— **def [InfraFailure](/recipe_modules/step/api.py#145)(self):** |
| |
| InfraFailure is a subclass of StepFailure, and will translate to a purple |
| build. |
| |
| This exception is raised from steps which are marked as `infra_step`s when |
| they fail. |
| |
|   **@property**<br>— **def [MAX\_CPU](/recipe_modules/step/api.py#117)(self):** |
| |
| Returns the maximum number of millicores this system has. |
| |
|   **@property**<br>— **def [MAX\_MEMORY](/recipe_modules/step/api.py#122)(self):** |
| |
| Returns the maximum amount of memory on the system in MB. |
| |
| — **def [ResourceCost](/recipe_modules/step/api.py#50)(self, cpu=500, memory=50, disk=0, net=0):** |
| |
| A structure defining the resources that a given step may need. |
| |
| The four resources are: |
| |
| * cpu (measured in millicores): The amount of cpu the step is expected to |
| take. Defaults to 500. |
| * memory (measured in MB): The amount of memory the step is expected to |
| take. Defaults to 50. |
| * disk (as percentage of max disk bandwidth): The amount of "disk |
| bandwidth" the step is expected to take. This is a very simplified |
| percentage covering IOPS, read/write bandwidth, seek time, etc. At 100, |
| the step will run exclusively w.r.t. all other steps having a `disk` |
| cost. At 0, the step will run regardless of other steps with disk cost. |
| * net (as percentage of max net bandwidth): The amount of "net |
| bandwidth" the step is expected to take. This is a very simplified |
| percentage covering bandwidth, latency, etc. and is indescriminate of |
| the remote hosts, network conditions, etc. At 100, the step will run |
| exclusively w.r.t. all other steps having a `net` cost. At 0, the step |
| will run regardless of other steps with net cost. |
| |
| A step will run when ALL of the resources are simultaneously available. The |
| Recipe Engine currently uses a greedy scheduling algorithm for picking the |
| next step to run. If multiple steps are waiting for resources, this will |
| pick the largest (cpu, memory, disk, net) step which fits the currently |
| available resources and run that. The theory is that, assuming: |
| |
| * Recipes are finite tasks, which aim to run ALL of their steps, and want |
| to do so as quickly as possible. This is not a typical OS scheduling |
| scenario where there's some window of time over which the recipe needs |
| to be 'fair'. Additionally, recipes run with finite timeouts attached. |
| * The duration of a given step is the same regardless of when during the |
| build it runs (i.e. running a step now vs later should take roughly the |
| same amount of time). |
| |
| It's therefore optimal to run steps as quickly as possible, to avoid wasting |
| the timeout attached to the build. |
| |
| Note that `bool(ResourceCost(...))` is defined to be True if the |
| ResourceCost has at least one non-zero cost, and False otherwise. |
| |
| Args: |
| * cpu (int): Millicores that this step will take to run. See `MAX_CPU` |
| helper. A value higher than the maximum number of millicores on the system |
| is equivalent to `MAX_CPU`. |
| * memory (int): Number of Mebibytes of memory this step will take to run. |
| See `MAX_MEMORY` as a helper. A value higher than the maximum amount of |
| memory on the system is equivalent to `MAX_MEMORY`. |
| * disk (int [0..100]): The disk IO resource this step will take as |
| a percentage of the maximum system disk IO. |
| * net (int [0..100]): The network IO resource this step will take as |
| a percentage of the maximum system network IO. |
| |
| Returns: |
| a ResourceCost suitable for use with `api.step(...)`'s cost kwarg. Note |
| that passing `None` to api.step for the cost kwarg is equivalent to |
| `ResourceCost(0, 0, 0, 0)`. |
| |
|   **@property**<br>— **def [StepFailure](/recipe_modules/step/api.py#127)(self):** |
| |
| This is the base Exception class for all step failures. |
| |
| It can be manually raised from recipe code to cause the build to turn red. |
| |
| Usage: |
| * `raise api.StepFailure("some reason")` |
| * `except api.StepFailure:` |
| |
|   **@property**<br>— **def [StepWarning](/recipe_modules/step/api.py#139)(self):** |
| |
| StepWarning is a subclass of StepFailure, and will translate to a yellow |
| build. |
| |
|   **@recipe_api.composite_step**<br>— **def [\_\_call\_\_](/recipe_modules/step/api.py#617)(self, name, cmd, ok_ret=(0,), infra_step=False, raise_on_failure=True, wrapper=(), timeout=None, stdout=None, stderr=None, stdin=None, step_test_data=None, cost=_ResourceCost()):** |
| |
| Runs a step (subprocess). |
| |
| Args: |
| * name (string): The name of this step. |
| * cmd (None|List[int|string|Placeholder|Path]): The program arguments to |
| run. If None or an empty list, then this step just shows up in the UI |
| but doesn't run anything. |
| * Numbers and strings are used as-is. |
| * Placeholders are 'rendered' to a string (using their render() method). |
| Placeholders are e.g. `api.json.input()` or `api.raw_io.output()`. |
| Typically rendering these turns into an absolute path to a file on |
| disk, which the program is expected to read from/write to. |
| * Paths are rendered to an OS-native absolute path. |
| * ok_ret (tuple or set of ints, 'any', 'all'): allowed return codes. Any |
| unexpected return codes will cause an exception to be thrown. If you |
| pass in the value 'any' or 'all', the engine will allow any return code |
| to be returned. Defaults to {0}. |
| * infra_step: Whether or not this is an infrastructure step. |
| Failing infrastructure steps will place the step in an EXCEPTION state |
| and if raise_on_failure is True an InfraFailure will be raised. |
| * raise_on_failure: Whether or not the step will raise on failure. If |
| True, a StepFailure will be raised if the step's status is FAILURE, an |
| InfraFailure will be raised if the step's status is EXCEPTION and a |
| StepWarning will be raised if the step's status is WARNING. Regardless |
| of the value of this argument, an InfraFailure will be raised if the |
| step is canceled. |
| * wrapper: If supplied, a command to prepend to the executed step as a |
| command wrapper. |
| * timeout: If supplied, the recipe engine will kill the step after the |
| specified number of seconds. Also accepts a datetime.timedelta. |
| * stdout: Placeholder to put step stdout into. If used, stdout won't |
| appear in annotator's stdout. |
| * stderr: Placeholder to put step stderr into. If used, stderr won't |
| appear in annotator's stderr. |
| * stdin: Placeholder to read step stdin from. |
| * step_test_data (func -> recipe_test_api.StepTestData): A factory which |
| returns a StepTestData object that will be used as the default test |
| data for this step. The recipe author can override/augment this object |
| in the GenTests function. |
| * cost (None|ResourceCost): The estimated system resource cost of this |
| step. See `ResourceCost()`. The recipe_engine will prevent more than the |
| machine's maximum resources worth of steps from running at once (i.e. |
| steps will wait until there's enough resource available before |
| starting). Waiting subprocesses are unblocked in capacity-available |
| order. This means it's possible for pending tasks with large |
| requirements to 'starve' temporarily while other smaller cost tasks |
| run in parallel. Equal-weight tasks will start in FIFO order. Steps |
| with a cost of None will NEVER wait (which is the equivalent of |
| `ResourceCost()`). Defaults to `ResourceCost(cpu=500, memory=50)`. |
| |
| Returns a `step_data.StepData` for the running step. |
| |
|   **@property**<br>— **def [active\_result](/recipe_modules/step/api.py#155)(self):** |
| |
| The currently active (open) result from the last step that was run. This |
| is a `step_data.StepData` object. |
| |
| Allows you to do things like: |
| ```python |
| try: |
| api.step('run test', [..., api.json.output()]) |
| finally: |
| result = api.step.active_result |
| if result.json.output: |
| new_step_text = result.json.output['step_text'] |
| api.step.active_result.presentation.step_text = new_step_text |
| ``` |
| |
| This will update the step_text of the test, even if the test fails. Without |
| this api, the above code would look like: |
| |
| ```python |
| try: |
| result = api.step('run test', [..., api.json.output()]) |
| except api.StepFailure as f: |
| result = f.result |
| raise |
| finally: |
| if result.json.output: |
| new_step_text = result.json.output['step_text'] |
| api.step.active_result.presentation.step_text = new_step_text |
| ``` |
| |
| — **def [close\_non\_nest\_step](/recipe_modules/step/api.py#188)(self):** |
| |
| Call this to explicitly terminate the currently open non-nest step. |
| |
| After calling this, api.step.active_step will return the current nest step |
| context (if any). |
| |
| No-op if there's no currently active non-nest step. |
| |
|   **@property**<br>— **def [defer\_results](/recipe_modules/step/api.py#356)(self):** |
| |
| See recipe_api.py for docs. |
| |
| — **def [empty](/recipe_modules/step/api.py#316)(self, name, status='SUCCESS', step_text=None, log_text=None, log_name='stdout', raise_on_failure=True):** |
| |
| Runs an "empty" step (one without any command). |
| |
| This can be useful to insert a status step/message in the UI, or summarize |
| some computation which occurred inside the recipe logic. |
| |
| Args: |
| name (str) - The name of the step. |
| status step.(INFRA_FAILURE|FAILURE|SUCCESS) - The initial status for this |
| step. |
| step_text (str) - Some text to set for the "step_text" on the presentation |
| of this step. |
| log_text (str|list(str)) - Some text to set for the log of this step. If |
| this is a list(str), will be treated as separate lines of the log. |
| Otherwise newlines will be respected. |
| log_name (str) - The name of the log to output `log_text` to. |
| raise_on_failure (bool) - If set, and `status` is not SUCCESS, raise |
| the appropriate exception. |
| |
| Returns step_data.StepData. |
| |
|   **@contextlib.contextmanager**<br>— **def [nest](/recipe_modules/step/api.py#222)(self, name, status='worst'):** |
| |
| Nest allows you to nest steps hierarchically on the build UI. |
| |
| This generates a dummy step with the provided name in the current namespace. |
| All other steps run within this `with` statement will be nested inside of |
| this dummy step. Nested steps can also nest within each other. |
| |
| The presentation for the dummy step can be updated (e.g. to add step_text, |
| step_links, etc.) or set the step's status. If you do not set the status, |
| it will be calculated from the status' of all the steps run within this one |
| according to the `status` algorithm selected. |
| 1. If there's an active exception when leaving the `with` statement, the |
| status will be one of FAILURE, WARNING or EXCEPTION (depending on the |
| type of exception). |
| 2. Otherwise: |
| 1. If the status algorithm is 'worst', it will assume the status of the |
| worst child step. This is useful for when your nest step runs e.g. |
| a bunch of test shards. If any shard fails, you want the nest step |
| to fail as well. |
| 2. If the status algorithm is 'last', it will assume the status of the |
| last child step. This is useful for when you're using the nest step |
| to encapsulate a sequence operation where only the last step's |
| status really matters. |
| |
| *** promo |
| NOTE: Because the nest step allows action on the result of all steps run |
| within it, a nest step will wait for ALL recipe code within it (including |
| greenlets spawned with api.future.spawn!). |
| *** |
| |
| Example: |
| |
| # status='worst' |
| with api.step.nest('run test'): |
| with api.step.defer_results(): |
| for shard in range(4): |
| run_shard('test', shard) |
| |
| # status='last' |
| with api.step.nest('do upload'): |
| for attempt in range(4): |
| try: |
| do_upload() # first one fails, but second succeeds. |
| except api.step.StepFailure: |
| pass |
| else: |
| report_error() |
| |
| # manually adjust status |
| with api.step.nest('custom thing') as presentation: |
| # stuff! |
| presentation.status = 'FAILURE' # or whatever |
| |
| *** note |
| **DEPRECATED**: The object yielded also has a '.presentation' field to be |
| compatible with code that treats the yielded object as a StepData object. If |
| you see such code, please update it to treat the yielded object directly as |
| StepPresentation instead. |
| *** |
| |
| Args: |
| * name (str): The name of this step. |
| * status ('worst'|'last'): The algorithm to use to pick a |
| `presentation.status` if the recipe doesn't set one explicitly. |
| |
| Yields a StepPresentation for this dummy step, which you may update as you |
| please. |
| |
| — **def [raise\_on\_failure](/recipe_modules/step/api.py#464)(self, result, status_override=None):** |
| |
| Raise an appropriate exception if a step is not successful. |
| |
| Arguments: |
| * result - The step result. |
| * status_override - An optional status value to override the status |
| present on the result of the step. This allows for the exception to |
| include information about the result and be based off of the initial |
| status even if the step's status has subsequently been changed, which |
| aligns with the behavior that would occur if a step was executed with |
| raise_on_failure=True and a step's status was changed in a finally |
| block. |
| |
| Returns: |
| If the step's status is SUCCESS, the step result will be returned. |
| |
| Raises: |
| * StepFailure if the step's status is FAILURE |
| * StepWarning if the step's status is WARNING |
| * InfraFailure if the step's status is EXCEPTION or CANCELED |
| |
|   **@recipe_api.composite_step**<br>— **def [sub\_build](/recipe_modules/step/api.py#495)(self, name, cmd, build, raise_on_failure=True, output_path=None, legacy_global_namespace=False, timeout=None, step_test_data=None, cost=_ResourceCost()):** |
| |
| Launch a sub-build by invoking a LUCI executable. All steps in the |
| sub-build will appear as child steps of this step (Merge Step). |
| |
| See protocol: https://go.chromium.org/luci/luciexe |
| |
| Example: |
| |
| ```python |
| run_exe = api.cipd.ensure_tool(...) # Install LUCI executable `run_exe` |
| |
| # Basic Example: launch `run_exe` with empty initial build and |
| # default options. |
| ret = api.sub_build("launch sub build", [run_exe], build_pb2.Build()) |
| sub_build = ret.step.sub_build # access final build proto result |
| |
| # Example: launch `run_exe` with input build to recipe and customized |
| # output path, cwd and cache directory. |
| with api.context( |
| # Change the cwd of the launched LUCI executable |
| cwd=api.path['start_dir'].join('subdir'), |
| # Change the cache_dir of the launched LUCI executable. Defaults to |
| # api.path['cache'] if unchanged. |
| luciexe=sections_pb2.LUCIExe(cache_dir=api.path['cache'].join('sub')), |
| ): |
| # Command executed: |
| # `/path/to/run_exe --output [CLEANUP]/build.json --foo bar baz` |
| ret = api.sub_build("launch sub build", |
| [run_exe, '--foo', 'bar', 'baz'], |
| api.buildbucket.build, |
| output_path=api.path['cleanup'].join('build.json')) |
| sub_build = ret.step.sub_build # access final build proto result |
| ``` |
| |
| Args: |
| * name (str): The name of this step. |
| * cmd (List[int|string|Placeholder|Path]): Same as the `cmd` parameter in |
| `__call__` method except that None is NOT allowed. cmd[0] MUST denote a |
| LUCI executable. The `--output` flag and its value should NOT be |
| provided in the list. It should be provided via keyword arg |
| `output_path` instead. |
| * build (build_pb2.Build): The initial build state that the launched |
| luciexe will start with. This method will clone the input build, modify |
| the clone's fields and pass the clone to luciexe (see 'Invocation' |
| section in http://go.chromium.org/luci/luciexe for what modification |
| will be done). |
| * raise_on_failure: Whether or not the step will raise on failure. If |
| True, a StepFailure will be raised if the step's status is FAILURE, an |
| InfraFailure will be raised if the step's status is EXCEPTION and a |
| StepWarning will be raised if the step's status is WARNING. Regardless |
| of the value of this argument, an InfraFailure will be raised if the |
| step is canceled. |
| * output_path (None|str|Path): The value of the `--output` flag. If |
| provided, it should be a path to a non-existent file (its directory |
| MUST exist). The extension of the path dictates the encoding format of |
| final build proto (See `EXT_TO_CODEC`). If not provided, the output |
| will be a temp file with binary encoding. |
| * legacy_global_namespace (bool): If set, activates legacy global |
| namespace merging. Only meant for legacy ChromeOS builders. |
| See crbug.com/1310155. |
| * timeout (None|int|float|datetime.timedelta): Same as the `timeout` |
| parameter in `__call__` method. |
| * step_test_data(Callable[[], recipe_test_api.StepTestData]): Same as the |
| `step_test_data` parameter in `__call__` method. |
| * cost (None|ResourceCost): Same as the `cost` parameter in `__call__` |
| method. |
| |
| Returns a `step_data.StepData` for the finished step. The final build proto |
| object can be accessed via `ret.step.sub_build`. The build is guaranteed to |
| be present (i.e. not None) with a terminal build status. |
| |
| Raises `StepFailure` if the sub-build reports FAILURE status. |
| Raises `InfraFailure` if the sub-build reports INFRA_FAILURE or CANCELED |
| status. |
| ### *recipe_modules* / [swarming](/recipe_modules/swarming) |
| |
| [DEPS](/recipe_modules/swarming/__init__.py#9): [buildbucket](#recipe_modules-buildbucket), [cas](#recipe_modules-cas), [cipd](#recipe_modules-cipd), [context](#recipe_modules-context), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| #### **class [SwarmingApi](/recipe_modules/swarming/api.py#1118)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| API for interacting with swarming. |
| |
| The tool's source lives at |
| http://go.chromium.org/luci/client/cmd/swarming. |
| |
| This module will deploy the client to [CACHE]/swarming_client/; users should |
| add this path to the named cache for their builder. |
| |
|   **@property**<br>— **def [bot\_id](/recipe_modules/swarming/api.py#1141)(self):** |
| |
| Swarming bot ID executing this task. |
| |
| — **def [collect](/recipe_modules/swarming/api.py#1270)(self, name, tasks, output_dir=None, task_output_stdout='json', timeout=None, eager=False, verbose=False):** |
| |
| Waits on a set of Swarming tasks. |
| |
| Args: |
| name (str): The name of the step. |
| tasks (Iterable(str|TaskRequestMetadata)): A list of ids or metadata |
| objects corresponding to tasks to wait |
| output_dir (Path|None): Where to download the tasks' isolated outputs. If |
| set to None, they will not be downloaded; else, a given task's outputs |
| will be downloaded to output_dir/<task id>/. |
| task_output_stdout (str): Where to output each task's output. Must be one |
| of 'none', 'json', 'console' or 'all'. |
| timeout (str|None): The duration for which to wait on the tasks to finish. |
| If set to None, there will be no timeout; else, timeout follows the |
| format described by https://golang.org/pkg/time/#ParseDuration. |
| eager (bool): Whether to return as soon as the first task finishes, |
| instead of waiting for all tasks to finish. |
| verbose (bool): Whether to use verbose logs. |
| |
| Returns: |
| A list of TaskResult objects. |
| |
|   **@property**<br>— **def [current\_server](/recipe_modules/swarming/api.py#1151)(self):** |
| |
| Swarming server executing this task. |
| |
| — **def [ensure\_client](/recipe_modules/swarming/api.py#1171)(self):** |
| |
| — **def [initialize](/recipe_modules/swarming/api.py#1156)(self):** |
| |
|   **@contextlib.contextmanager**<br>— **def [on\_path](/recipe_modules/swarming/api.py#1187)(self):** |
| |
| This context manager ensures the go swarming client is available on |
| $PATH. |
| |
| Example: |
| |
| with api.swarming.on_path(): |
| # do your steps which require the swarming binary on path |
| |
| — **def [show\_request](/recipe_modules/swarming/api.py#1359)(self, name, task):** |
| |
| Retrive the TaskRequest for a Swarming task. |
| |
| Args: |
| name (str): The name of the step. |
| task (str|TaskRequestMetadata): Task Id or metadata objects of the |
| swarming task to be retrived. |
| |
| Returns: |
| TaskRequest objects. |
| |
|   **@property**<br>— **def [task\_id](/recipe_modules/swarming/api.py#1146)(self):** |
| |
| This task's Swarming ID. |
| |
| — **def [task\_request](/recipe_modules/swarming/api.py#1201)(self):** |
| |
| Creates a new TaskRequest object. |
| |
| See documentation for TaskRequest/TaskSlice to see how to build this up |
| into a full task. |
| |
| Once your TaskRequest is complete, you can pass it to `trigger` in order to |
| have it start running on the swarming server. |
| |
| — **def [task\_request\_from\_jsonish](/recipe_modules/swarming/api.py#1212)(self, json_d):** |
| |
| Creates a new TaskRequest object from a JSON-serializable dict. |
| |
| The input argument should match the schema as the output of |
| TaskRequest.to_jsonish(). |
| |
| — **def [trigger](/recipe_modules/swarming/api.py#1220)(self, step_name, requests, verbose=False):** |
| |
| Triggers a set of Swarming tasks. |
| |
| Args: |
| step_name (str): The name of the step. |
| requests (seq[TaskRequest]): A sequence of task request objects |
| representing the tasks we want to trigger. |
| verbose (bool): Whether to use verbose logs. |
| |
| Returns: |
| A list of TaskRequestMetadata objects. |
| ### *recipe_modules* / [time](/recipe_modules/time) |
| |
| [DEPS](/recipe_modules/time/__init__.py#7): [random](#recipe_modules-random), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Allows mockable access to the current time. |
| |
| #### **class [TimeApi](/recipe_modules/time/api.py#95)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| — **def [exponential\_retry](/recipe_modules/time/api.py#131)(self, retries, delay, condition=None):** |
| |
| Adds exponential retry to a function. |
| |
| See the 'exponential_retry' function in this module for more docs. |
| |
| — **def [ms\_since\_epoch](/recipe_modules/time/api.py#146)(self):** |
| |
| Returns current timestamp as an int number of milliseconds since epoch. |
| |
| |
| — **def [sleep](/recipe_modules/time/api.py#104)(self, secs, with_step=None, step_result=None):** |
| |
| Suspend execution of |secs| (float) seconds, waiting for GLOBAL_SHUTDOWN. |
| Does nothing in testing. |
| |
| Args: |
| * secs (number) - The number of seconds to sleep. |
| * with_step (bool|None) - If True (or None and secs>60), emits a step to |
| indicate to users that the recipe is sleeping (not just hanging). False |
| suppresses this. |
| * step_result (step_data.StepData|None) - Result of running a step. Should |
| be None if with_step is True or None. |
| |
| — **def [time](/recipe_modules/time/api.py#138)(self):** |
| |
| Returns current timestamp as a float number of seconds since epoch. |
| |
| — **def [utcnow](/recipe_modules/time/api.py#151)(self):** |
| |
| Returns current UTC time as a datetime.datetime. |
| ### *recipe_modules* / [tricium](/recipe_modules/tricium) |
| |
| [DEPS](/recipe_modules/tricium/__init__.py#7): [cipd](#recipe_modules-cipd), [context](#recipe_modules-context), [file](#recipe_modules-file), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [proto](#recipe_modules-proto), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| API for Tricium analyzers to use. |
| |
| This recipe module is intended to support different kinds of |
| analyzer recipes, including: |
| * Recipes that wrap one or more legacy analyzers. |
| * Recipes that accumulate comments one by one. |
| * Recipes that wrap other tools and parse their output. |
| |
| #### **class [TriciumApi](/recipe_modules/tricium/api.py#26)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| TriciumApi provides basic support for Tricium. |
| |
| — **def [\_\_init\_\_](/recipe_modules/tricium/api.py#38)(self, \*\*kwargs):** |
| |
| Sets up the API. |
| |
| Initializes an empty list of comments for use with |
| add_comment and write_comments. |
| |
| — **def [add\_comment](/recipe_modules/tricium/api.py#47)(self, category, message, path, start_line=0, end_line=0, start_char=0, end_char=0, suggestions=()):** |
| |
| Adds one comment to accumulate. |
| |
| For semantics of start_line, start_char, end_line, end_char, see Gerrit doc |
| https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#comment-range |
| |
| — **def [run\_legacy](/recipe_modules/tricium/api.py#138)(self, analyzers, input_base, affected_files, commit_message, emit=True):** |
| |
| Runs legacy analyzers. |
| |
| This function internally accumulates the comments from the analyzers it |
| runs to the same global storage used by `add_comment()`. By default it |
| emits comments from legacy analyzers to the tricium output property, |
| along with any comments previously created by calling `add_comment()` |
| directly, after running all the specified analyzers. |
| |
| Args: |
| * analyzers (List(LegacyAnalyer)): Analyzers to run. |
| * input_base (Path): The Tricium input dir, generally a checkout base. |
| * affected_files (List(str)): Paths of files in the change, relative |
| to input_base. |
| * commit_message (str): Commit message from Gerrit. |
| * emit (bool): Whether to write results to the tricium output |
| property. If unset, the caller will be responsible for calling |
| `write_comments` to emit the comments added by the legacy analyzers. |
| This is useful for recipes that need to run a mixture of custom |
| analyzers (using `add_comment()` to store comments) and legacy |
| analyzers. |
| |
|   **@staticmethod**<br>— **def [validate\_comment](/recipe_modules/tricium/api.py#74)(comment):** |
| |
| Validates comment to comply with Tricium/Gerrit requirements. |
| |
| Raise ValueError on the first detected problem. |
| |
| — **def [write\_comments](/recipe_modules/tricium/api.py#115)(self):** |
| |
| Emit the results accumulated by `add_comment` and `run_legacy`. |
| ### *recipe_modules* / [url](/recipe_modules/url) |
| |
| [DEPS](/recipe_modules/url/__init__.py#7): [context](#recipe_modules-context), [json](#recipe_modules-json), [path](#recipe_modules-path), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Methods for interacting with HTTP(s) URLs. |
| |
| #### **class [UrlApi](/recipe_modules/url/api.py#16)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| — **def [get\_file](/recipe_modules/url/api.py#131)(self, url, path, step_name=None, headers=None, transient_retry=True, strip_prefix=None, timeout=None):** |
| |
| GET data at given URL and writes it to file. |
| |
| Args: |
| * url: URL to request. |
| * path (Path): the Path where the content will be written. |
| * step_name: optional step name, 'GET <url>' by default. |
| * headers: a {header_name: value} dictionary for HTTP headers. |
| * transient_retry (bool or int): Determines how transient HTTP errorts |
| (>500) will be retried. If True (default), errors will be retried up |
| to 10 times. If False, no transient retries will occur. If an integer |
| is supplied, this is the number of transient retries to perform. All |
| retries have exponential backoff applied. |
| * strip_prefix (str or None): If not None, this prefix must be present at |
| the beginning of the response, and will be stripped from the resulting |
| content (e.g., GERRIT_JSON_PREFIX). |
| * timeout: Timeout (see step.__call__). |
| |
| Returns (UrlApi.Response): |
| Response with "path" as its "output" value. |
| |
| Raises: |
| * HTTPError, InfraHTTPError: if the request failed. |
| * ValueError: If the request was invalid. |
| |
| — **def [get\_json](/recipe_modules/url/api.py#187)(self, url, step_name=None, headers=None, transient_retry=True, strip_prefix=None, log=False, timeout=None, default_test_data=None):** |
| |
| GET data at given URL and writes it to file. |
| |
| Args: |
| * url: URL to request. |
| * step_name: optional step name, 'GET <url>' by default. |
| * headers: a {header_name: value} dictionary for HTTP headers. |
| * transient_retry (bool or int): Determines how transient HTTP errorts |
| (>500) will be retried. If True (default), errors will be retried up |
| to 10 times. If False, no transient retries will occur. If an integer |
| is supplied, this is the number of transient retries to perform. All |
| retries have exponential backoff applied. |
| * strip_prefix (str or None): If not None, this prefix must be present at |
| the beginning of the response, and will be stripped from the resulting |
| content (e.g., GERRIT_JSON_PREFIX). |
| * log (bool): If True, emit the JSON content as a log. |
| * timeout: Timeout (see step.__call__). |
| * default_test_data (jsonish): If provided, use this as the unmarshalled |
| JSON result when testing if no overriding data is available. |
| |
| Returns (UrlApi.Response): Response with the JSON as its "output" value. |
| |
| Raises: |
| * HTTPError, InfraHTTPError: if the request failed. |
| * ValueError: If the request was invalid. |
| |
| — **def [get\_text](/recipe_modules/url/api.py#160)(self, url, step_name=None, headers=None, transient_retry=True, timeout=None, default_test_data=None):** |
| |
| GET data at given URL and writes it to file. |
| |
| Args: |
| * url: URL to request. |
| * step_name: optional step name, 'GET <url>' by default. |
| * headers: a {header_name: value} dictionary for HTTP headers. |
| * transient_retry (bool or int): Determines how transient HTTP errorts |
| (>500) will be retried. If True (default), errors will be retried up |
| to 10 times. If False, no transient retries will occur. If an integer |
| is supplied, this is the number of transient retries to perform. All |
| retries have exponential backoff applied. |
| * timeout: Timeout (see step.__call__). |
| * default_test_data (str): If provided, use this as the text output when |
| testing if no overriding data is available. |
| |
| Returns (UrlApi.Response): Response with the content as its output value. |
| |
| Raises: |
| * HTTPError, InfraHTTPError: if the request failed. |
| * ValueError: If the request was invalid. |
| |
| — **def [join](/recipe_modules/url/api.py#93)(self, \*parts):** |
| |
| Constructs a URL path from composite parts. |
| |
| Args: |
| * parts (str...): Strings to concastenate. Any leading or trailing slashes |
| will be stripped from intermediate strings to ensure that they join |
| together. Trailing slashes will not be stripped from the last part. |
| |
| — **def [validate\_url](/recipe_modules/url/api.py#109)(self, v):** |
| |
| Validates that "v" is a valid URL. |
| |
| A valid URL has a scheme and netloc, and must begin with HTTP or HTTPS. |
| |
| Args: |
| * v (str): The URL to validate. |
| |
| Returns (bool): True if the URL is considered secure, False if not. |
| |
| Raises: |
| ValueError: if "v" is not valid. |
| ### *recipe_modules* / [uuid](/recipe_modules/uuid) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Allows test-repeatable access to a random UUID. |
| |
| #### **class [UuidApi](/recipe_modules/uuid/api.py#11)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
| — **def [random](/recipe_modules/uuid/api.py#20)(self):** |
| |
| Returns a random UUID string. |
| ### *recipe_modules* / [version](/recipe_modules/version) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Thin API for parsing semver strings into comparable object. |
| |
| #### **class [VersionApi](/recipe_modules/version/api.py#12)([RecipeApi](/recipe_engine/recipe_api.py#886)):** |
| |
|   **@staticmethod**<br>— **def [parse](/recipe_modules/version/api.py#14)(version):** |
| |
| Parse implements PEP 440 parsing for semvers. |
| |
| If `version` is strictly parseable as PEP 440, this returns a Version |
| object. Otherwise it does a 'loose' parse, just extracting numerals from |
| version. |
| |
| You can read more about how this works at: |
| https://setuptools.readthedocs.io/en/latest/pkg_resources.html#parsing-utilities |
| ### *recipe_modules* / [warning](/recipe_modules/warning) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Allows recipe modules to issue warnings in simulation test. |
| |
| #### **class [WarningApi](/recipe_modules/warning/api.py#12)([RecipeApiPlain](/recipe_engine/recipe_api.py#738)):** |
| |
|   **@recipe_api.escape_all_warnings**<br>— **def [issue](/recipe_modules/warning/api.py#15)(self, name):** |
| |
| Issues an execution warning. |
| |
| `name` MAY either be a fully qualified "repo_name/WARNING_NAME" or a short |
| "WARNING_NAME". If it's a short name, then the "repo_name" will be |
| determined from the location of the file issuing the warning (i.e. if the |
| issue() comes from a file in repo_X, then "WARNING_NAME" will be |
| transformed to "repo_X/WARNING_NAME"). |
| |
| It is recommended to use the short name if the warning is defined in the |
| same repo as the issue() call. |
| ## Recipes |
| |
| ### *recipes* / [archive:examples/full](/recipe_modules/archive/examples/full.py) |
| |
| [DEPS](/recipe_modules/archive/examples/full.py#9): [archive](#recipe_modules-archive), [context](#recipe_modules-context), [file](#recipe_modules-file), [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/archive/examples/full.py#21)(api):** |
| ### *recipes* / [assertions:tests/assert-raises](/recipe_modules/assertions/tests/assert-raises.py) |
| |
| [DEPS](/recipe_modules/assertions/tests/assert-raises.py#9): [assertions](#recipe_modules-assertions), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/assertions/tests/assert-raises.py#18)(api):** |
| ### *recipes* / [assertions:tests/assert\_count\_equal](/recipe_modules/assertions/tests/assert_count_equal.py) |
| |
| [DEPS](/recipe_modules/assertions/tests/assert_count_equal.py#9): [assertions](#recipe_modules-assertions) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/assertions/tests/assert_count_equal.py#14)(api):** |
| ### *recipes* / [assertions:tests/assertions](/recipe_modules/assertions/tests/assertions.py) |
| |
| [DEPS](/recipe_modules/assertions/tests/assertions.py#9): [assertions](#recipe_modules-assertions), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/assertions/tests/assertions.py#15)(api):** |
| ### *recipes* / [assertions:tests/attribute\_error](/recipe_modules/assertions/tests/attribute_error.py) |
| |
| [DEPS](/recipe_modules/assertions/tests/attribute_error.py#9): [assertions](#recipe_modules-assertions), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/assertions/tests/attribute_error.py#15)(api):** |
| ### *recipes* / [assertions:tests/long\_message](/recipe_modules/assertions/tests/long_message.py) |
| |
| [DEPS](/recipe_modules/assertions/tests/long_message.py#9): [assertions](#recipe_modules-assertions), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/assertions/tests/long_message.py#14)(api):** |
| ### *recipes* / [assertions:tests/max\_diff](/recipe_modules/assertions/tests/max_diff.py) |
| |
| [DEPS](/recipe_modules/assertions/tests/max_diff.py#9): [assertions](#recipe_modules-assertions), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/assertions/tests/max_diff.py#15)(api):** |
| ### *recipes* / [bcid\_reporter:examples/usage](/recipe_modules/bcid_reporter/examples/usage.py) |
| |
| [DEPS](/recipe_modules/bcid_reporter/examples/usage.py#7): [bcid\_reporter](#recipe_modules-bcid_reporter), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/bcid_reporter/examples/usage.py#12)(api):** |
| ### *recipes* / [buildbucket:examples/full](/recipe_modules/buildbucket/examples/full.py) |
| |
| [DEPS](/recipe_modules/buildbucket/examples/full.py#16): [buildbucket](#recipe_modules-buildbucket), [json](#recipe_modules-json), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This file is a recipe demonstrating the buildbucket recipe module. |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/examples/full.py#27)(api):** |
| ### *recipes* / [buildbucket:run/multi](/recipe_modules/buildbucket/run/multi.py) |
| |
| [DEPS](/recipe_modules/buildbucket/run/multi.py#13): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [swarming](#recipe_modules-swarming) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY3 |
| |
| Launches multiple builds at the same revision. |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/run/multi.py#31)(api, build_requests, collect_builds):** |
| ### *recipes* / [buildbucket:tests/add\_tags](/recipe_modules/buildbucket/tests/add_tags.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/add_tags.py#7): [buildbucket](#recipe_modules-buildbucket), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/add_tags.py#13)(api):** |
| ### *recipes* / [buildbucket:tests/build](/recipe_modules/buildbucket/tests/build.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/build.py#22): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/build.py#30)(api):** |
| ### *recipes* / [buildbucket:tests/cancel](/recipe_modules/buildbucket/tests/cancel.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/cancel.py#12): [buildbucket](#recipe_modules-buildbucket) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/cancel.py#16)(api):** |
| ### *recipes* / [buildbucket:tests/collect](/recipe_modules/buildbucket/tests/collect.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/collect.py#7): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/collect.py#13)(api):** |
| ### *recipes* / [buildbucket:tests/output\_commit](/recipe_modules/buildbucket/tests/output_commit.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/output_commit.py#11): [buildbucket](#recipe_modules-buildbucket), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This recipe tests the buildbucket.set_output_gitiles_commit function. |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/output_commit.py#20)(api):** |
| ### *recipes* / [buildbucket:tests/schedule](/recipe_modules/buildbucket/tests/schedule.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/schedule.py#14): [buildbucket](#recipe_modules-buildbucket), [json](#recipe_modules-json), [properties](#recipe_modules-properties), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/schedule.py#23)(api):** |
| ### *recipes* / [buildbucket:tests/search](/recipe_modules/buildbucket/tests/search.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/search.py#14): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/search.py#23)(api):** |
| ### *recipes* / [cas:examples/full](/recipe_modules/cas/examples/full.py) |
| |
| [DEPS](/recipe_modules/cas/examples/full.py#7): [cas](#recipe_modules-cas), [file](#recipe_modules-file), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cas/examples/full.py#17)(api):** |
| ### *recipes* / [cas\_input:examples/full](/recipe_modules/cas_input/examples/full.py) |
| |
| [DEPS](/recipe_modules/cas_input/examples/full.py#7): [cas\_input](#recipe_modules-cas_input), [path](#recipe_modules-path), [properties](#recipe_modules-properties) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cas_input/examples/full.py#18)(api):** |
| ### *recipes* / [change\_verifier:tests/search](/recipe_modules/change_verifier/tests/search.py) |
| |
| [DEPS](/recipe_modules/change_verifier/tests/search.py#10): [change\_verifier](#recipe_modules-change_verifier), [proto](#recipe_modules-proto) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/change_verifier/tests/search.py#16)(api):** |
| |
| — **def [make\_runs](/recipe_modules/change_verifier/tests/search.py#36)(count=1):** |
| |
| Generates response Runs for a test. |
| ### *recipes* / [cipd:examples/full](/recipe_modules/cipd/examples/full.py) |
| |
| [DEPS](/recipe_modules/cipd/examples/full.py#11): [cipd](#recipe_modules-cipd), [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cipd/examples/full.py#38)(api, use_pkg, pkg_files, pkg_dirs, pkg_vars, ver_files, install_mode, refs, tags, metadata, max_threads):** |
| ### *recipes* / [commit\_position:examples/full](/recipe_modules/commit_position/examples/full.py) |
| |
| [DEPS](/recipe_modules/commit_position/examples/full.py#7): [commit\_position](#recipe_modules-commit_position), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/commit_position/examples/full.py#13)(api):** |
| ### *recipes* / [context:examples/full](/recipe_modules/context/examples/full.py) |
| |
| [DEPS](/recipe_modules/context/examples/full.py#11): [context](#recipe_modules-context), [path](#recipe_modules-path), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step), [time](#recipe_modules-time) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/context/examples/full.py#20)(api):** |
| ### *recipes* / [context:tests/cwd](/recipe_modules/context/tests/cwd.py) |
| |
| [DEPS](/recipe_modules/context/tests/cwd.py#7): [context](#recipe_modules-context), [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/context/tests/cwd.py#13)(api):** |
| ### *recipes* / [context:tests/env](/recipe_modules/context/tests/env.py) |
| |
| [DEPS](/recipe_modules/context/tests/env.py#7): [context](#recipe_modules-context), [path](#recipe_modules-path), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/context/tests/env.py#21)(api):** |
| ### *recipes* / [context:tests/greenlet](/recipe_modules/context/tests/greenlet.py) |
| |
| [DEPS](/recipe_modules/context/tests/greenlet.py#7): [context](#recipe_modules-context), [futures](#recipe_modules-futures), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/context/tests/greenlet.py#13)(api):** |
| ### *recipes* / [context:tests/infra\_step](/recipe_modules/context/tests/infra_step.py) |
| |
| [DEPS](/recipe_modules/context/tests/infra_step.py#7): [context](#recipe_modules-context), [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/context/tests/infra_step.py#13)(api):** |
| ### *recipes* / [context:tests/luci\_context](/recipe_modules/context/tests/luci_context.py) |
| |
| [DEPS](/recipe_modules/context/tests/luci_context.py#9): [assertions](#recipe_modules-assertions), [context](#recipe_modules-context), [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/context/tests/luci_context.py#16)(api):** |
| ### *recipes* / [cq:examples/ordered\_cls](/recipe_modules/cq/examples/ordered_cls.py) |
| |
| [DEPS](/recipe_modules/cq/examples/ordered_cls.py#12): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [cq](#recipe_modules-cq), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/examples/ordered_cls.py#21)(api):** |
| ### *recipes* / [cq:examples/trigger\_child\_builds](/recipe_modules/cq/examples/trigger_child_builds.py) |
| |
| [DEPS](/recipe_modules/cq/examples/trigger_child_builds.py#11): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [cq](#recipe_modules-cq), [json](#recipe_modules-json), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/examples/trigger_child_builds.py#21)(api):** |
| ### *recipes* / [cq:tests/cl\_group\_key](/recipe_modules/cq/tests/cl_group_key.py) |
| |
| [DEPS](/recipe_modules/cq/tests/cl_group_key.py#9): [buildbucket](#recipe_modules-buildbucket), [cq](#recipe_modules-cq) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/tests/cl_group_key.py#19)(api):** |
| ### *recipes* / [cq:tests/do\_not\_retry](/recipe_modules/cq/tests/do_not_retry.py) |
| |
| [DEPS](/recipe_modules/cq/tests/do_not_retry.py#7): [buildbucket](#recipe_modules-buildbucket), [cq](#recipe_modules-cq), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/tests/do_not_retry.py#17)(api):** |
| ### *recipes* / [cq:tests/experimental](/recipe_modules/cq/tests/experimental.py) |
| |
| [DEPS](/recipe_modules/cq/tests/experimental.py#9): [assertions](#recipe_modules-assertions), [cq](#recipe_modules-cq), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/tests/experimental.py#17)(api):** |
| ### *recipes* / [cq:tests/inactive](/recipe_modules/cq/tests/inactive.py) |
| |
| [DEPS](/recipe_modules/cq/tests/inactive.py#9): [assertions](#recipe_modules-assertions), [cq](#recipe_modules-cq), [properties](#recipe_modules-properties) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/tests/inactive.py#16)(api):** |
| ### *recipes* / [cq:tests/mode\_of\_run](/recipe_modules/cq/tests/mode_of_run.py) |
| |
| [DEPS](/recipe_modules/cq/tests/mode_of_run.py#7): [cq](#recipe_modules-cq), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/tests/mode_of_run.py#14)(api):** |
| ### *recipes* / [cq:tests/reuse](/recipe_modules/cq/tests/reuse.py) |
| |
| [DEPS](/recipe_modules/cq/tests/reuse.py#7): [assertions](#recipe_modules-assertions), [cq](#recipe_modules-cq), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/tests/reuse.py#14)(api):** |
| ### *recipes* / [cq:tests/triggered\_build\_ids](/recipe_modules/cq/tests/triggered_build_ids.py) |
| |
| [DEPS](/recipe_modules/cq/tests/triggered_build_ids.py#7): [buildbucket](#recipe_modules-buildbucket), [cq](#recipe_modules-cq), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/cq/tests/triggered_build_ids.py#17)(api):** |
| ### *recipes* / [engine\_tests/bad\_subprocess](/recipes/engine_tests/bad_subprocess.py) |
| |
| [DEPS](/recipes/engine_tests/bad_subprocess.py#9): [platform](#recipe_modules-platform), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that daemons that hang on to STDOUT can't cause the engine to hang. |
| |
| — **def [RunSteps](/recipes/engine_tests/bad_subprocess.py#15)(api):** |
| ### *recipes* / [engine\_tests/comprehensive\_ui](/recipes/engine_tests/comprehensive_ui.py) |
| |
| [DEPS](/recipes/engine_tests/comprehensive_ui.py#13): [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| A fast-running recipe which comprehensively covers all StepPresentation |
| features available in the recipe engine. |
| |
| — **def [RunSteps](/recipes/engine_tests/comprehensive_ui.py#25)(api):** |
| |
| — **def [named\_step](/recipes/engine_tests/comprehensive_ui.py#21)(api, name):** |
| ### *recipes* / [engine\_tests/config\_operations](/recipes/engine_tests/config_operations.py) |
| |
| [DEPS](/recipes/engine_tests/config_operations.py#44): [json](#recipe_modules-json), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that recipes can modify configuration options in various ways. |
| |
| — **def [BaseConfig](/recipes/engine_tests/config_operations.py#15)(\*\*_kwargs):** |
| |
| — **def [DumpRecipeEngineTestConfig](/recipes/engine_tests/config_operations.py#49)(api, config):** |
| |
| — **def [RunSteps](/recipes/engine_tests/config_operations.py#54)(api):** |
| |
|   **@config_ctx()**<br>— **def [test1](/recipes/engine_tests/config_operations.py#30)(c):** |
| |
|   **@config_ctx(includes=['test2a'])**<br>— **def [test2](/recipes/engine_tests/config_operations.py#38)(c):** |
| |
|   **@config_ctx()**<br>— **def [test2a](/recipes/engine_tests/config_operations.py#34)(c):** |
| ### *recipes* / [engine\_tests/early\_termination](/recipes/engine_tests/early_termination.py) |
| |
| [DEPS](/recipes/engine_tests/early_termination.py#10): [file](#recipe_modules-file), [futures](#recipe_modules-futures), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Simple recipe which runs a bunch of subprocesses which react to early |
| termination in different ways. |
| |
| — **def [RunSteps](/recipes/engine_tests/early_termination.py#23)(api, props):** |
| ### *recipes* / [engine\_tests/expect\_exception](/recipes/engine_tests/expect_exception.py) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that step_data can accept multiple specs at once. |
| |
| — **def [RunSteps](/recipes/engine_tests/expect_exception.py#22)(api):** |
| |
|   **@composite_step**<br>— **def [my\_function](/recipes/engine_tests/expect_exception.py#17)():** |
| ### *recipes* / [engine\_tests/failure\_results](/recipes/engine_tests/failure_results.py) |
| |
| [DEPS](/recipes/engine_tests/failure_results.py#14): [json](#recipe_modules-json), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that run_steps is handling recipe failures correctly. |
| |
| — **def [RunSteps](/recipes/engine_tests/failure_results.py#19)(api):** |
| ### *recipes* / [engine\_tests/functools\_partial](/recipes/engine_tests/functools_partial.py) |
| |
| [DEPS](/recipes/engine_tests/functools_partial.py#18): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Engine shouldn't explode when step_test_data gets functools.partial. |
| |
| This is a regression test for a bug caused by this revision: |
| http://src.chromium.org/viewvc/chrome?revision=298072&view=revision |
| |
| When this recipe is run (by run_test.py), the _print_step code is exercised. |
| |
| — **def [RunSteps](/recipes/engine_tests/functools_partial.py#20)(api):** |
| ### *recipes* / [engine\_tests/incorrect\_recipe\_result](/recipes/engine_tests/incorrect_recipe_result.py) |
| |
| [DEPS](/recipes/engine_tests/incorrect_recipe_result.py#14): [json](#recipe_modules-json), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that engine.py can handle unknown recipe results. |
| |
| — **def [RunSteps](/recipes/engine_tests/incorrect_recipe_result.py#22)(api, props):** |
| ### *recipes* / [engine\_tests/long\_sleep](/recipes/engine_tests/long_sleep.py) |
| |
| [DEPS](/recipes/engine_tests/long_sleep.py#8): [futures](#recipe_modules-futures), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Simple recipe which sleeps in a subprocess forever to facilitate early |
| termination tests. |
| |
| — **def [RunSteps](/recipes/engine_tests/long_sleep.py#22)(api, props):** |
| ### *recipes* / [engine\_tests/missing\_start\_dir](/recipes/engine_tests/missing_start_dir.py) |
| |
| [DEPS](/recipes/engine_tests/missing_start_dir.py#9): [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that deleting the current working directory doesn't immediately fail |
| |
| — **def [RunSteps](/recipes/engine_tests/missing_start_dir.py#15)(api):** |
| ### *recipes* / [engine\_tests/module\_injection\_site](/recipes/engine_tests/module_injection_site.py) |
| |
| [DEPS](/recipes/engine_tests/module_injection_site.py#15): [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This test serves to demonstrate that the ModuleInjectionSite object on |
| recipe modules (i.e. the `.m`) also contains a reference to the module which |
| owns it. |
| |
| This was implemented to aid in refactoring some recipes (crbug.com/782142). |
| |
| — **def [RunSteps](/recipes/engine_tests/module_injection_site.py#20)(api):** |
| ### *recipes* / [engine\_tests/multi\_test\_data](/recipes/engine_tests/multi_test_data.py) |
| |
| [DEPS](/recipes/engine_tests/multi_test_data.py#9): [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that step_data can accept multiple specs at once. |
| |
| — **def [RunSteps](/recipes/engine_tests/multi_test_data.py#14)(api):** |
| ### *recipes* / [engine\_tests/multiple\_placeholders](/recipes/engine_tests/multiple_placeholders.py) |
| |
| [DEPS](/recipes/engine_tests/multiple_placeholders.py#11): [assertions](#recipe_modules-assertions), [json](#recipe_modules-json), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests error checking around multiple placeholders in a single step. |
| |
| — **def [RunSteps](/recipes/engine_tests/multiple_placeholders.py#18)(api):** |
| ### *recipes* / [engine\_tests/nonexistent\_command](/recipes/engine_tests/nonexistent_command.py) |
| |
| [DEPS](/recipes/engine_tests/nonexistent_command.py#9): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipes/engine_tests/nonexistent_command.py#14)(api):** |
| ### *recipes* / [engine\_tests/placeholder\_exception](/recipes/engine_tests/placeholder_exception.py) |
| |
| [DEPS](/recipes/engine_tests/placeholder_exception.py#14): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that placeholders can't wreck the world by exhausting the step stack. |
| |
| — **def [RunSteps](/recipes/engine_tests/placeholder_exception.py#26)(api):** |
| ### *recipes* / [engine\_tests/proto\_output\_properties](/recipes/engine_tests/proto_output_properties.py) |
| |
| [DEPS](/recipes/engine_tests/proto_output_properties.py#12): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that output properties can be a proto message. |
| |
| — **def [RunSteps](/recipes/engine_tests/proto_output_properties.py#16)(api):** |
| ### *recipes* / [engine\_tests/proto\_properties](/recipes/engine_tests/proto_properties.py) |
| |
| [DEPS](/recipes/engine_tests/proto_properties.py#9): [assertions](#recipe_modules-assertions), [properties](#recipe_modules-properties) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipes/engine_tests/proto_properties.py#18)(api, properties, env_props):** |
| ### *recipes* / [engine\_tests/recipe\_paths](/recipes/engine_tests/recipe_paths.py) |
| |
| [DEPS](/recipes/engine_tests/recipe_paths.py#9): [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that recipes have access to names, resources and their repo. |
| |
| — **def [RunSteps](/recipes/engine_tests/recipe_paths.py#14)(api):** |
| ### *recipes* / [engine\_tests/sort\_properties](/recipes/engine_tests/sort_properties.py) |
| |
| [DEPS](/recipes/engine_tests/sort_properties.py#9): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that step presentation properties can be ordered. |
| |
| — **def [RunSteps](/recipes/engine_tests/sort_properties.py#13)(api):** |
| ### *recipes* / [engine\_tests/undeclared\_method](/recipes/engine_tests/undeclared_method.py) |
| |
| [DEPS](/recipes/engine_tests/undeclared_method.py#10): [cipd](#recipe_modules-cipd), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipes/engine_tests/undeclared_method.py#22)(api, from_recipe, attribute, module):** |
| ### *recipes* / [engine\_tests/unicode](/recipes/engine_tests/unicode.py) |
| |
| [DEPS](/recipes/engine_tests/unicode.py#8): [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipes/engine_tests/unicode.py#13)(api):** |
| ### *recipes* / [engine\_tests/whitelist\_steps](/recipes/engine_tests/whitelist_steps.py) |
| |
| [DEPS](/recipes/engine_tests/whitelist_steps.py#14): [context](#recipe_modules-context), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| Tests that step_data can accept multiple specs at once. |
| |
| — **def [RunSteps](/recipes/engine_tests/whitelist_steps.py#24)(api, fakeit):** |
| ### *recipes* / [file:examples/compute\_hash](/recipe_modules/file/examples/compute_hash.py) |
| |
| [DEPS](/recipe_modules/file/examples/compute_hash.py#7): [assertions](#recipe_modules-assertions), [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/compute_hash.py#13)(api):** |
| ### *recipes* / [file:examples/copy](/recipe_modules/file/examples/copy.py) |
| |
| [DEPS](/recipe_modules/file/examples/copy.py#7): [file](#recipe_modules-file), [json](#recipe_modules-json), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/copy.py#14)(api):** |
| ### *recipes* / [file:examples/copytree](/recipe_modules/file/examples/copytree.py) |
| |
| [DEPS](/recipe_modules/file/examples/copytree.py#7): [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/copytree.py#13)(api):** |
| ### *recipes* / [file:examples/error](/recipe_modules/file/examples/error.py) |
| |
| [DEPS](/recipe_modules/file/examples/error.py#7): [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/error.py#13)(api):** |
| ### *recipes* / [file:examples/file\_hash](/recipe_modules/file/examples/file_hash.py) |
| |
| [DEPS](/recipe_modules/file/examples/file_hash.py#7): [assertions](#recipe_modules-assertions), [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/file_hash.py#13)(api):** |
| ### *recipes* / [file:examples/flatten\_single\_directories](/recipe_modules/file/examples/flatten_single_directories.py) |
| |
| [DEPS](/recipe_modules/file/examples/flatten_single_directories.py#7): [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/flatten_single_directories.py#13)(api):** |
| ### *recipes* / [file:examples/glob](/recipe_modules/file/examples/glob.py) |
| |
| [DEPS](/recipe_modules/file/examples/glob.py#7): [file](#recipe_modules-file), [json](#recipe_modules-json), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/glob.py#13)(api):** |
| ### *recipes* / [file:examples/handle\_json\_file](/recipe_modules/file/examples/handle_json_file.py) |
| |
| [DEPS](/recipe_modules/file/examples/handle_json_file.py#7): [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/handle_json_file.py#13)(api):** |
| ### *recipes* / [file:examples/listdir](/recipe_modules/file/examples/listdir.py) |
| |
| [DEPS](/recipe_modules/file/examples/listdir.py#7): [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/listdir.py#13)(api):** |
| ### *recipes* / [file:examples/raw\_copy](/recipe_modules/file/examples/raw_copy.py) |
| |
| [DEPS](/recipe_modules/file/examples/raw_copy.py#7): [file](#recipe_modules-file), [json](#recipe_modules-json), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/raw_copy.py#14)(api):** |
| ### *recipes* / [file:examples/read\_write\_proto](/recipe_modules/file/examples/read_write_proto.py) |
| |
| [DEPS](/recipe_modules/file/examples/read_write_proto.py#9): [file](#recipe_modules-file), [path](#recipe_modules-path), [proto](#recipe_modules-proto) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/read_write_proto.py#16)(api):** |
| ### *recipes* / [file:examples/symlink](/recipe_modules/file/examples/symlink.py) |
| |
| [DEPS](/recipe_modules/file/examples/symlink.py#7): [file](#recipe_modules-file), [json](#recipe_modules-json), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/symlink.py#14)(api):** |
| ### *recipes* / [file:examples/truncate](/recipe_modules/file/examples/truncate.py) |
| |
| [DEPS](/recipe_modules/file/examples/truncate.py#7): [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/file/examples/truncate.py#13)(api):** |
| ### *recipes* / [futures:examples/background\_helper](/recipe_modules/futures/examples/background_helper.py) |
| |
| [DEPS](/recipe_modules/futures/examples/background_helper.py#9): [futures](#recipe_modules-futures), [json](#recipe_modules-json), [path](#recipe_modules-path), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/background_helper.py#86)(api):** |
| |
| — **def [manage\_helper](/recipe_modules/futures/examples/background_helper.py#21)(api, chn):** |
| |
|   **@contextmanager**<br>— **def [run\_helper](/recipe_modules/futures/examples/background_helper.py#59)(api):** |
| |
| Runs the background helper. |
| |
| Yields control once helper is ready. Kills helper once leaving the context |
| manager. |
| |
| This is an example of what your recipe module code would look like. Note that |
| we don't pass the channel to the 'user' code (i.e. RunSteps). |
| ### *recipes* / [futures:examples/extreme\_namespaces](/recipe_modules/futures/examples/extreme_namespaces.py) |
| |
| [DEPS](/recipe_modules/futures/examples/extreme_namespaces.py#7): [context](#recipe_modules-context), [futures](#recipe_modules-futures), [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [Level1](/recipe_modules/futures/examples/extreme_namespaces.py#27)(api, i):** |
| |
| — **def [Level2](/recipe_modules/futures/examples/extreme_namespaces.py#15)(api, i):** |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/extreme_namespaces.py#33)(api):** |
| ### *recipes* / [futures:examples/fan\_out\_in](/recipe_modules/futures/examples/fan_out_in.py) |
| |
| [DEPS](/recipe_modules/futures/examples/fan_out_in.py#7): [futures](#recipe_modules-futures), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/fan_out_in.py#13)(api):** |
| ### *recipes* / [futures:examples/lazy\_fan\_out\_in](/recipe_modules/futures/examples/lazy_fan_out_in.py) |
| |
| [DEPS](/recipe_modules/futures/examples/lazy_fan_out_in.py#7): [futures](#recipe_modules-futures), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/lazy_fan_out_in.py#13)(api):** |
| ### *recipes* / [futures:examples/lazy\_fan\_out\_in\_early\_abort](/recipe_modules/futures/examples/lazy_fan_out_in_early_abort.py) |
| |
| [DEPS](/recipe_modules/futures/examples/lazy_fan_out_in_early_abort.py#7): [futures](#recipe_modules-futures), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/lazy_fan_out_in_early_abort.py#13)(api):** |
| ### *recipes* / [futures:examples/lottasteps](/recipe_modules/futures/examples/lottasteps.py) |
| |
| [DEPS](/recipe_modules/futures/examples/lottasteps.py#20): [futures](#recipe_modules-futures), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This tests the engine's ability to handle many simultaneously-started steps. |
| |
| Prior to this, logdog butler and the recipe engine would run out of file |
| handles, because every spawn_immediate would immediately generate all log |
| handles for the step, instead of waiting for the step's cost to be available. |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/lottasteps.py#29)(api, props):** |
| ### *recipes* / [futures:examples/metadata](/recipe_modules/futures/examples/metadata.py) |
| |
| [DEPS](/recipe_modules/futures/examples/metadata.py#9): [futures](#recipe_modules-futures), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This tests metadata features of the Future object. |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/metadata.py#15)(api):** |
| ### *recipes* / [futures:examples/result](/recipe_modules/futures/examples/result.py) |
| |
| [DEPS](/recipe_modules/futures/examples/result.py#7): [futures](#recipe_modules-futures), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/result.py#13)(api):** |
| ### *recipes* / [futures:examples/semaphore](/recipe_modules/futures/examples/semaphore.py) |
| |
| [DEPS](/recipe_modules/futures/examples/semaphore.py#7): [futures](#recipe_modules-futures), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/semaphore.py#20)(api):** |
| |
| — **def [worker](/recipe_modules/futures/examples/semaphore.py#13)(api, sem, i, N):** |
| ### *recipes* / [generator\_script:examples/full](/recipe_modules/generator_script/examples/full.py) |
| |
| [DEPS](/recipe_modules/generator_script/examples/full.py#9): [generator\_script](#recipe_modules-generator_script), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/generator_script/examples/full.py#21)(api, script_name):** |
| ### *recipes* / [golang:examples/full](/recipe_modules/golang/examples/full.py) |
| |
| [DEPS](/recipe_modules/golang/examples/full.py#7): [golang](#recipe_modules-golang), [platform](#recipe_modules-platform), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/golang/examples/full.py#14)(api):** |
| ### *recipes* / [json:examples/full](/recipe_modules/json/examples/full.py) |
| |
| [DEPS](/recipe_modules/json/examples/full.py#7): [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/json/examples/full.py#23)(api):** |
| ### *recipes* / [json:tests/add\_json\_log](/recipe_modules/json/tests/add_json_log.py) |
| |
| [DEPS](/recipe_modules/json/tests/add_json_log.py#7): [json](#recipe_modules-json), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/json/tests/add_json_log.py#12)(api):** |
| ### *recipes* / [led:tests/full](/recipe_modules/led/tests/full.py) |
| |
| [DEPS](/recipe_modules/led/tests/full.py#16): [buildbucket](#recipe_modules-buildbucket), [led](#recipe_modules-led), [properties](#recipe_modules-properties), [proto](#recipe_modules-proto), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/led/tests/full.py#32)(api, get_cmd, child_properties, sloppy_child_properties, do_bogus_edits):** |
| ### *recipes* / [led:tests/no\_exist](/recipe_modules/led/tests/no_exist.py) |
| |
| [DEPS](/recipe_modules/led/tests/no_exist.py#7): [led](#recipe_modules-led), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/led/tests/no_exist.py#12)(api):** |
| ### *recipes* / [led:tests/trigger\_build](/recipe_modules/led/tests/trigger_build.py) |
| |
| [DEPS](/recipe_modules/led/tests/trigger_build.py#9): [led](#recipe_modules-led), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/led/tests/trigger_build.py#15)(api):** |
| ### *recipes* / [legacy\_annotation:examples/full](/recipe_modules/legacy_annotation/examples/full.py) |
| |
| [DEPS](/recipe_modules/legacy_annotation/examples/full.py#7): [legacy\_annotation](#recipe_modules-legacy_annotation), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/legacy_annotation/examples/full.py#20)(api):** |
| ### *recipes* / [milo:examples/full](/recipe_modules/milo/examples/full.py) |
| |
| [DEPS](/recipe_modules/milo/examples/full.py#9): [milo](#recipe_modules-milo) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/milo/examples/full.py#13)(api):** |
| ### *recipes* / [nodejs:examples/full](/recipe_modules/nodejs/examples/full.py) |
| |
| [DEPS](/recipe_modules/nodejs/examples/full.py#7): [nodejs](#recipe_modules-nodejs), [platform](#recipe_modules-platform), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/nodejs/examples/full.py#14)(api):** |
| ### *recipes* / [path:examples/full](/recipe_modules/path/examples/full.py) |
| |
| [DEPS](/recipe_modules/path/examples/full.py#7): [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/path/examples/full.py#19)(api):** |
| ### *recipes* / [placeholder](/recipes/placeholder.py) |
| |
| [DEPS](/recipes/placeholder.py#7): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step), [swarming](#recipe_modules-swarming), [time](#recipe_modules-time) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY3 |
| |
| — **def [RunSteps](/recipes/placeholder.py#30)(api, properties):** |
| ### *recipes* / [platform:examples/full](/recipe_modules/platform/examples/full.py) |
| |
| [DEPS](/recipe_modules/platform/examples/full.py#7): [platform](#recipe_modules-platform), [step](#recipe_modules-step), [version](#recipe_modules-version) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/platform/examples/full.py#13)(api):** |
| ### *recipes* / [properties:examples/full](/recipe_modules/properties/examples/full.py) |
| |
| [DEPS](/recipe_modules/properties/examples/full.py#16): [json](#recipe_modules-json), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/properties/examples/full.py#25)(api, props, env_props):** |
| ### *recipes* / [proto:tests/encode\_decode](/recipe_modules/proto/tests/encode_decode.py) |
| |
| [DEPS](/recipe_modules/proto/tests/encode_decode.py#7): [assertions](#recipe_modules-assertions), [path](#recipe_modules-path), [proto](#recipe_modules-proto), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/proto/tests/encode_decode.py#17)(api):** |
| ### *recipes* / [proto:tests/placeholders](/recipe_modules/proto/tests/placeholders.py) |
| |
| [DEPS](/recipe_modules/proto/tests/placeholders.py#7): [path](#recipe_modules-path), [proto](#recipe_modules-proto), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/proto/tests/placeholders.py#16)(api):** |
| ### *recipes* / [random:tests/full](/recipe_modules/random/tests/full.py) |
| |
| [DEPS](/recipe_modules/random/tests/full.py#7): [random](#recipe_modules-random), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/random/tests/full.py#13)(api):** |
| ### *recipes* / [raw\_io:examples/full](/recipe_modules/raw_io/examples/full.py) |
| |
| [DEPS](/recipe_modules/raw_io/examples/full.py#8): [path](#recipe_modules-path), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/raw_io/examples/full.py#17)(api):** |
| ### *recipes* / [raw\_io:tests/output\_mismatch](/recipe_modules/raw_io/tests/output_mismatch.py) |
| |
| [DEPS](/recipe_modules/raw_io/tests/output_mismatch.py#10): [assertions](#recipe_modules-assertions), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY3 |
| |
| — **def [RunSteps](/recipe_modules/raw_io/tests/output_mismatch.py#17)(api):** |
| ### *recipes* / [resultdb:examples/exonerate](/recipe_modules/resultdb/examples/exonerate.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/exonerate.py#13): [context](#recipe_modules-context), [json](#recipe_modules-json), [properties](#recipe_modules-properties), [resultdb](#recipe_modules-resultdb), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/exonerate.py#41)(api):** |
| ### *recipes* / [resultdb:examples/get\_included\_invocations](/recipe_modules/resultdb/examples/get_included_invocations.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/get_included_invocations.py#9): [assertions](#recipe_modules-assertions), [resultdb](#recipe_modules-resultdb) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/get_included_invocations.py#15)(api):** |
| ### *recipes* / [resultdb:examples/include](/recipe_modules/resultdb/examples/include.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/include.py#13): [context](#recipe_modules-context), [resultdb](#recipe_modules-resultdb) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/include.py#19)(api):** |
| ### *recipes* / [resultdb:examples/query](/recipe_modules/resultdb/examples/query.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/query.py#17): [buildbucket](#recipe_modules-buildbucket), [resultdb](#recipe_modules-resultdb), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/query.py#24)(api):** |
| ### *recipes* / [resultdb:examples/query\_test\_result\_statistics](/recipe_modules/resultdb/examples/query_test_result_statistics.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/query_test_result_statistics.py#12): [context](#recipe_modules-context), [resultdb](#recipe_modules-resultdb) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/query_test_result_statistics.py#18)(api):** |
| ### *recipes* / [resultdb:examples/result\_history](/recipe_modules/resultdb/examples/result_history.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/result_history.py#13): [resultdb](#recipe_modules-resultdb) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/result_history.py#18)(api):** |
| ### *recipes* / [resultdb:examples/resultsink](/recipe_modules/resultdb/examples/resultsink.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/resultsink.py#9): [context](#recipe_modules-context), [resultdb](#recipe_modules-resultdb), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/resultsink.py#16)(api):** |
| ### *recipes* / [resultdb:examples/test\_presentation](/recipe_modules/resultdb/examples/test_presentation.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/test_presentation.py#7): [resultdb](#recipe_modules-resultdb) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/test_presentation.py#11)(api):** |
| ### *recipes* / [resultdb:examples/test\_presentation\_default](/recipe_modules/resultdb/examples/test_presentation_default.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/test_presentation_default.py#7): [resultdb](#recipe_modules-resultdb) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/test_presentation_default.py#11)(api):** |
| ### *recipes* / [resultdb:examples/upload\_invocation\_artifacts](/recipe_modules/resultdb/examples/upload_invocation_artifacts.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/upload_invocation_artifacts.py#12): [resultdb](#recipe_modules-resultdb) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/upload_invocation_artifacts.py#17)(api):** |
| ### *recipes* / [runtime:tests/full](/recipe_modules/runtime/tests/full.py) |
| |
| [DEPS](/recipe_modules/runtime/tests/full.py#9): [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/runtime/tests/full.py#15)(api):** |
| ### *recipes* / [scheduler:examples/emit\_triggers](/recipe_modules/scheduler/examples/emit_triggers.py) |
| |
| [DEPS](/recipe_modules/scheduler/examples/emit_triggers.py#9): [buildbucket](#recipe_modules-buildbucket), [json](#recipe_modules-json), [runtime](#recipe_modules-runtime), [scheduler](#recipe_modules-scheduler), [time](#recipe_modules-time) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This file is a recipe demonstrating emitting triggers to LUCI Scheduler. |
| |
| — **def [RunSteps](/recipe_modules/scheduler/examples/emit_triggers.py#18)(api):** |
| ### *recipes* / [scheduler:examples/info](/recipe_modules/scheduler/examples/info.py) |
| |
| [DEPS](/recipe_modules/scheduler/examples/info.py#9): [scheduler](#recipe_modules-scheduler), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This file is a recipe demonstrating reading/mocking scheduler host. |
| |
| — **def [RunSteps](/recipe_modules/scheduler/examples/info.py#14)(api):** |
| ### *recipes* / [scheduler:examples/triggers](/recipe_modules/scheduler/examples/triggers.py) |
| |
| [DEPS](/recipe_modules/scheduler/examples/triggers.py#16): [json](#recipe_modules-json), [scheduler](#recipe_modules-scheduler), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This file is a recipe demonstrating reading triggers of the current build. |
| |
| — **def [RunSteps](/recipe_modules/scheduler/examples/triggers.py#22)(api):** |
| ### *recipes* / [service\_account:examples/full](/recipe_modules/service_account/examples/full.py) |
| |
| [DEPS](/recipe_modules/service_account/examples/full.py#9): [path](#recipe_modules-path), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [service\_account](#recipe_modules-service_account) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/service_account/examples/full.py#23)(api, key_path, scopes):** |
| ### *recipes* / [step:examples/full](/recipe_modules/step/examples/full.py) |
| |
| [DEPS](/recipe_modules/step/examples/full.py#9): [context](#recipe_modules-context), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/examples/full.py#27)(api, bad_return, access_invalid_data, access_deep_invalid_data, assign_extra_junk, timeout):** |
| ### *recipes* / [step:tests/active\_result](/recipe_modules/step/tests/active_result.py) |
| |
| [DEPS](/recipe_modules/step/tests/active_result.py#7): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/active_result.py#12)(api):** |
| ### *recipes* / [step:tests/defer](/recipe_modules/step/tests/defer.py) |
| |
| [DEPS](/recipe_modules/step/tests/defer.py#7): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/defer.py#11)(api):** |
| ### *recipes* / [step:tests/empty](/recipe_modules/step/tests/empty.py) |
| |
| [DEPS](/recipe_modules/step/tests/empty.py#11): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/empty.py#16)(api):** |
| ### *recipes* / [step:tests/inject\_paths](/recipe_modules/step/tests/inject_paths.py) |
| |
| [DEPS](/recipe_modules/step/tests/inject_paths.py#7): [context](#recipe_modules-context), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/inject_paths.py#15)(api):** |
| ### *recipes* / [step:tests/nested](/recipe_modules/step/tests/nested.py) |
| |
| [DEPS](/recipe_modules/step/tests/nested.py#11): [context](#recipe_modules-context), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/nested.py#17)(api):** |
| ### *recipes* / [step:tests/raise\_on\_failure](/recipe_modules/step/tests/raise_on_failure.py) |
| |
| [DEPS](/recipe_modules/step/tests/raise_on_failure.py#9): [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/raise_on_failure.py#19)(api, infra_step, set_status_to_exception):** |
| ### *recipes* / [step:tests/stdio](/recipe_modules/step/tests/stdio.py) |
| |
| [DEPS](/recipe_modules/step/tests/stdio.py#7): [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/stdio.py#13)(api):** |
| ### *recipes* / [step:tests/step\_call\_args](/recipe_modules/step/tests/step_call_args.py) |
| |
| [DEPS](/recipe_modules/step/tests/step_call_args.py#9): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/step_call_args.py#14)(api):** |
| ### *recipes* / [step:tests/step\_cost](/recipe_modules/step/tests/step_cost.py) |
| |
| [DEPS](/recipe_modules/step/tests/step_cost.py#9): [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/step_cost.py#14)(api):** |
| ### *recipes* / [step:tests/sub\_build](/recipe_modules/step/tests/sub_build.py) |
| |
| [DEPS](/recipe_modules/step/tests/sub_build.py#20): [assertions](#recipe_modules-assertions), [context](#recipe_modules-context), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/sub_build.py#31)(api, props):** |
| ### *recipes* / [step:tests/timeout](/recipe_modules/step/tests/timeout.py) |
| |
| [DEPS](/recipe_modules/step/tests/timeout.py#9): [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/step/tests/timeout.py#20)(api, timeout):** |
| ### *recipes* / [swarming:examples/full](/recipe_modules/swarming/examples/full.py) |
| |
| [DEPS](/recipe_modules/swarming/examples/full.py#16): [cipd](#recipe_modules-cipd), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step), [swarming](#recipe_modules-swarming) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/swarming/examples/full.py#28)(api):** |
| ### *recipes* / [swarming:examples/this\_task](/recipe_modules/swarming/examples/this_task.py) |
| |
| [DEPS](/recipe_modules/swarming/examples/this_task.py#7): [step](#recipe_modules-step), [swarming](#recipe_modules-swarming) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/swarming/examples/this_task.py#13)(api):** |
| ### *recipes* / [swarming:tests/copy](/recipe_modules/swarming/tests/copy.py) |
| |
| [DEPS](/recipe_modules/swarming/tests/copy.py#9): [assertions](#recipe_modules-assertions), [swarming](#recipe_modules-swarming) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/copy.py#15)(api):** |
| ### *recipes* / [swarming:tests/realms](/recipe_modules/swarming/tests/realms.py) |
| |
| [DEPS](/recipe_modules/swarming/tests/realms.py#9): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [context](#recipe_modules-context), [step](#recipe_modules-step), [swarming](#recipe_modules-swarming) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/realms.py#18)(api):** |
| ### *recipes* / [swarming:tests/task\_request\_from\_jsonish](/recipe_modules/swarming/tests/task_request_from_jsonish.py) |
| |
| [DEPS](/recipe_modules/swarming/tests/task_request_from_jsonish.py#9): [assertions](#recipe_modules-assertions), [swarming](#recipe_modules-swarming) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/task_request_from_jsonish.py#15)(api):** |
| ### *recipes* / [time:examples/full](/recipe_modules/time/examples/full.py) |
| |
| [DEPS](/recipe_modules/time/examples/full.py#11): [properties](#recipe_modules-properties), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step), [time](#recipe_modules-time) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/time/examples/full.py#19)(api):** |
| ### *recipes* / [tricium:examples/add\_comment](/recipe_modules/tricium/examples/add_comment.py) |
| |
| [DEPS](/recipe_modules/tricium/examples/add_comment.py#10): [properties](#recipe_modules-properties), [tricium](#recipe_modules-tricium) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/tricium/examples/add_comment.py#17)(api, trigger_type_error):** |
| ### *recipes* / [tricium:examples/wrapper](/recipe_modules/tricium/examples/wrapper.py) |
| |
| [DEPS](/recipe_modules/tricium/examples/wrapper.py#14): [file](#recipe_modules-file), [path](#recipe_modules-path), [tricium](#recipe_modules-tricium) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| An example of a recipe wrapping legacy analyzers. |
| |
| — **def [RunSteps](/recipe_modules/tricium/examples/wrapper.py#21)(api):** |
| ### *recipes* / [tricium:tests/add\_comment\_validation](/recipe_modules/tricium/tests/add_comment_validation.py) |
| |
| [DEPS](/recipe_modules/tricium/tests/add_comment_validation.py#10): [properties](#recipe_modules-properties), [tricium](#recipe_modules-tricium) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/tricium/tests/add_comment_validation.py#43)(api, case):** |
| ### *recipes* / [tricium:tests/enforce\_comments\_num\_limit](/recipe_modules/tricium/tests/enforce_comments_num_limit.py) |
| |
| [DEPS](/recipe_modules/tricium/tests/enforce_comments_num_limit.py#12): [assertions](#recipe_modules-assertions), [properties](#recipe_modules-properties), [proto](#recipe_modules-proto), [tricium](#recipe_modules-tricium) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/tricium/tests/enforce_comments_num_limit.py#22)(api, props):** |
| ### *recipes* / [url:examples/full](/recipe_modules/url/examples/full.py) |
| |
| [DEPS](/recipe_modules/url/examples/full.py#7): [context](#recipe_modules-context), [path](#recipe_modules-path), [step](#recipe_modules-step), [url](#recipe_modules-url) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/url/examples/full.py#29)(api):** |
| ### *recipes* / [url:tests/join](/recipe_modules/url/tests/join.py) |
| |
| [DEPS](/recipe_modules/url/tests/join.py#7): [step](#recipe_modules-step), [url](#recipe_modules-url) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/url/tests/join.py#13)(api):** |
| ### *recipes* / [url:tests/validate\_url](/recipe_modules/url/tests/validate_url.py) |
| |
| [DEPS](/recipe_modules/url/tests/validate_url.py#9): [properties](#recipe_modules-properties), [step](#recipe_modules-step), [url](#recipe_modules-url) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/url/tests/validate_url.py#16)(api):** |
| ### *recipes* / [uuid:examples/full](/recipe_modules/uuid/examples/full.py) |
| |
| [DEPS](/recipe_modules/uuid/examples/full.py#7): [step](#recipe_modules-step), [uuid](#recipe_modules-uuid) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/uuid/examples/full.py#13)(api):** |
| ### *recipes* / [version:examples/full](/recipe_modules/version/examples/full.py) |
| |
| [DEPS](/recipe_modules/version/examples/full.py#7): [version](#recipe_modules-version) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| — **def [RunSteps](/recipe_modules/version/examples/full.py#12)(api):** |
| ### *recipes* / [warning:tests/fakes](/recipe_modules/warning/tests/fakes.py) |
| |
| PYTHON_VERSION_COMPATIBILITY: PY2+3 |
| |
| This is a fake recipe to trick the simulation and make it believes that |
| this module has tests. The actual test for this module is done via unit test |
| because the `issue` method can only be used from recipe_modules, not recipes. |
| |
| — **def [RunSteps](/recipe_modules/warning/tests/fakes.py#14)(api):** |
| |