| <!--- 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) |
| * [assertions](#recipe_modules-assertions) |
| * [bcid_reporter](#recipe_modules-bcid_reporter) |
| * [bcid_verifier](#recipe_modules-bcid_verifier) — API for interacting with Software Verifier. |
| * [buildbucket](#recipe_modules-buildbucket) — API for interacting with the buildbucket service. |
| * [cas](#recipe_modules-cas) — API for interacting with cas client. |
| * [cas_input](#recipe_modules-cas_input) — Simple API for handling CAS inputs to a recipe. |
| * [change_verifier](#recipe_modules-change_verifier) — Recipe API for LUCI Change Verifier. |
| * [cipd](#recipe_modules-cipd) — API for interacting with CIPD. |
| * [commit_position](#recipe_modules-commit_position) |
| * [context](#recipe_modules-context) — The context module provides APIs for manipulating a few pieces of 'ambient' data that affect how steps are run. |
| * [cq](#recipe_modules-cq) — Wrapper for CV API. |
| * [cv](#recipe_modules-cv) — Recipe API for LUCI CV, the pre-commit testing system. |
| * [defer](#recipe_modules-defer) — Runs a function but defers the result until a later time. |
| * [file](#recipe_modules-file) — File manipulation (read/write/delete/glob) methods. |
| * [findings](#recipe_modules-findings) |
| * [futures](#recipe_modules-futures) — Implements in-recipe concurrency via green threads. |
| * [generator_script](#recipe_modules-generator_script) — A simple method for running steps generated by an external script. |
| * [golang](#recipe_modules-golang) |
| * [json](#recipe_modules-json) — Methods for producing and consuming JSON. |
| * [led](#recipe_modules-led) — An interface to call the led tool. |
| * [legacy_annotation](#recipe_modules-legacy_annotation) — Legacy Annotation module provides support for running a command emitting legacy @@@annotation@@@ in the new luciexe mode. |
| * [luci_analysis](#recipe_modules-luci_analysis) — API for interacting with the LUCI Analysis RPCs This API is for calling LUCI Analysis RPCs for various aggregated info about test results. |
| * [luci_config](#recipe_modules-luci_config) |
| * [milo](#recipe_modules-milo) — API for specifying Milo behavior. |
| * [nodejs](#recipe_modules-nodejs) |
| * [path](#recipe_modules-path) — All functions related to manipulating paths in recipes. |
| * [platform](#recipe_modules-platform) — Mockable system platform identity functions. |
| * [properties](#recipe_modules-properties) — Provides access to the recipes input properties. |
| * [proto](#recipe_modules-proto) — Methods for producing and consuming protobuf data to/from steps and the filesystem. |
| * [random](#recipe_modules-random) — Allows randomness in recipes. |
| * [raw_io](#recipe_modules-raw_io) — Provides objects for reading and writing raw data to and from steps. |
| * [resultdb](#recipe_modules-resultdb) — API for interacting with the ResultDB service. |
| * [runtime](#recipe_modules-runtime) |
| * [scheduler](#recipe_modules-scheduler) — API for interacting with the LUCI Scheduler service. |
| * [service_account](#recipe_modules-service_account) — API for getting OAuth2 access tokens for LUCI tasks or private keys. |
| * [step](#recipe_modules-step) — Step is the primary API for running steps (external programs, etc. |
| * [swarming](#recipe_modules-swarming) |
| * [time](#recipe_modules-time) — Allows mockable access to the current time. |
| * [tricium](#recipe_modules-tricium) — API for Tricium analyzers to use. |
| * [url](#recipe_modules-url) — Methods for interacting with HTTP(s) URLs. |
| * [uuid](#recipe_modules-uuid) — Allows test-repeatable access to a random UUID. |
| * [version](#recipe_modules-version) — Thin API for parsing semver strings into comparable object. |
| * [warning](#recipe_modules-warning) — Allows recipe modules to issue warnings in simulation test. |
| |
| **[Recipes](#Recipes)** |
| * [archive:examples/full](#recipes-archive_examples_full) |
| * [assertions:tests/assert-raises](#recipes-assertions_tests_assert-raises) |
| * [assertions:tests/assert_count_equal](#recipes-assertions_tests_assert_count_equal) |
| * [assertions:tests/assertions](#recipes-assertions_tests_assertions) |
| * [assertions:tests/attribute_error](#recipes-assertions_tests_attribute_error) |
| * [assertions:tests/long_message](#recipes-assertions_tests_long_message) |
| * [assertions:tests/max_diff](#recipes-assertions_tests_max_diff) |
| * [bcid_reporter:examples/usage](#recipes-bcid_reporter_examples_usage) |
| * [bcid_reporter:tests/retry](#recipes-bcid_reporter_tests_retry) |
| * [bcid_verifier:tests/test-verify](#recipes-bcid_verifier_tests_test-verify) |
| * [buildbucket:examples/full](#recipes-buildbucket_examples_full) — This file is a recipe demonstrating the buildbucket recipe module. |
| * [buildbucket:tests/add_build_tags](#recipes-buildbucket_tests_add_build_tags) |
| * [buildbucket:tests/add_step_tags](#recipes-buildbucket_tests_add_step_tags) |
| * [buildbucket:tests/backend](#recipes-buildbucket_tests_backend) |
| * [buildbucket:tests/backend_utilities_fail](#recipes-buildbucket_tests_backend_utilities_fail) |
| * [buildbucket:tests/build](#recipes-buildbucket_tests_build) |
| * [buildbucket:tests/cancel](#recipes-buildbucket_tests_cancel) |
| * [buildbucket:tests/collect](#recipes-buildbucket_tests_collect) |
| * [buildbucket:tests/get](#recipes-buildbucket_tests_get) |
| * [buildbucket:tests/list_builders](#recipes-buildbucket_tests_list_builders) |
| * [buildbucket:tests/output_commit](#recipes-buildbucket_tests_output_commit) — This recipe tests the buildbucket. |
| * [buildbucket:tests/schedule](#recipes-buildbucket_tests_schedule) |
| * [buildbucket:tests/search](#recipes-buildbucket_tests_search) |
| * [cas:examples/full](#recipes-cas_examples_full) |
| * [cas_input:examples/full](#recipes-cas_input_examples_full) |
| * [change_verifier:tests/match_config](#recipes-change_verifier_tests_match_config) |
| * [change_verifier:tests/search](#recipes-change_verifier_tests_search) |
| * [cipd:examples/full](#recipes-cipd_examples_full) |
| * [cipd:tests/platform](#recipes-cipd_tests_platform) |
| * [commit_position:examples/full](#recipes-commit_position_examples_full) |
| * [context:examples/full](#recipes-context_examples_full) |
| * [context:tests/cwd](#recipes-context_tests_cwd) |
| * [context:tests/env](#recipes-context_tests_env) |
| * [context:tests/greenlet](#recipes-context_tests_greenlet) |
| * [context:tests/infra_step](#recipes-context_tests_infra_step) |
| * [context:tests/luci_context](#recipes-context_tests_luci_context) |
| * [cq:examples/ordered_cls](#recipes-cq_examples_ordered_cls) |
| * [cq:examples/trigger_child_builds](#recipes-cq_examples_trigger_child_builds) |
| * [cq:tests/cl_group_key](#recipes-cq_tests_cl_group_key) |
| * [cq:tests/do_not_retry](#recipes-cq_tests_do_not_retry) |
| * [cq:tests/experimental](#recipes-cq_tests_experimental) |
| * [cq:tests/inactive](#recipes-cq_tests_inactive) |
| * [cq:tests/mode_of_run](#recipes-cq_tests_mode_of_run) |
| * [cq:tests/owner_is_googler](#recipes-cq_tests_owner_is_googler) |
| * [cq:tests/reuse](#recipes-cq_tests_reuse) |
| * [cq:tests/triggered_build_ids](#recipes-cq_tests_triggered_build_ids) |
| * [cv:examples/ordered_cls](#recipes-cv_examples_ordered_cls) |
| * [cv:examples/trigger_child_builds](#recipes-cv_examples_trigger_child_builds) |
| * [cv:tests/attempt_key](#recipes-cv_tests_attempt_key) |
| * [cv:tests/cl_group_key](#recipes-cv_tests_cl_group_key) |
| * [cv:tests/cl_owner](#recipes-cv_tests_cl_owner) |
| * [cv:tests/do_not_retry](#recipes-cv_tests_do_not_retry) |
| * [cv:tests/experimental](#recipes-cv_tests_experimental) |
| * [cv:tests/inactive](#recipes-cv_tests_inactive) |
| * [cv:tests/mode_of_run](#recipes-cv_tests_mode_of_run) |
| * [cv:tests/owner_is_googler](#recipes-cv_tests_owner_is_googler) |
| * [cv:tests/reuse](#recipes-cv_tests_reuse) |
| * [cv:tests/triggered_build_ids](#recipes-cv_tests_triggered_build_ids) |
| * [defer:tests/collect](#recipes-defer_tests_collect) |
| * [defer:tests/context](#recipes-defer_tests_context) |
| * [defer:tests/non_deferred](#recipes-defer_tests_non_deferred) |
| * [defer:tests/result](#recipes-defer_tests_result) |
| * [defer:tests/suppressed](#recipes-defer_tests_suppressed) |
| * [engine_tests/allowlist_steps](#recipes-engine_tests_allowlist_steps) — Tests that step_data can accept multiple specs at once. |
| * [engine_tests/bad_subprocess](#recipes-engine_tests_bad_subprocess) — Tests that daemons that hang on to STDOUT can't cause the engine to hang. |
| * [engine_tests/comprehensive_ui](#recipes-engine_tests_comprehensive_ui) — A fast-running recipe which comprehensively covers all StepPresentation features available in the recipe engine. |
| * [engine_tests/config_operations](#recipes-engine_tests_config_operations) — Tests that recipes can modify configuration options in various ways. |
| * [engine_tests/early_termination](#recipes-engine_tests_early_termination) — 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) — Tests that tests with a single exception are handled correctly. |
| * [engine_tests/expect_exceptions](#recipes-engine_tests_expect_exceptions) — Tests that tests with multiple exceptions are handled correctly. |
| * [engine_tests/failure_results](#recipes-engine_tests_failure_results) — Tests that run_steps is handling recipe failures correctly. |
| * [engine_tests/functools_partial](#recipes-engine_tests_functools_partial) — Engine shouldn't explode when step_test_data gets functools. |
| * [engine_tests/incorrect_recipe_result](#recipes-engine_tests_incorrect_recipe_result) — Tests that engine. |
| * [engine_tests/long_sleep](#recipes-engine_tests_long_sleep) — Simple recipe which sleeps in a subprocess forever to facilitate early termination tests. |
| * [engine_tests/missing_start_dir](#recipes-engine_tests_missing_start_dir) — Tests that deleting the current working directory doesn't immediately fail. |
| * [engine_tests/module_injection_site](#recipes-engine_tests_module_injection_site) — This test serves to demonstrate that the ModuleInjectionSite object on recipe modules (i. |
| * [engine_tests/multi_test_data](#recipes-engine_tests_multi_test_data) — Tests that step_data can accept multiple specs at once. |
| * [engine_tests/multiple_placeholders](#recipes-engine_tests_multiple_placeholders) — Tests error checking around multiple placeholders in a single step. |
| * [engine_tests/nonexistent_command](#recipes-engine_tests_nonexistent_command) |
| * [engine_tests/placeholder_exception](#recipes-engine_tests_placeholder_exception) — Tests that placeholders can't wreck the world by exhausting the step stack. |
| * [engine_tests/proto_output_properties](#recipes-engine_tests_proto_output_properties) — Tests that output properties can be a proto message. |
| * [engine_tests/proto_properties](#recipes-engine_tests_proto_properties) |
| * [engine_tests/recipe_paths](#recipes-engine_tests_recipe_paths) — Tests that recipes have access to names, resources and their repo. |
| * [engine_tests/recipe_test_data](#recipes-engine_tests_recipe_test_data) — Tests that we can pass data via api. |
| * [engine_tests/sort_properties](#recipes-engine_tests_sort_properties) — Tests that step presentation properties can be ordered. |
| * [engine_tests/undeclared_method](#recipes-engine_tests_undeclared_method) |
| * [engine_tests/unicode](#recipes-engine_tests_unicode) |
| * [file:examples/chmod](#recipes-file_examples_chmod) |
| * [file:examples/compute_hash](#recipes-file_examples_compute_hash) |
| * [file:examples/copy](#recipes-file_examples_copy) |
| * [file:examples/copytree](#recipes-file_examples_copytree) |
| * [file:examples/error](#recipes-file_examples_error) |
| * [file:examples/file_hash](#recipes-file_examples_file_hash) |
| * [file:examples/flatten_single_directories](#recipes-file_examples_flatten_single_directories) |
| * [file:examples/glob](#recipes-file_examples_glob) |
| * [file:examples/handle_json_file](#recipes-file_examples_handle_json_file) |
| * [file:examples/listdir](#recipes-file_examples_listdir) |
| * [file:examples/raw_copy](#recipes-file_examples_raw_copy) |
| * [file:examples/read_write_proto](#recipes-file_examples_read_write_proto) |
| * [file:examples/symlink](#recipes-file_examples_symlink) |
| * [file:examples/truncate](#recipes-file_examples_truncate) |
| * [findings:tests/infer_source](#recipes-findings_tests_infer_source) |
| * [findings:tests/upload_findings](#recipes-findings_tests_upload_findings) |
| * [futures:examples/background_helper](#recipes-futures_examples_background_helper) |
| * [futures:examples/extreme_namespaces](#recipes-futures_examples_extreme_namespaces) |
| * [futures:examples/fan_out_in](#recipes-futures_examples_fan_out_in) |
| * [futures:examples/lazy_fan_out_in](#recipes-futures_examples_lazy_fan_out_in) |
| * [futures:examples/lazy_fan_out_in_early_abort](#recipes-futures_examples_lazy_fan_out_in_early_abort) |
| * [futures:examples/lottasteps](#recipes-futures_examples_lottasteps) — This tests the engine's ability to handle many simultaneously-started steps. |
| * [futures:examples/metadata](#recipes-futures_examples_metadata) — This tests metadata features of the Future object. |
| * [futures:examples/result](#recipes-futures_examples_result) |
| * [futures:examples/semaphore](#recipes-futures_examples_semaphore) |
| * [generator_script:examples/full](#recipes-generator_script_examples_full) |
| * [golang:examples/full](#recipes-golang_examples_full) |
| * [json:examples/full](#recipes-json_examples_full) |
| * [json:tests/add_json_log](#recipes-json_tests_add_json_log) |
| * [json:tests/unsorted](#recipes-json_tests_unsorted) — Test to assert that sort_keys=False preserves insertion order. |
| * [led:tests/full](#recipes-led_tests_full) |
| * [led:tests/led_real_build](#recipes-led_tests_led_real_build) |
| * [led:tests/no_exist](#recipes-led_tests_no_exist) |
| * [led:tests/trigger_build](#recipes-led_tests_trigger_build) |
| * [led:tests/trigger_build_with_payload](#recipes-led_tests_trigger_build_with_payload) |
| * [legacy_annotation:examples/full](#recipes-legacy_annotation_examples_full) |
| * [luci_analysis:tests/query_failure_rate_test](#recipes-luci_analysis_tests_query_failure_rate_test) — Tests for query_failure_rate. |
| * [luci_analysis:tests/query_stability_test](#recipes-luci_analysis_tests_query_stability_test) — Tests for query_stability. |
| * [luci_analysis:tests/test_generate_analysis](#recipes-luci_analysis_tests_test_generate_analysis) — Tests for generate_analysis. |
| * [luci_analysis:tests/test_generate_stability_response](#recipes-luci_analysis_tests_test_generate_stability_response) — Tests for generate_stability_response. |
| * [luci_analysis:tests/test_history_query](#recipes-luci_analysis_tests_test_history_query) — Tests for query_failure_rate. |
| * [luci_analysis:tests/test_lookup_bug](#recipes-luci_analysis_tests_test_lookup_bug) — Tests for lookup_bug. |
| * [luci_analysis:tests/test_query_cluster_failures](#recipes-luci_analysis_tests_test_query_cluster_failures) — Tests for query_cluster_failres. |
| * [luci_analysis:tests/test_query_variants](#recipes-luci_analysis_tests_test_query_variants) — Tests for query_variants. |
| * [luci_config:tests/full](#recipes-luci_config_tests_full) |
| * [milo:examples/full](#recipes-milo_examples_full) |
| * [nodejs:examples/full](#recipes-nodejs_examples_full) |
| * [path:examples/full](#recipes-path_examples_full) |
| * [path:tests/cast_to_path](#recipes-path_tests_cast_to_path) |
| * [path:tests/dynamic_paths](#recipes-path_tests_dynamic_paths) |
| * [path:tests/exists](#recipes-path_tests_exists) |
| * [path:tests/expand](#recipes-path_tests_expand) |
| * [path:tests/test_api_legacy](#recipes-path_tests_test_api_legacy) — Test to cover legacy aspects of PathTestApi. |
| * [placeholder](#recipes-placeholder) |
| * [platform:examples/full](#recipes-platform_examples_full) |
| * [properties:examples/full](#recipes-properties_examples_full) |
| * [proto:tests/encode_decode](#recipes-proto_tests_encode_decode) |
| * [proto:tests/placeholders](#recipes-proto_tests_placeholders) |
| * [random:tests/full](#recipes-random_tests_full) |
| * [raw_io:examples/full](#recipes-raw_io_examples_full) |
| * [raw_io:tests/output_mismatch](#recipes-raw_io_tests_output_mismatch) |
| * [resultdb:examples/exonerate](#recipes-resultdb_examples_exonerate) |
| * [resultdb:examples/get_included_invocations](#recipes-resultdb_examples_get_included_invocations) |
| * [resultdb:examples/get_invocation_instructions](#recipes-resultdb_examples_get_invocation_instructions) |
| * [resultdb:examples/include](#recipes-resultdb_examples_include) |
| * [resultdb:examples/query](#recipes-resultdb_examples_query) |
| * [resultdb:examples/query_new_test_variants](#recipes-resultdb_examples_query_new_test_variants) |
| * [resultdb:examples/query_test_result_statistics](#recipes-resultdb_examples_query_test_result_statistics) |
| * [resultdb:examples/query_test_results](#recipes-resultdb_examples_query_test_results) |
| * [resultdb:examples/query_test_variants](#recipes-resultdb_examples_query_test_variants) |
| * [resultdb:examples/resultsink](#recipes-resultdb_examples_resultsink) |
| * [resultdb:examples/test_presentation](#recipes-resultdb_examples_test_presentation) |
| * [resultdb:examples/test_presentation_default](#recipes-resultdb_examples_test_presentation_default) |
| * [resultdb:examples/update_invocation](#recipes-resultdb_examples_update_invocation) |
| * [resultdb:examples/upload_invocation_artifacts](#recipes-resultdb_examples_upload_invocation_artifacts) |
| * [runtime:tests/full](#recipes-runtime_tests_full) |
| * [scheduler:examples/emit_triggers](#recipes-scheduler_examples_emit_triggers) — This file is a recipe demonstrating emitting triggers to LUCI Scheduler. |
| * [scheduler:examples/info](#recipes-scheduler_examples_info) — This file is a recipe demonstrating reading/mocking scheduler host. |
| * [scheduler:examples/triggers](#recipes-scheduler_examples_triggers) — This file is a recipe demonstrating reading triggers of the current build. |
| * [service_account:examples/full](#recipes-service_account_examples_full) |
| * [step:examples/full](#recipes-step_examples_full) |
| * [step:tests/active_result](#recipes-step_tests_active_result) |
| * [step:tests/drop_expectation](#recipes-step_tests_drop_expectation) |
| * [step:tests/empty](#recipes-step_tests_empty) |
| * [step:tests/inject_paths](#recipes-step_tests_inject_paths) |
| * [step:tests/nested](#recipes-step_tests_nested) |
| * [step:tests/raise_on_failure](#recipes-step_tests_raise_on_failure) |
| * [step:tests/stdio](#recipes-step_tests_stdio) |
| * [step:tests/step_call_args](#recipes-step_tests_step_call_args) |
| * [step:tests/step_cost](#recipes-step_tests_step_cost) |
| * [step:tests/sub_build](#recipes-step_tests_sub_build) |
| * [step:tests/timeout](#recipes-step_tests_timeout) |
| * [swarming:examples/full](#recipes-swarming_examples_full) |
| * [swarming:examples/this_task](#recipes-swarming_examples_this_task) |
| * [swarming:tests/collect_errors](#recipes-swarming_tests_collect_errors) |
| * [swarming:tests/copy](#recipes-swarming_tests_copy) |
| * [swarming:tests/list_bots](#recipes-swarming_tests_list_bots) |
| * [swarming:tests/list_tasks](#recipes-swarming_tests_list_tasks) |
| * [swarming:tests/realms](#recipes-swarming_tests_realms) |
| * [swarming:tests/task_request_from_jsonish](#recipes-swarming_tests_task_request_from_jsonish) |
| * [swarming:tests/task_result_from_jsonish](#recipes-swarming_tests_task_result_from_jsonish) |
| * [time:examples/full](#recipes-time_examples_full) |
| * [time:examples/jitter](#recipes-time_examples_jitter) |
| * [tricium:examples/add_comment](#recipes-tricium_examples_add_comment) |
| * [tricium:examples/wrapper](#recipes-tricium_examples_wrapper) — An example of a recipe wrapping legacy analyzers. |
| * [tricium:tests/add_comment_validation](#recipes-tricium_tests_add_comment_validation) |
| * [tricium:tests/enforce_comments_num_limit](#recipes-tricium_tests_enforce_comments_num_limit) |
| * [url:examples/full](#recipes-url_examples_full) |
| * [url:tests/join](#recipes-url_tests_join) |
| * [url:tests/validate_url](#recipes-url_tests_validate_url) |
| * [uuid:examples/full](#recipes-uuid_examples_full) |
| * [version:examples/full](#recipes-version_examples_full) |
| * [warning:tests/fakes](#recipes-warning_tests_fakes) — 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) |
| |
| |
| #### **class [ArchiveApi](/recipe_modules/archive/api.py#11)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| Provides steps to manipulate archive files (tar, zip, etc.). |
| |
| — **def [extract](/recipe_modules/archive/api.py#45)(self, step_name: str, archive_file: (config_types.Path | str), output: (config_types.Path | str), mode: str='safe', include_files: Sequence[str]=(), archive_type: (str | None)=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#16)(self, root: config_types.Path):** |
| |
| 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 / 'file'). |
| with_dir(root / 'directory'). |
| archive('archive step', output, 'tbz')) |
| |
| # Archive root/** |
| zip_path = ( |
| api.archive.package(root). |
| archive('archive step', api.path.start_dir / '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) |
| |
| |
| #### **class [AssertionsApi](/recipe_modules/assertions/api.py#56)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| 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), [file](#recipe_modules-file), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step), [time](#recipe_modules-time) |
| |
| |
| #### **class [BcidReporterApi](/recipe_modules/bcid_reporter/api.py#25)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| API for interacting with Provenance server using the broker tool. |
| |
|   **@property**<br>— **def [bcid\_reporter\_path](/recipe_modules/bcid_reporter/api.py#37)(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 [create\_from\_pkg](/recipe_modules/bcid_reporter/api.py#232)(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 and |
| reports cipd digest to local provenance server. |
| |
| This builds, uploads and reports the package in one step. |
| |
| Args: |
| * pkg_def - The description of the package we want to create. |
| * refs - A list of ref names to set for the package instance. |
| * tags - A map of tag name -> value to set for the package instance. |
| * metadata - A list of metadata entries to attach. |
| * compression_level - Deflate compression level. If None, defaults to 5 |
| (0 - disable, 1 - best speed, 9 - best compression). |
| * verification_timeout - 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/bcid_reporter/api.py#181)(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 and reports cipd digest to local provenance server. |
| |
| This builds, uploads and reports the package in one step. |
| |
| Args: |
| * pkg_def - The path to the yaml file. |
| * refs - A list of ref names to set for the package instance. |
| * tags - A map of tag name -> value to set for the package instance. |
| * metadata - A list of metadata entries to attach. |
| * pkg_vars - A map of var name -> value to use for vars |
| referenced in package definition file. |
| * compression_level - Deflate compression level. If None, defaults to 5 |
| (0 - disable, 1 - best speed, 9 - best compression). |
| * verification_timeout - 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. |
| |
|   **@retry()**<br>— **def [report\_cipd](/recipe_modules/bcid_reporter/api.py#86)(self, digest, pkg, iid, server_url=None):** |
| |
| Reports cipd digest to local provenance server. |
| |
| This is used to report produced artifacts hash and metadata to provenance, |
| 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 provenance server, the |
| broker tool will use default if not specified. |
| |
|   **@retry()**<br>— **def [report\_gcs](/recipe_modules/bcid_reporter/api.py#116)(self, digest, guri, server_url=None):** |
| |
| Reports gcs digest to local provenance server. |
| |
| This is used to report produced artifacts hash and metadata to provenance, |
| 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 provenance server, the |
| broker tool will use default if not specified. |
| |
|   **@retry()**<br>— **def [report\_sbom](/recipe_modules/bcid_reporter/api.py#144)(self, digest, guri, sbom_subjects=None, server_url=None):** |
| |
| Reports SBOM gcs digest to local provenance server. |
| |
| This is used to report the SBOM metadata to provenance, along with |
| the hash of the artifact it represents. It is also used to generate |
| provenance. |
| |
| Args: |
| * digest (str) - The hash of the SBOM. |
| * guri (str) - This is the unique GCS URI for the SBOM, |
| e.g. gs://bucket/path/to/sbom. |
| * sbom_subjects (str list or str) - The hash values corresponding to the |
| artifacts that this SBOM covers. |
| * server_url (Optional[str]) - URL for the local provenance server, the |
| broker tool will use default if not specified. |
| |
|   **@retry(raise_on_failure=False)**<br>— **def [report\_stage](/recipe_modules/bcid_reporter/api.py#53)(self, stage, server_url=None):** |
| |
| Reports task stage to local provenance server. This is best-effort and |
| won't abort the execution on errors. |
| |
| 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 provenance server, the |
| broker tool will use default if not specified. |
| ### *recipe_modules* / [bcid\_verifier](/recipe_modules/bcid_verifier) |
| |
| [DEPS](/recipe_modules/bcid_verifier/__init__.py#7): [cipd](#recipe_modules-cipd), [file](#recipe_modules-file), [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| |
| API for interacting with Software Verifier. |
| |
| To successfully authenticate to this API, you must have the |
| https://www.googleapis.com/auth/bcid_verify OAuth scope. |
| |
| #### **class [BcidVerifierApi](/recipe_modules/bcid_verifier/api.py#22)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| API for interacting with Software Verifier |
| |
|   **@property**<br>— **def [bcid\_verifier\_path](/recipe_modules/bcid_verifier/api.py#29)(self):** |
| |
| Returns the path to the bcid_verifier binary. |
| |
| When the property is accessed the first time, the latest stable, released |
| version of bcid_verifier will be installed using CIPD. |
| |
| — **def [verify\_provenance](/recipe_modules/bcid_verifier/api.py#39)(self, bcid_policy: str, artifact_path: str, attestation_path: str, log_only_mode: bool=False):** |
| |
| Calls the BCID Software Verifier API to verify provenance for an |
| artifact. |
| |
| Args: |
| * bcid_policy: This field name is slightly misleading, and it would be |
| better if it was called resource_uri. This arg represents the full |
| ResourceURI to use when verifying this artifact. It should include both |
| the name of a valid BCID Policy or Resource Prefix, and the unique path |
| to the artifact protected by this verification. As an example, a call to |
| SoftwareVerifier to verify the provenance of a Chrome artifact before |
| signing might use the following structure. |
| bcid_policy: chrome_app://chrome/desktop/win/ |
| artifact path: chrome-signed/desktop-5c0tCh/132.0.6834.0/win-clang/chrome.zip |
| Which would result in the following resource URI to use here: |
| chrome_app://chrome/desktop/win/chrome-signed/desktop-5c0tCh/132.0.6834.0/win-clang/chrome.zip |
| |
| * artifact_path: Local file path to the artifact to be verified. |
| * attestation_path: Local file path to the attestation (intoto.jsonl) file |
| for the provided artifact. |
| * log_only_mode: |
| Whether to verify provenance in log only mode, and skip enforcement. |
| Enforcement fails closed, and if unable to receive a response from |
| Software Verifier, it will constitute a rejection. In log only mode, |
| a failed request or a failure to verify will not be considered a |
| failure. |
| ### *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), [warning](#recipe_modules-warning) |
| |
| |
| API for interacting with the buildbucket service. |
| |
| Requires `buildbucket` command in `$PATH`: |
| https://godoc.org/go.chromium.org/luci/buildbucket/client/cmd/buildbucket |
| |
| #### **class [BuildbucketApi](/recipe_modules/buildbucket/api.py#43)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| A module for interacting with buildbucket. |
| |
| — **def [add\_tags\_to\_current\_build](/recipe_modules/buildbucket/api.py#285)(self, tags: list[common_pb2.StringPair]):** |
| |
| Adds arbitrary tags during the runtime of a build. |
| |
| Args: |
| * tags: 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 [backend\_hostname](/recipe_modules/buildbucket/api.py#1250)(self):** |
| |
| Returns the backend hostname for the build. |
| If it is legacy swarming build then the swarming hostname will be returned. |
| |
|   **@property**<br>— **def [backend\_task\_dimensions](/recipe_modules/buildbucket/api.py#1259)(self):** |
| |
| Returns the task dimensions used by the task for the build. |
| |
| |
| — **def [backend\_task\_dimensions\_from\_build](/recipe_modules/buildbucket/api.py#1265)(self, build: (build_pb2.Build | None)=None):** |
| |
| Returns the task dimensions for the provided build. |
| If no build is provided, then self.build will be used. |
| |
|   **@property**<br>— **def [backend\_task\_id](/recipe_modules/buildbucket/api.py#1278)(self):** |
| |
| Returns the task id of the task for the build. |
| |
| |
| — **def [backend\_task\_id\_from\_build](/recipe_modules/buildbucket/api.py#1284)(self, build: (build_pb2.Build | None)=None):** |
| |
| Returns the task id of the task for the provided build. |
| If no build is provided, then self.build will be used. |
| |
|   **@property**<br>— **def [bucket\_v1](/recipe_modules/buildbucket/api.py#1232)(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#137)(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. |
| |
| — **def [build\_url](/recipe_modules/buildbucket/api.py#201)(self, \*, host: (str | None)=None, build_id: ((int | str) | None)=None, build: (build_pb2.Build | None)=None):** |
| |
| Returns url to a build. Defaults to current build. |
| |
|   **@property**<br>— **def [builder\_cache\_path](/recipe_modules/buildbucket/api.py#312)(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\_full\_name](/recipe_modules/buildbucket/api.py#161)(self):** |
| |
| Returns the full builder name: {project}/{bucket}/{builder}. |
| |
|   **@property**<br>— **def [builder\_name](/recipe_modules/buildbucket/api.py#156)(self):** |
| |
| Returns builder name. Shortcut for `.build.builder.builder`. |
| |
|   **@property**<br>— **def [builder\_realm](/recipe_modules/buildbucket/api.py#171)(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 [builder\_url](/recipe_modules/buildbucket/api.py#184)(self, \*, host: (str | None)=None, project: (str | None)=None, bucket: (str | None)=None, builder: (str | None)=None, build: (build_pb2.Build | None)=None):** |
| |
| Returns url to a builder. Defaults to current builder. |
| |
| — **def [cancel\_build](/recipe_modules/buildbucket/api.py#887)(self, build_id: (int | str), reason: (str | None)=None, step_name: (str | None)=None):** |
| |
| Cancel the build associated with the provided build ID. |
| |
| Args: |
| * `build_id`: a buildbucket build ID. It should be either an integer or |
| the numeric value in string format (e.g. 123456789 or '123456789'). |
| * `reason`: reason for canceling the given build. Markdown is supported. |
| |
| Returns: |
| None if build is successfully canceled. Otherwise, an InfraFailure will |
| be raised |
| |
| — **def [collect\_build](/recipe_modules/buildbucket/api.py#1022)(self, build_id: str, \*\*kwargs: Any):** |
| |
| 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#1036)(self, build_ids: Sequence[(int | str)], interval: (int | None)=None, timeout: (int | None)=None, step_name: (str | None)=None, raise_if_unsuccessful: bool=False, url_title_fn: (UrlTitleFunction | None)=None, mirror_status: bool=False, fields: Set[str]=DEFAULT_FIELDS, cost: (engine_types.ResourceCost | None)=None, eager: bool=False):** |
| |
| 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"]). |
| * `cost`: A step.ResourceCost to override for the underlying bb invocation. |
| If not specified, will use the recipe_engine's default values for |
| ResourceCost. |
| * `eager`: Whether stop upon getting the first build. |
| |
| 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#993)(self, build_id: (int | str), url_title_fn: (UrlTitleFunction | None)=None, step_name: (str | None)=None, fields: Set[str]=DEFAULT_FIELDS, test_data: (build_pb2.Build | None)=None):** |
| |
| 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"]). |
| * `test_data`: a build_pb2.Build for use in testing. |
| |
| Returns: |
| A build_pb2.Build. |
| |
| — **def [get\_multi](/recipe_modules/buildbucket/api.py#929)(self, build_ids: Sequence[(int | str)], url_title_fn: (UrlTitleFunction | None)=None, step_name: (str | None)=None, fields: Set[str]=DEFAULT_FIELDS, test_data: (Sequence[build_pb2.Build] | None)=None):** |
| |
| 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"]). |
| * `test_data`: a sequence of build_pb2.Build objects for use in testing. |
| |
| Returns: |
| A dict {build_id: build_pb2.Build}. |
| |
|   **@property**<br>— **def [gitiles\_commit](/recipe_modules/buildbucket/api.py#213)(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#306)(self):** |
| |
| Hides the build in UI |
| |
|   **@host.setter**<br>— **def [host](/recipe_modules/buildbucket/api.py#109)(self, value: str):** |
| |
| — **def [is\_critical](/recipe_modules/buildbucket/api.py#224)(self, build: (build_pb2.Build | None)=None):** |
| |
| Returns True if the build is critical. Build defaults to the current one. |
| |
| |
| — **def [list\_builders](/recipe_modules/buildbucket/api.py#693)(self, project: str, bucket: str, step_name: (str | None)=None):** |
| |
| Lists configured builders in a bucket. |
| |
| Args: |
| * project: The name of the project to list from (e.g. 'chromeos'). |
| * bucket: The name of the bucket to list from (e.g. 'release'). |
| |
| Returns: |
| A list of builder names, excluding the project and bucket |
| (e.g. 'betty-pi-arc-release-main'). |
| |
| — **def [run](/recipe_modules/buildbucket/api.py#334)(self, schedule_build_requests: Sequence[builds_service_pb2.ScheduleBuildRequest], collect_interval: (int | None)=None, timeout: (int | None)=None, url_title_fn: (UrlTitleFunction | None)=None, step_name: (str | None)=None, raise_if_unsuccessful: bool=False, eager: bool=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#588)(self, schedule_build_requests: Sequence[builds_service_pb2.ScheduleBuildRequest], url_title_fn: (UrlTitleFunction | None)=None, step_name: (str | None)=None, include_sub_invs: bool=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.cv.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#370)(self, builder: str, project: (str | Inherit)=INHERIT, bucket: (str | Inherit)=INHERIT, properties: Mapping[(str, Any)]=None, experimental: ((bool | common_pb2.Trinary) | Inherit)=INHERIT, experiments: (Mapping[(str, bool)] | None)=None, gitiles_commit: (common_pb2.GitilesCommit | Inherit)=INHERIT, gerrit_changes: (Sequence[common_pb2.GerritChange] | Inherit)=INHERIT, tags: (Sequence[common_pb2.StringPair] | None)=None, inherit_buildsets: bool=True, swarming_parent_run_id: (str | None)=None, dimensions: (Sequence[common_pb2.RequestedDimension] | None)=None, priority: ((int | None) | Inherit)=INHERIT, critical: ((bool | common_pb2.Trinary) | Inherit)=INHERIT, exe_cipd_version: ((str | Inherit) | None)=None, fields: Set[str]=DEFAULT_FIELDS, can_outlive_parent: (bool | None)=None, as_shadow_if_parent_is_led: bool=False, led_inherit_parent: bool=False):** |
| |
| Creates a new `ScheduleBuildRequest` message with reasonable defaults. |
| |
| This is a convenience 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: name of the destination builder. |
| * project: project containing the destination builder. Defaults to the |
| project of the current build. |
| * bucket: bucket containing the destination builder. Defaults to the bucket |
| of the current build. |
| * properties: input properties for the new build. |
| * experimental: 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: enabled and disabled experiments for the new build. Overrides |
| the result computed from experiments defined in builder config. |
| * gitiles_commit: 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 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: tags for the new build. |
| * inherit_buildsets: if `True` (default), the returned request will include |
| buildset tags from the current build. |
| * swarming_parent_run_id: 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: override dimensions defined on the server. |
| * priority: 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: 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: CIPD version of the LUCI Executable (e.g. recipe) to |
| use. Pass `None` to use the server configured one. |
| * fields: 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. |
| * as_shadow_if_parent_is_led: flag for if to schedule the child build in |
| shadow bucket and have shadow adjustments applied, if the current build |
| is in shadow bucket. |
| Examples: |
| * if the child build inherits the parent's bucket (explicitly or |
| implicitly). |
| * if the parent is a normal build in bucket 'original', the child will |
| also be created in bucket 'original'. |
| * if the parent is a led build in bucket 'shadow', the child will also |
| be created in bucket 'shadow'. |
| * Note: the schdule request in this case will use bucket 'original' |
| instead of bucket `shadow`. It's because Buildbucket needs the |
| 'original' bucket to find the Builder config to generate the child |
| build so it can then put it in 'shadow' bucket. |
| * if the child build is using a different bucket from the parent, then |
| that bucket will be used in both normal and led flow to create the |
| child. |
| * led_inherit_parent: flag for if the child led build should inherit |
| agent_input and exe from its parent led build. It only takes effect if |
| the parent is a led build and `as_shadow_if_parent_is_led` is True. |
| |
| — **def [search](/recipe_modules/buildbucket/api.py#720)(self, predicate: builds_service_pb2.BuildPredicate, limit: (int | None)=None, url_title_fn: (UrlTitleFunction | None)=None, report_build: bool=True, step_name: (str | None)=None, fields: Set[str]=DEFAULT_FIELDS, timeout: (int | None)=None, test_data: (Callable[([], Sequence[build_pb2.Build])] | None)=None):** |
| |
| Searches builds with one predicate. |
| |
| 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), |
| )) |
| ``` |
| |
| Underneath it calls `bb batch` to perform the search, which should have a |
| better performance and memory usage than `bb ls`: since we could get the |
| batch response as a whole and take advantage of the proto recipe for direct |
| encoding/decoding. And the limit could be used as the page_size in |
| SearchBuildsRequest. |
| |
| — **def [search\_with\_multiple\_predicates](/recipe_modules/buildbucket/api.py#793)(self, predicate: Sequence[builds_service_pb2.BuildPredicate], limit: (int | None)=None, url_title_fn: (UrlTitleFunction | None)=None, report_build: bool=True, step_name: (str | None)=None, fields: Set[str]=DEFAULT_FIELDS, timeout: (int | None)=None, test_data: (Callable[([], Sequence[build_pb2.Build])] | None)=None):** |
| |
| Searches for builds with multiple predicates. |
| |
| Example: find all builds with one tag OR another. |
| |
| ```python |
| from PB.go.chromium.org.luci.buildbucket.proto import rpc as builds_service_pb2 |
| |
| related_builds = api.buildbucket.search([ |
| builds_service_pb2.BuildPredicate( |
| tags=['one.tag'], |
| ), |
| builds_service_pb2.BuildPredicate( |
| tags=['another.tag'], |
| ), |
| ]) |
| ``` |
| |
| Unlike search(), it still calls `bb ls` to keep the overall limit working. |
| |
| Args: |
| * predicate: a list of `builds_service_pb2.BuildPredicate` objects. |
| 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"]). |
| * timeout: if supplied, the recipe engine will kill the step after the |
| specified number of seconds |
| * test_data: A sequence of build_pb2.Build protos for this step to |
| return in testing. |
| |
| Returns: |
| A list of builds ordered newest-to-oldest. |
| |
| — **def [set\_output\_gitiles\_commit](/recipe_modules/buildbucket/api.py#230)(self, gitiles_commit: common_pb2.GitilesCommit):** |
| |
| 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: 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. |
| |
|   **@property**<br>— **def [shadowed\_bucket](/recipe_modules/buildbucket/api.py#1374)(self):** |
| |
|   **@property**<br>— **def [swarming\_bot\_dimensions](/recipe_modules/buildbucket/api.py#1297)(self):** |
| |
| Returns the swarming bot dimensions for the build. |
| |
| |
| — **def [swarming\_bot\_dimensions\_from\_build](/recipe_modules/buildbucket/api.py#1303)(self, build: (build_pb2.Build | None)=None):** |
| |
| Returns the swarming bot dimensions for the provided build. |
| If no build is provided, then self.build will be used. |
| |
|   **@property**<br>— **def [swarming\_parent\_run\_id](/recipe_modules/buildbucket/api.py#1326)(self):** |
| |
| Returns the parent_run_id (swarming specific) used in the task. |
| |
| |
|   **@property**<br>— **def [swarming\_priority](/recipe_modules/buildbucket/api.py#1345)(self):** |
| |
| Returns the priority (swarming specific) of the task. |
| |
| |
|   **@property**<br>— **def [swarming\_task\_service\_account](/recipe_modules/buildbucket/api.py#1359)(self):** |
| |
| Returns the swarming specific service account used in the task. |
| |
| |
|   **@staticmethod**<br>— **def [tags](/recipe_modules/buildbucket/api.py#280)(\*\*tags: (list[str] | str)):** |
| |
| Alias for tags in util.py. See doc there. |
| |
| — **def [use\_service\_account\_key](/recipe_modules/buildbucket/api.py#123)(self, key_path: (config_types.Path | str)):** |
| |
| 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: a path to JSON file with service account credentials. |
| |
|   **@contextlib.contextmanager**<br>— **def [with\_host](/recipe_modules/buildbucket/api.py#113)(self, host: str):** |
| |
| 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), [json](#recipe_modules-json), [path](#recipe_modules-path), [raw\_io](#recipe_modules-raw_io), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| |
| API for interacting with cas client. |
| |
| #### **class [CasApi](/recipe_modules/cas/api.py#14)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| A module for interacting with cas client. |
| |
| — **def [archive](/recipe_modules/cas/api.py#110)(self, step_name, root, \*paths, log_level='info', \*\*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. |
| * kwargs: Additional keyword arguments to forward to "step". |
| |
| Returns: |
| digest (str): digest of uploaded root directory. |
| |
| — **def [download](/recipe_modules/cas/api.py#81)(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#24)(self):** |
| |
| — **def [viewer\_url](/recipe_modules/cas/api.py#101)(self, digest):** |
| |
| Return URL of cas viewer. |
| |
|   **@contextlib.contextmanager**<br>— **def [with\_instance](/recipe_modules/cas/api.py#39)(self, instance):** |
| |
| Sets the CAS instance while in context, then reverts it. |
| ### *recipe_modules* / [cas\_input](/recipe_modules/cas_input) |
| |
| [DEPS](/recipe_modules/cas_input/__init__.py#9): [cas](#recipe_modules-cas), [path](#recipe_modules-path) |
| |
| |
| 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#22)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| A module for downloading CAS inputs to a recipe. |
| |
| — **def [download\_caches](/recipe_modules/cas_input/api.py#34)(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#30)(self):** |
| ### *recipe_modules* / [change\_verifier](/recipe_modules/change_verifier) |
| |
| [DEPS](/recipe_modules/change_verifier/__init__.py#7): [buildbucket](#recipe_modules-buildbucket), [cipd](#recipe_modules-cipd), [cv](#recipe_modules-cv), [luci\_config](#recipe_modules-luci_config), [proto](#recipe_modules-proto), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| |
| 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#39)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| This module provides recipe API of LUCI Change Verifier. |
| |
| — **def [match\_config](/recipe_modules/change_verifier/api.py#165)(self, host: str, change: int, project: (str | None)=None, config_name: str=cv_api.CONFIG_FILE):** |
| |
| Retrieve the applicable CV group for a given change. |
| |
| — **def [search\_runs](/recipe_modules/change_verifier/api.py#47)(self, project: str, cls: (((Sequence[(GerritChangeTuple | run_pb.GerritChange)] | GerritChangeTuple) | run_pb.GerritChange) | None)=None, limit: (int | None)=None, step_name: (str | None)=None, dev: bool=False):** |
| |
| Searches for Runs. |
| |
| Args: |
| * project: LUCI project name. |
| * cls: CLs, specified as (host, change number) tuples or |
| run_pb.GerritChanges. A single tuple or GerritChange may also be passed. |
| All Runs returned must include all of the given CLs, and Runs may also |
| contain other CLs. |
| * limit: max number of Runs to return. Defaults to 32. |
| * step_name: optional custom step name in RPC steps. |
| * dev: 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): [buildbucket](#recipe_modules-buildbucket), [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) |
| |
| |
| 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#246)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| 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#351)(self, pkg_path: str, reader: bool=True, writer: bool=False, owner: bool=False):** |
| |
| Checks whether the caller has a given roles in a package. |
| |
| Args: |
| * pkg_path - The package subpath. |
| * reader - Check for READER role. |
| * writer - Check for WRITER role. |
| * owner - Check for OWNER role. |
| |
| Returns True if the caller has given roles, False otherwise. |
| |
| — **def [add\_instance\_link](/recipe_modules/cipd/api.py#646)(self, step_result: step_data.StepData):** |
| |
| — **def [build](/recipe_modules/cipd/api.py#460)(self, input_dir: Path, output_package: Path, package_name: str, compression_level: (CompressionLevel | None)=None, install_mode: (InstallMode | None)=None, preserve_mtime: bool=False, preserve_writable: bool=False):** |
| |
| Builds, but does not upload, a cipd package from a directory. |
| |
| Args: |
| * input_dir - The directory to build the package from. |
| * output_package - The file to write the package to. |
| * package_name - The name of the cipd package as it would appear |
| when uploaded to the cipd package server. |
| * compression_level - Deflate compression level. If None, defaults to 5 |
| (0 - disable, 1 - best speed, 9 - best compression). |
| * install_mode - 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 - Preserve file's modification time. |
| * preserve_writable - Preserve file's writable permission bit. |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [build\_from\_pkg](/recipe_modules/cipd/api.py#436)(self, pkg_def: PackageDefinition, output_package: Path, compression_level: (CompressionLevel | None)=None):** |
| |
| Builds a package based on a PackageDefinition object. |
| |
| Args: |
| * pkg_def - The description of the package we want to create. |
| * output_package - The file to write the package to. |
| * compression_level - 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#408)(self, pkg_def: Path, output_package: Path, pkg_vars: dict[(str, str)]=None, compression_level: (CompressionLevel | None)=None):** |
| |
| Builds a package based on on-disk YAML package definition file. |
| |
| Args: |
| * pkg_def - The path to the yaml file. |
| * output_package - The file to write the package to. |
| * pkg_vars - A map of var name -> value to use for vars |
| referenced in package definition file. |
| * compression_level - 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#316)(self, directory: (Path | None)):** |
| |
| 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#690)(self, pkg_def: PackageDefinition, refs: (Sequence[str] | None)=None, tags: (Mapping[(str, str)] | None)=None, metadata: (Sequence[Metadata] | None)=None, compression_level: (CompressionLevel | None)=None, verification_timeout: (str | None)=None):** |
| |
| Builds and uploads a package based on a PackageDefinition object. |
| |
| This builds and uploads the package in one step. |
| |
| Args: |
| * pkg_def - The description of the package we want to create. |
| * refs - A list of ref names to set for the package instance. |
| * tags - A map of tag name -> value to set for the package instance. |
| * metadata - A list of metadata entries to attach. |
| * compression_level - Deflate compression level. If None, defaults to 5 |
| (0 - disable, 1 - best speed, 9 - best compression). |
| * verification_timeout - 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#651)(self, pkg_def: Path, refs: (Sequence[str] | None)=None, tags: (Mapping[(str, str)] | None)=None, metadata: (Sequence[Metadata] | None)=None, pkg_vars: (Mapping[(str, str)] | None)=None, compression_level: (CompressionLevel | None)=None, verification_timeout: (str | None)=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 - The path to the yaml file. |
| * refs - A list of ref names to set for the package instance. |
| * tags - A map of tag name -> value to set for the package instance. |
| * metadata - A list of metadata entries to attach. |
| * pkg_vars - A map of var name -> value to use for vars |
| referenced in package definition file. |
| * compression_level - Deflate compression level. If None, defaults to 5 |
| (0 - disable, 1 - best speed, 9 - best compression). |
| * verification_timeout - 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#937)(self, package_name: str, version: str, test_data_refs: (Sequence[str] | None)=None, test_data_tags: (Sequence[str] | None)=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 - The name of the cipd package. |
| * version - The package version to point the ref to. |
| * test_data_refs - The list of refs for this call to return |
| by default when in test mode. |
| * test_data_tags - 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#725)(self, root: Path, ensure_file: (EnsureFile | Path), name: str='ensure_installed'):** |
| |
| Ensures that packages are installed in a given root dir. |
| |
| Args: |
| * root - Path to installation site root directory. |
| * ensure_file - List of packages to install. |
| * name - Step display name. |
| |
| Returns the map of subdirectories to CIPDApi.Pin instances. |
| |
| — **def [ensure\_file\_resolve](/recipe_modules/cipd/api.py#772)(self, ensure_file: (EnsureFile | Path), name: str='cipd ensure-file-resolve'):** |
| |
| Resolves versions of all packages for all verified platforms in an |
| ensure file. |
| |
| Args: |
| * ensure_file - Ensure file to resolve. |
| |
| — **def [ensure\_tool](/recipe_modules/cipd/api.py#1069)(self, package: str, version: str, executable_path: (str | None)=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 - The full name of the CIPD package. |
| * version - The version of the package to download. |
| * executable_path - 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#328)(self):** |
| |
| — **def [instances](/recipe_modules/cipd/api.py#972)(self, package_name: str, limit: (int | None)=None):** |
| |
| Lists instances of a package, most recently uploaded first. |
| |
| Args: |
| * package_name - The name of the cipd package. |
| * limit - 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 [make\_link](/recipe_modules/cipd/api.py#643)(self, package: str, version: str):** |
| |
| — **def [pkg\_deploy](/recipe_modules/cipd/api.py#1045)(self, root: Path, package_file: Path):** |
| |
| 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 to a package file to install. |
| * root - Path to a CIPD root. |
| |
| Returns a Pin for the deployed package. |
| |
| — **def [pkg\_fetch](/recipe_modules/cipd/api.py#1011)(self, destination: Path, package_name: str, version: str):** |
| |
| 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 to a file location which will be (over)written |
| with the package file contents. |
| * package_name - The package name (or pattern with e.g. ${platform}) |
| * version - The CIPD version to fetch |
| |
| Returns a Pin for the downloaded package. |
| |
|   **@property**<br>— **def [platform](/recipe_modules/cipd/api.py#1145)(self):** |
| |
| Returns the CIPD platform string, equivalent to '${platform}'. |
| |
| — **def [register](/recipe_modules/cipd/api.py#572)(self, package_name: str, package_path: Path, refs: (Sequence[str] | None)=None, tags: (Mapping[(str, str)] | None)=None, metadata: Sequence[Metadata]=None, verification_timeout: (str | None)=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#900)(self, package_name: str, tag: str, test_instances: ((list[str] | int) | None)=None):** |
| |
| Searches for package instances by tag, optionally constrained by package |
| name. |
| |
| Args: |
| * package_name - The name of the cipd package. |
| * tag - The cipd package tag. |
| * test_instances - 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#838)(self, package_name: str, version: str, metadata: list[Metadata]):** |
| |
| Attaches metadata to a package instance. |
| |
| Args: |
| * package_name - The name of the cipd package. |
| * version - The package version to attach metadata to. |
| * metadata - A list of metadata entries to attach. |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [set\_ref](/recipe_modules/cipd/api.py#869)(self, package_name: str, version: str, refs: list[str]):** |
| |
| Moves a ref to point to a given version. |
| |
| Args: |
| * package_name - The name of the cipd package. |
| * version - The package version to point the ref to. |
| * refs - A list of ref names to set for the package instance. |
| |
| Returns the CIPDApi.Pin instance. |
| |
| — **def [set\_tag](/recipe_modules/cipd/api.py#806)(self, package_name: str, version: str, tags: dict[(str, str)]):** |
| |
| Tags package of a specific version. |
| |
| Args: |
| * package_name - The name of the cipd package. |
| * version - The package version to resolve. Could also be itself a |
| tag or ref. |
| * tags - 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) |
| |
| |
| #### **class [CommitPositionApi](/recipe_modules/commit_position/api.py#12)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| Recipe module providing commit position parsing and formatting. |
| |
|   **@classmethod**<br>— **def [format](/recipe_modules/commit_position/api.py#28)(cls, ref, revision_number):** |
| |
| Returns a commit position string. |
| |
| ref must start with 'refs/'. |
| |
|   **@classmethod**<br>— **def [parse](/recipe_modules/commit_position/api.py#18)(cls, value):** |
| |
| Returns (ref, revision_number) tuple. |
| ### *recipe_modules* / [context](/recipe_modules/context) |
| |
| |
| 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 / '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#439)):** |
| |
|   **@contextlib.contextmanager**<br>— **def [\_\_call\_\_](/recipe_modules/context/api.py#112)(self, cwd: (config_types.Path | None)=None, env_prefixes: (Mapping[(str, Sequence[str])] | None)=None, env_suffixes: (Mapping[(str, Sequence[str])] | None)=None, env: (Mapping[(str, str)] | None)=None, infra_steps: (bool | None)=None, luciexe: (sections_pb2.LUCIExe | None)=None, realm: str=None, deadline: (sections_pb2.Deadline | None)=None):** |
| |
| Allows adjustment of multiple context values in a single call. |
| |
| Args: |
| * cwd - 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 - Environmental variable prefix augmentations. See below |
| for more info. |
| * env_suffixes - Environmental variable suffix augmentations. See below |
| for more info. |
| * env - Environmental variable overrides. See below for more info. |
| * infra_steps - if steps in this context should be considered |
| infrastructure steps. On failure, these will raise InfraFailure |
| exceptions instead of StepFailure exceptions. |
| * 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 - 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 - 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#263)(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#356)(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#273)(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#288)(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#302)(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#316)(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#324)(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#336)(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#346)(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#367)(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): [cv](#recipe_modules-cv), [properties](#recipe_modules-properties), [warning](#recipe_modules-warning) |
| |
| |
| Wrapper for CV API. |
| |
| #### **class [CQApi](/recipe_modules/cq/api.py#20)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| This module is a thin wrapper of the cv module. |
| |
| — **def [initialize](/recipe_modules/cq/api.py#27)(self):** |
| |
| Apply non-default value cq module properties to the cv module. |
| ### *recipe_modules* / [cv](/recipe_modules/cv) |
| |
| [DEPS](/recipe_modules/cv/__init__.py#9): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| Recipe API for LUCI CV, the pre-commit testing system. |
| |
| #### **class [CVApi](/recipe_modules/cv/api.py#20)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| This module provides recipe API of LUCI CV, a pre-commit testing system. |
| |
|   **@property**<br>— **def [active](/recipe_modules/cv/api.py#52)(self):** |
| |
| Returns whether CQ is active for this build. |
| |
| — **def [allow\_reuse\_for](/recipe_modules/cv/api.py#255)(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/cv/api.py#251)(self):** |
| |
|   **@property**<br>— **def [attempt\_key](/recipe_modules/cv/api.py#140)(self):** |
| |
| Returns a string that is unique for a CV attempt. |
| |
| The same `attempt_key` will be used for all builds within an |
| attempt. |
| |
| Raises: |
| CQInactive if CQ is not active for this build. |
| |
|   **@property**<br>— **def [cl\_group\_key](/recipe_modules/cv/api.py#152)(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 [cl\_owners](/recipe_modules/cv/api.py#178)(self):** |
| |
| Returns string(s) of the owner's email addresses used for the patchset. |
| |
| Usually CLs only have one owner, but more than one is possible so a list |
| will be returned. |
| |
| Raises: |
| CQInactive if CQ is not active for this build. |
| |
|   **@property**<br>— **def [do\_not\_retry\_build](/recipe_modules/cv/api.py#233)(self):** |
| |
|   **@property**<br>— **def [equivalent\_cl\_group\_key](/recipe_modules/cv/api.py#165)(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/cv/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/cv/api.py#42)(self):** |
| |
|   **@property**<br>— **def [ordered\_gerrit\_changes](/recipe_modules/cv/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 [owner\_is\_googler](/recipe_modules/cv/api.py#273)(self):** |
| |
| Returns whether the Run/Attempt owner is a Googler. |
| |
| DO NOT USE: this is a temporary workaround for crbug.com/1259887 that is |
| supposed to be used by builders in Chrome project only. |
| Raises: |
| CQInactive if CQ is not active for this build. |
| ValueError if the builder is not in Chrome project. |
| |
|   **@property**<br>— **def [props\_for\_child\_build](/recipe_modules/cv/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.cv.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.cv.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/cv/api.py#217)(self, \*build_ids):** |
| |
| Adds the given Buildbucket build IDs to the list of triggered build IDs. |
| |
| Must be called after some step. |
| |
| Args: |
| * build_ids (list of int or string): Buildbucket build IDs. |
| |
| — **def [record\_triggered\_builds](/recipe_modules/cv/api.py#201)(self, \*builds):** |
| |
| Adds IDs of given Buildbucket builds to the list of triggered build IDs. |
| |
| Must be called after some step. |
| |
| Expected usage: |
| ```python |
| api.cv.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/cv/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/cv/api.py#237)(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/cv/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/cv/api.py#196)(self):** |
| |
| Returns recorded Buildbucket build IDs as a list of integers. |
| ### *recipe_modules* / [defer](/recipe_modules/defer) |
| |
| [DEPS](/recipe_modules/defer/__init__.py#7): [step](#recipe_modules-step) |
| |
| |
| Runs a function but defers the result until a later time. |
| |
| #### **class [DeferApi](/recipe_modules/defer/api.py#107)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| Runs a function but defers the result until a later time. |
| |
| Exceptions caught by api.defer() will show in MILO as they occur, but won't |
| continue to propagate the exception until api.defer.collect() or |
| DeferredResult.result() is called. |
| |
| For StepFailures and InfraFailures, MILO already includes the failure output. |
| For other exceptions, api.defer() will add a step showing the exception and |
| continue. |
| |
| If exceptions were caught and saved in DeferredResults, api.defer.collect() |
| will raise an ExceptionGroup containing all deferred exceptions. |
| ExceptionGroups containing specific kinds of exceptions can be handled using |
| the "except*" syntax (for more details see |
| https://docs.python.org/3/tutorial/errors.html#raising-and-handling-multiple-unrelated-exceptions). |
| |
| If there are no failures, api.defer.collect() returns a Sequence of the |
| return values of the functions passed into api.defer(). |
| |
| — **def [\_\_call\_\_](/recipe_modules/defer/api.py#173)(self, func: Callable[(..., T)], \*args, \*\*kwargs):** |
| |
| Calls func(*args, **kwargs) but catches all exceptions. |
| |
| Returns a DeferredResult. If the call returns a value, the DeferredResult |
| contains that value. If the call raises an exception, the DeferredResult |
| contains that exception. |
| |
| The DeferredResult is expected to be passed into api.defer.collect(), but |
| DeferredResult.result() does similar processing. |
| |
| — **def [collect](/recipe_modules/defer/api.py#190)(self, results: Sequence[DeferredResult], step_name: (str | None)=None):** |
| |
| Raise any exceptions in the given list of DeferredResults. |
| |
| If there are no exceptions, do nothing. If there are one or more exceptions, |
| reraise one of the worst of them. |
| |
| Args: |
| results: Results to check. |
| step_name: Name for step including traceback logs if there are failures. |
| If None, don't include a step with traceback logs. |
| |
|   **@contextlib.contextmanager**<br>— **def [context](/recipe_modules/defer/api.py#131)(self, collect_step_name: (str | None)=None):** |
| |
| Creates a context that tracks deferred calls. |
| |
| Usage: |
| |
| with api.defer.context() as defer: |
| defer(api.step, ...) |
| defer(api.step, ...) |
| ... |
| # api.defer.collect() is called on exiting the context. |
| ### *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) |
| |
| |
| File manipulation (read/write/delete/glob) methods. |
| |
| #### **class [FileApi](/recipe_modules/file/api.py#96)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [chmod](/recipe_modules/file/api.py#220)(self, name: str, path: (config_types.Path | str), mode: str, recursive: bool=False):** |
| |
| Set the access mode for a file or directory. |
| |
| Args: |
| * name: The name of the step. |
| * path: The path of the file or directory. |
| * mode: The access mode in octal. |
| * recursive: Whether to run chmod recursively. |
| |
| Raises: file.Error |
| |
| — **def [compute\_hash](/recipe_modules/file/api.py#301)(self, name: str, paths: Sequence[(config_types.Path | str)], base_path: (config_types.Path | str), test_data: str=''):** |
| |
| 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: The name of the step. |
| * paths: Path of directory/file(s) to compute hash. |
| * base_path: Base directory to calculating hash relative to absolute path. |
| For e.g. `start_dir` of a recipe execution can be used. |
| * test_data: 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: |
| 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#153)(self, name: str, source: ((config_types.Path | str) | recipe_api.Placeholder), dest: ((config_types.Path | str) | recipe_api.Placeholder)):** |
| |
| Copies a file (including mode bits) from source to destination on the |
| local filesystem. |
| |
| Behaves identically to shutil.copy. |
| |
| Args: |
| * name: The name of the step. |
| * source: The path to the file you want to copy. |
| * dest: 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#179)(self, name: str, source: (config_types.Path | str), dest: (config_types.Path | str), symlinks: bool=False, hardlink: bool=False, allow_override: bool=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. |
| * hardlink (bool): Create hardlinks using os.link(), instead of copying |
| the files. |
| * allow_override (bool): If True, existing files in `dest` will be |
| overridden. If False or not specified, the copy will be stopped with |
| raising `file.Error` exception if the file exists in `dest`. |
| |
| Raises: file.Error |
| |
| — **def [ensure\_directory](/recipe_modules/file/api.py#691)(self, name: str, dest: (config_types.Path | str), mode: int=511):** |
| |
| Ensures that `dest` exists and is a directory. |
| |
| Args: |
| * name: The name of the step. |
| * dest: The directory to ensure. |
| * mode: 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#268)(self, file_path: (config_types.Path | str), test_data: str=''):** |
| |
| Computes hash of contents of a single file. |
| |
| Args: |
| * file_path: Path of file to compute hash. |
| * test_data: 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: |
| 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#713)(self, name: str, files: Sequence[(config_types.Path | str)], test_data: (Sequence[int] | None)=None):** |
| |
| Returns list of filesizes for the given files. |
| |
| Args: |
| * name: The name of the step. |
| * files: Paths to files. |
| * test_data: List of filesizes to use in tests. |
| |
| Returns size of each file in bytes. |
| |
| — **def [flatten\_single\_directories](/recipe_modules/file/api.py#887)(self, name: str, path: (config_types.Path | str)):** |
| |
| 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: The name of the step. |
| * path: The absolute path to begin flattening. |
| |
| Raises: file.Error |
| |
| — **def [glob\_paths](/recipe_modules/file/api.py#586)(self, name: str, source: (config_types.Path | str), pattern: str, include_hidden: bool=False, test_data: Sequence[str]=()):** |
| |
| Performs glob expansion on `pattern`. |
| |
| glob rules for `pattern` follow the same syntax as for the stdlib `glob` |
| module with `recursive=True`. |
| |
| ``` |
| 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 all paths found. |
| |
| Raises: file.Error. |
| |
| — **def [listdir](/recipe_modules/file/api.py#652)(self, name: str, source: (config_types.Path | str), recursive: bool=False, test_data: Sequence[str]=(), include_log: bool=True):** |
| |
| Lists all files inside a directory. |
| |
| If the source dir contains non-unicode file or dir names, the corresponding |
| bad characters will be replace with "?" mark. |
| |
| Args: |
| * name: The name of the step. |
| * source: The directory to list. |
| * recursive: 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: Some default data for this step to return |
| when running under simulation. This should be the list of relative |
| paths found in this directory. |
| * include_log: Include step log of read text. |
| |
| Returns list of entries |
| |
| Raises: file.Error. |
| |
| — **def [move](/recipe_modules/file/api.py#244)(self, name: str, source: (config_types.Path | str), dest: (config_types.Path | str)):** |
| |
| 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#458)(self, name: str, source: (config_types.Path | str), test_data: Any='', include_log: bool=True):** |
| |
| Reads a file as UTF-8 encoded json. |
| |
| Args: |
| * name: The name of the step. |
| * source: The path of the file to read. |
| * test_data: Some default json serializable data for this step to return |
| when running under simulation. |
| * include_log: Include step log of read json. |
| |
| Returns: The content of the file. |
| |
| Raise file.Error |
| |
| — **def [read\_proto](/recipe_modules/file/api.py#510)(self, name: str, source: (config_types.Path | str), msg_class: type[ProtoMessage], codec: ProtoCodec, test_proto: Any=None, include_log: bool=True, decoding_kwargs: (dict | None)=None):** |
| |
| Reads a file into a proto message. |
| |
| Args: |
| * name: The name of the step. |
| * source: The path of the file to read. |
| * msg_class: The message type to be read. |
| * codec: The encoder to use. |
| * test_proto: A default proto message for this step to return when |
| running under simulation. |
| * include_log: Include step log of read proto. |
| * decoding_kwargs: Passed directly to the chosen encoder. See proto |
| module for details. |
| |
| — **def [read\_raw](/recipe_modules/file/api.py#358)(self, name: str, source: (config_types.Path | str), test_data: bytes=''):** |
| |
| Reads a file as raw data. |
| |
| Args: |
| * name: The name of the step. |
| * source: The path of the file to read. |
| * test_data: Some default data for this step to return when running under |
| simulation. |
| |
| Returns: The unencoded (binary) contents of the file. |
| |
| Raises: file.Error |
| |
| — **def [read\_text](/recipe_modules/file/api.py#403)(self, name: str, source: (config_types.Path | str), test_data: str='', include_log: bool=True):** |
| |
| Reads a file as UTF-8 encoded text. |
| |
| Args: |
| * name: The name of the step. |
| * source: The path of the file to read. |
| * test_data: Some default data for this step to return when running under |
| simulation. |
| * include_log: Include step log of read text. |
| |
| Returns: The content of the file. |
| |
| Raises: file.Error |
| |
| — **def [remove](/recipe_modules/file/api.py#632)(self, name: str, source: (config_types.Path | str)):** |
| |
| 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#763)(self, name: str, source: (config_types.Path | str)):** |
| |
| 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#786)(self, name: str, source: (config_types.Path | str), pattern: str, recursive: bool=True, include_hidden: bool=True):** |
| |
| Removes all entries in `source` matching the glob `pattern`. |
| |
| glob rules for `pattern` follow the same syntax as for the stdlib `glob` |
| module with `recursive=True`. |
| |
| ``` |
| 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: The name of the step. |
| * source: The directory whose contents should be filtered and removed. |
| * pattern: The glob pattern to apply under `source`. Anything matching |
| this pattern will be removed. |
| * recursive: Recursively remove entries under `source`. |
| TODO: Remove this option. Use `**` syntax instead. |
| * include_hidden: 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#741)(self, name: str, source: (config_types.Path | str)):** |
| |
| 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: The name of the step. |
| * source: The directory to remove. |
| |
| Raises: file.Error. |
| |
| — **def [symlink](/recipe_modules/file/api.py#838)(self, name: str, source: ((config_types.Path | str) | recipe_api.Placeholder), linkname: ((config_types.Path | str) | recipe_api.Placeholder)):** |
| |
| 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#861)(self, root: (config_types.Path | str)):** |
| |
| Creates a SymlinkTree, given a root directory. |
| |
| Args: |
| * root: root of a tree of symlinks. |
| |
| — **def [truncate](/recipe_modules/file/api.py#869)(self, name: str, path: (config_types.Path | str), size_mb: int=100):** |
| |
| Creates an empty file with path and size_mb on the local filesystem. |
| |
| Args: |
| * name: The name of the step. |
| * path: The absolute path to create. |
| * size_mb: The size of the file in megabytes. Defaults to 100 |
| |
| Raises: file.Error |
| |
| — **def [write\_json](/recipe_modules/file/api.py#483)(self, name: str, dest: (config_types.Path | str), data: Any, indent: ((int | str) | None)=None, include_log: bool=True, sort_keys: bool=True):** |
| |
| Write the given json serializable `data` to `dest`. |
| |
| Args: |
| * name: The name of the step. |
| * dest: The path of the file to write. |
| * data: Json serializable data to write. |
| * indent: The indent of the written JSON. See |
| https://docs.python.org/3/library/json.html#json.dump for more details. |
| * include_log: Include step log of written json. |
| * sort_keys: Sort they keys in `data`. See api.json.input(). |
| |
| Raises: file.Error. |
| |
| — **def [write\_proto](/recipe_modules/file/api.py#552)(self, name: str, dest: (config_types.Path | str), proto_msg: google.protobuf.message, codec: ProtoCodec, include_log: bool=True, encoding_kwargs: (dict | None)=None):** |
| |
| Writes the given proto message to `dest`. |
| |
| Args: |
| * name: The name of thhe step. |
| * dest: The path of the file to write. |
| * proto_msg: Message to write. |
| * codec: The encoder to use. |
| * include_log: Include step log of written proto. |
| * encoding_kwargs: Passed directly to the chosen encoder. See proto |
| module for details. |
| |
| — **def [write\_raw](/recipe_modules/file/api.py#383)(self, name: str, dest: (config_types.Path | str), data: bytes):** |
| |
| Write the given `data` to `dest`. |
| |
| Args: |
| * name: The name of the step. |
| * dest: The path of the file to write. |
| * data: The data to write. |
| |
| Raises: file.Error. |
| |
| — **def [write\_text](/recipe_modules/file/api.py#433)(self, name: str, dest: (config_types.Path | str), text_data: str, include_log: bool=True):** |
| |
| Write the given UTF-8 encoded `text_data` to `dest`. |
| |
| Args: |
| * name: The name of the step. |
| * dest: The path of the file to write. |
| * text_data: The UTF-8 encoded data to write. |
| * include_log: Include step log of written text. |
| |
| Raises: file.Error. |
| ### *recipe_modules* / [findings](/recipe_modules/findings) |
| |
| [DEPS](/recipe_modules/findings/__init__.py#7): [buildbucket](#recipe_modules-buildbucket), [proto](#recipe_modules-proto), [resultdb](#recipe_modules-resultdb), [step](#recipe_modules-step), [uuid](#recipe_modules-uuid) |
| |
| |
| #### **class [FindingsAPI](/recipe_modules/findings/api.py#17)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [populate\_source\_from\_current\_build](/recipe_modules/findings/api.py#169)(self, location: findings_pb.Location):** |
| |
| Set the location source based on the input of the current build. |
| |
| This can be used for finding.location or replacement.location. Currently, |
| only works for build with exactly one Gerrit change. Raise ValueError |
| otherwise. |
| |
| — **def [upload\_findings](/recipe_modules/findings/api.py#47)(self, findings: list[findings_pb.Finding], step_name: (str | None)=None):** |
| |
| Uploads code findings to ResultDB. |
| |
| Requires ResultDB to be enabled for the current Build. |
| |
| Args: |
| * findings (List(findings_pb.Finding)): Code findings to upload. |
| findings definition can be found in |
| https://chromium.googlesource.com/infra/luci/recipes-py/+/HEAD/recipe_proto/go.chromium.org/luci/common/proto/findings/findings.proto |
| * step_name (str): optional step name for uploading findings. |
| ### *recipe_modules* / [futures](/recipe_modules/futures) |
| |
| |
| Implements in-recipe concurrency via green threads. |
| |
| #### **class [FuturesApi](/recipe_modules/futures/api.py#168)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| Provides access to the Recipe concurrency primitives. |
| |
|   **@staticmethod**<br>— **def [iwait](/recipe_modules/futures/api.py#369)(futures: Iterable[Future[Any]], timeout: Optional[float]=None, count: Optional[int]=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#179)(self, value: int=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#207)(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#249)(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#315)(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#348)(futures: Iterable[Future[Any]], timeout: Optional[float]=None, count: Optional[int]=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) |
| |
| |
| A simple method for running steps generated by an external script. |
| |
| #### **class [GeneratorScriptApi](/recipe_modules/generator_script/api.py#14)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [\_\_call\_\_](/recipe_modules/generator_script/api.py#73)(self, path_to_script, \*args, checkout_dir=None, \*\*_):** |
| |
| 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. |
| |
| If `path_to_script` ends with .py, it will be run with `vpython3`. |
| |
| 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) |
| |
| |
| #### **class [GolangApi](/recipe_modules/golang/api.py#12)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
|   **@contextlib.contextmanager**<br>— **def [\_\_call\_\_](/recipe_modules/golang/api.py#17)(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), [warning](#recipe_modules-warning) |
| |
| |
| Methods for producing and consuming JSON. |
| |
| #### **class [JsonApi](/recipe_modules/json/api.py#132)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
|   **@staticmethod**<br>— **def [dumps](/recipe_modules/json/api.py#133)(\*args, \*\*kwargs):** |
| |
| Works like `json.dumps`. |
| |
| By default this sorts dictionary keys (see discussion in `input()`), but you |
| can pass sort_keys=False to override this behavior. |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#163)**<br>— **def [input](/recipe_modules/json/api.py#160)(self, data, sort_keys=True):** |
| |
| A placeholder which will expand to a file path containing <data>. |
| |
| By default this sorts dictionaries in `data` to make this output |
| deterministic. In python3, dictionary insertion order is preserved per-spec, |
| so this is no longer necessary for determinism, and in some cases (such as |
| SPDX), the 'pretty' output is in non-alphabetical order. The default remains |
| `True`, however, to avoid breaking all downstream tests. |
| |
| — **def [is\_serializable](/recipe_modules/json/api.py#152)(self, obj):** |
| |
| Returns True if the object is JSON-serializable. |
| |
|   **@staticmethod**<br>— **def [loads](/recipe_modules/json/api.py#142)(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#163)**<br>— **def [output](/recipe_modules/json/api.py#172)(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#187)(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#9): [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) |
| |
| |
| An interface to call the led tool. |
| |
| #### **class [LedApi](/recipe_modules/led/api.py#23)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| 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:linux-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#216)(self, \*cmd: str):** |
| |
| Runs led with the given arguments. Wraps result in a `LedResult`. |
| |
|   **@property**<br>— **def [cipd\_input](/recipe_modules/led/api.py#199)(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#155)(self):** |
| |
| — **def [inject\_input\_recipes](/recipe_modules/led/api.py#221)(self, led_result: LedResult):** |
| |
| 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#176)(self):** |
| |
| Whether the current build is a led job. |
| |
|   **@property**<br>— **def [led\_build](/recipe_modules/led/api.py#171)(self):** |
| |
| Whether the current build is a led job as a real Buildbucket build. |
| |
|   **@property**<br>— **def [rbe\_cas\_input](/recipe_modules/led/api.py#190)(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#181)(self):** |
| |
| A unique string identifier for this led job, if it's a raw swarming task. |
| |
| If the current build is *not* a led job as raw swarming task, value will be |
| an empty string. |
| |
|   **@property**<br>— **def [shadowed\_bucket](/recipe_modules/led/api.py#207)(self):** |
| |
| The bucket of the original build/builder the led build replicates from. |
| |
| If set, it will be an `InputProperties.ShadowedBucket` protobuf; |
| otherwise None. |
| |
| — **def [trigger\_builder](/recipe_modules/led/api.py#234)(self, project_name: str, bucket_name: str, builder_name: str, properties: dict, use_payload: bool=False):** |
| |
| 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. |
| * use_payload - Use edit-payload or edit -rbh to update cas input. |
| ### *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) |
| |
| |
| 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#25)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [\_\_call\_\_](/recipe_modules/legacy_annotation/api.py#29)(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* / [luci\_analysis](/recipe_modules/luci_analysis) |
| |
| [DEPS](/recipe_modules/luci_analysis/__init__.py#7): [json](#recipe_modules-json), [step](#recipe_modules-step) |
| |
| |
| API for interacting with the LUCI Analysis RPCs |
| |
| This API is for calling LUCI Analysis RPCs for various aggregated info about |
| test results. |
| See go/luci-analysis for more info. |
| |
| #### **class [LuciAnalysisApi](/recipe_modules/luci_analysis/api.py#32)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [lookup\_bug](/recipe_modules/luci_analysis/api.py#265)(self, bug_id, system='monorail'):** |
| |
| Looks up the rule associated with a given bug. |
| |
| This is a wrapper of `luci.analysis.v1.Rules` `LookupBug` API. |
| |
| Args: |
| bug_id (str): Bug Id is the bug tracking system-specific identity of the |
| bug. For monorail, the scheme is {project}/{numeric_id}, for buganizer |
| the scheme is {numeric_id}. |
| system (str): System is the bug tracking system of the bug. This is either |
| "monorail" or "buganizer". Defaults to monorail. |
| |
| Returns: |
| list of rules (str), Format: projects/{project}/rules/{rule_id} |
| |
| — **def [query\_cluster\_failures](/recipe_modules/luci_analysis/api.py#300)(self, cluster_name):** |
| |
| Queries examples of failures in the given cluster. |
| |
| This is a wrapper of `luci.analysis.v1.Clusters` `QueryClusterFailures` API. |
| |
| Args: |
| cluster_name (str): The resource name of the cluster to retrieve. |
| Format: projects/{project}/clusters/{cluster_algorithm}/{cluster_id} |
| |
| Returns: |
| list of DistinctClusterFailure |
| |
| For value format, see [`DistinctClusterFailure` message] |
| (https://bit.ly/DistinctClusterFailure) |
| |
| — **def [query\_failure\_rate](/recipe_modules/luci_analysis/api.py#86)(self, test_and_variant_list, project='chromium'):** |
| |
| Queries LUCI Analysis for failure rates |
| |
| Args: |
| test_and_variant_list list(Test): List of dicts containing testId and |
| variantHash |
| project (str): Optional. The LUCI project to query the failures from. |
| Returns: |
| List of TestVariantFailureRateAnalysis protos |
| |
| — **def [query\_stability](/recipe_modules/luci_analysis/api.py#119)(self, test_variant_position_list, project='chromium'):** |
| |
| Queries LUCI Analysis for test stability. |
| |
| Args: |
| test_variant_position_list list(TestVariantPosition): List of dicts |
| containing testId, variant and source position |
| project (str): Optional. The LUCI project to query the failures from. |
| Returns: |
| Tuple of (List(TestVariantStabilityAnalysis), TestStabilityCriteria) |
| Raises: |
| StepFailure if query is invalid or service returns unexpected responses. |
| |
| — **def [query\_test\_history](/recipe_modules/luci_analysis/api.py#155)(self, test_id, project='chromium', sub_realm=None, variant_predicate=None, partition_time_range=None, submitted_filter=None, page_size=1000, page_token=None):** |
| |
| A wrapper method to use `luci.analysis.v1.TestHistory` `Query` API. |
| |
| Args: |
| test_id (str): test ID to query. |
| project (str): Optional. The LUCI project to query the history from. |
| sub_realm (str): Optional. The realm without the "<project>:" prefix. |
| E.g. "try". Default all test verdicts will be returned. |
| variant_predicate (luci.analysis.v1.VariantPredicate): Optional. The |
| subset of test variants to request history for. Default all will be |
| returned. |
| partition_time_range (luci.analysis.v1.common.TimeRange): Optional. A |
| range of timestamps to query the test history from. Default all will be |
| returned. (At most recent 90 days as TTL). |
| submitted_filter (luci.analysis.v1.common.SubmittedFilter): Optional. |
| Whether test verdicts generated by code with unsubmitted changes (e.g. |
| Gerrit changes) should be included in the response. Default all will be |
| returned. Default all will be returned. |
| page_size (int): Optional. 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 1000. |
| page_token (str): Optional. 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. |
| |
| Returns: |
| (list of parsed luci.analysis.v1.TestVerdict objects, next page token) |
| |
| — **def [query\_variants](/recipe_modules/luci_analysis/api.py#216)(self, test_id, project='chromium', sub_realm=None, variant_predicate=None, page_size=1000, page_token=None):** |
| |
| A wrapper method to use `luci.analysis.v1.TestHistory` `QueryVariants` |
| API. |
| |
| Args: |
| |
| test_id (str): test ID to query. |
| project (str): Optional. The LUCI project to query the variants from. |
| sub_realm (str): Optional. The realm without the "<project>:" prefix. |
| E.g. "try". Default all test verdicts will be returned. |
| variant_predicate (luci.analysis.v1.VariantPredicate): Optional. The |
| subset of test variants to request history for. Default all will be |
| returned. |
| page_size (int): Optional. 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 1000. |
| page_token (str): Optional. 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. |
| |
| Returns: |
| (list of VariantInfo { variant_hash: str, variant: { def: dict } }, |
| next page token) |
| |
| — **def [rule\_name\_to\_cluster\_name](/recipe_modules/luci_analysis/api.py#289)(self, rule):** |
| |
| Convert the resource name for a rule to its corresponding cluster. |
| Args: |
| rule (str): Format: projects/{project}/rules/{rule_id} |
| Returns: |
| cluster (str): Format: |
| projects/{project}/clusters/{cluster_algorithm}/{cluster_id}. |
| ### *recipe_modules* / [luci\_config](/recipe_modules/luci_config) |
| |
| [DEPS](/recipe_modules/luci_config/__init__.py#7): [buildbucket](#recipe_modules-buildbucket), [file](#recipe_modules-file), [proto](#recipe_modules-proto), [step](#recipe_modules-step) |
| |
| |
| #### **class [LuciConfigApi](/recipe_modules/luci_config/api.py#20)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| Module for polling and parsing luci config files via the luci-config API. |
| |
| Depends on `prpc` binary being available in $PATH: |
| https://godoc.org/go.chromium.org/luci/grpc/cmd/prpc |
| |
| — **def [buildbucket](/recipe_modules/luci_config/api.py#163)(self, \*\*kwargs):** |
| |
| — **def [commit\_queue](/recipe_modules/luci_config/api.py#167)(self, config_name: (str | None)=None, \*\*kwargs):** |
| |
| — **def [fetch\_config](/recipe_modules/luci_config/api.py#84)(self, config_name: str, message_type: MessageType, project: (str | None)=None, local_dir: (config_types.Path | None)=None, allow_unknown_fields: bool=False, allow_cache: bool=True):** |
| |
| Fetch and parse config file from the luci-config API as a proto. |
| |
| Since configs are unlikely to change significantly during a build and to |
| simplify test data, results are cached. |
| |
| Args: |
| config_name: The name of the config file to fetch, e.g. |
| "commit-queue.cfg". |
| message_type: The Python type corresponding to the config's protobuf |
| message type. |
| project: The name of the LUCI project to fetch the config from; e.g. |
| "fuchsia". Defaults to the project that the current Buildbucket |
| build is running in. |
| local_dir: If specified, assumed to point to a local directory of files |
| generated by lucicfg. The specified config file will be read from |
| the corresponding local file rather than fetching it from the LUCI |
| Config service. |
| allow_unknown_fields: Whether to allow unknown fields, rather then |
| erroring out on them. This is useful when reading config files for |
| which the corresponding proto file that's been copied into the |
| recipes repo may be out of date. This option should be used with |
| care, as it strips potentially important information. |
| allow_cache: Allow retrieving from a cache if we've already retrieved |
| this config before. |
| |
| — **def [fetch\_config\_raw](/recipe_modules/luci_config/api.py#31)(self, config_name: str, project: (str | None)=None, local_dir: (config_types.Path | None)=None, allow_cache: bool=True):** |
| |
| Fetch and parse config file from the luci-config API as a proto. |
| |
| Since configs are unlikely to change significantly during a build and to |
| simplify test data, results are cached. |
| |
| Args: |
| config_name: The name of the config file to fetch, e.g. |
| "commit-queue.cfg". |
| project: The name of the LUCI project to fetch the config from; e.g., |
| "fuchsia". Defaults to the project that the current Buildbucket |
| build is running in. |
| local_dir: If specified, assumed to point to a local directory of files |
| generated by lucicfg. The specified config file will be read from |
| the corresponding local file rather than fetching it from the LUCI |
| Config service. |
| allow_cache: Allow retrieving from a cache if we've already retrieved |
| this config before. |
| |
| — **def [milo](/recipe_modules/luci_config/api.py#175)(self, \*\*kwargs):** |
| |
| — **def [scheduler](/recipe_modules/luci_config/api.py#178)(self, \*\*kwargs):** |
| ### *recipe_modules* / [milo](/recipe_modules/milo) |
| |
| [DEPS](/recipe_modules/milo/__init__.py#7): [buildbucket](#recipe_modules-buildbucket), [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) |
| |
| |
| API for specifying Milo behavior. |
| |
| #### **class [MiloApi](/recipe_modules/milo/api.py#19)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| A module for interacting with Milo. |
| |
|   **@property**<br>— **def [current\_results\_url](/recipe_modules/milo/api.py#35)(self):** |
| |
| Returns a Milo URL to view the current invocation's results. |
| |
| eg: https://luci-milo.appspot.com/ui/inv/some-inv-name |
| |
|   **@property**<br>— **def [host](/recipe_modules/milo/api.py#25)(self):** |
| |
| Hostname of Milo instance corresponding to the current build. |
| |
| Defaults to the prod instance, but will try to detect when using dev. |
| |
| — **def [show\_blamelist\_for](/recipe_modules/milo/api.py#44)(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) |
| |
| |
| #### **class [NodeJSApi](/recipe_modules/nodejs/api.py#12)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
|   **@contextlib.contextmanager**<br>— **def [\_\_call\_\_](/recipe_modules/nodejs/api.py#17)(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#11): [context](#recipe_modules-context), [warning](#recipe_modules-warning) |
| |
| |
| 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_dir` - 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_dir` - 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_dir` - 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_dir` - 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. |
| |
| #### **class [PathApi](/recipe_modules/path/api.py#330)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CHECKOUT_DIR_DEPRECATED')**<br>— **def [\_\_contains\_\_](/recipe_modules/path/api.py#579)(self, pathname: NamedBasePathsType):** |
| |
| This method is DEPRECATED. |
| |
| If `pathname` is "checkout", returns True iff checkout_dir is set. |
| If you want to check if checkout_dir is set, use |
| `api.path.checkout_dir is not None` or similar, instead. |
| |
| Returns True for all other `pathname` values in NamedBasePaths. |
| Returns False for all other values. |
| |
| In the past, the base paths that this module knew about were extensible via |
| a very complicated 'config' system. All of that has been removed, but this |
| method remains for now. |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CHECKOUT_DIR_DEPRECATED')**<br>— **def [abs\_to\_path](/recipe_modules/path/api.py#517)(self, abs_string_path: str):** |
| |
| Converts an absolute path string `abs_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 |
| * home_dir |
| * start_dir |
| * tmp_base_dir |
| * cleanup_dir |
| |
| 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#734)(self, path: (config_types.Path | str)):** |
| |
| Equivalent to os.abspath. |
| |
| — **def [assert\_absolute](/recipe_modules/path/api.py#455)(self, path: (config_types.Path | str)):** |
| |
| Raises AssertionError if the given path is not an absolute path. |
| |
| Args: |
| * path - The path to check. |
| |
| — **def [basename](/recipe_modules/path/api.py#738)(self, path: (config_types.Path | str)):** |
| |
| Equivalent to os.path.basename. |
| |
|   **@property**<br>— **def [cache\_dir](/recipe_modules/path/api.py#668)(self):** |
| |
| This directory is provided by whatever's running the recipe. |
| |
| When the recipe executes via Buildbucket, directories under here map to |
| 'named caches' which the Build has set. These caches would be preserved |
| locally on the machine executing this recipe, and are restored for |
| subsequent recipe exections on the same machine which request the same named |
| cache. |
| |
| By default, Buildbucket installs a cache named 'builder' which is an |
| immediate subdirectory of cache_dir, and will attempt to be persisted |
| between executions of recipes on the same Buildbucket builder which use the |
| same machine. So, if you are just looking for a place to put files which may |
| be persisted between builds, use: |
| |
| api.path.cache_dir/'builder' |
| |
| As the base Path. |
| |
| Note that directories created under here /may/ be evicted in between runs of |
| the recipe (i.e. to relieve disk pressure). |
| |
| — **def [cast\_to\_path](/recipe_modules/path/api.py#702)(self, strpath: str):** |
| |
| This returns a Path for strpath which can be used anywhere a Path is |
| required. |
| |
| If `strpath` is not an absolute path (e.g. rooted with a valid Windows drive |
| or a '/' for non-Windows paths), this will raise ValueError. |
| |
| This implicitly tries abs_to_path prior to returning a drive-rooted Path. |
| This means that if strpath is a subdirectory of a known path (say, |
| cache_dir), the returned Path will be based on that known path. This is |
| important for test compatibility. |
| |
|   **@checkout_dir.setter**<br>— **def [checkout\_dir](/recipe_modules/path/api.py#608)(self, path: config_types.Path):** |
| |
| Sets the global variable `api.path.checkout_dir` to the given path. |
| |
| |
| |
|   **@property**<br>— **def [cleanup\_dir](/recipe_modules/path/api.py#693)(self):** |
| |
| This directory is guaranteed to be cleaned up (eventually) after the |
| execution of this recipe. |
| |
| This directory is guaranteed to be empty when the recipe starts. |
| |
| — **def [dirname](/recipe_modules/path/api.py#742)(self, path: (config_types.Path | str)):** |
| |
| 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 to take directory name of |
| |
| Returns dirname of path |
| |
| — **def [exists](/recipe_modules/path/api.py#863)(self, path: ((config_types.Path | str) | util.InputPlaceholder)):** |
| |
| 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#837)(self, path: str):** |
| |
| Mostly equivalent to os.path.expanduser. |
| |
| This only handles "~", not "~user". |
| |
| — **def [expandvars](/recipe_modules/path/api.py#850)(self, path: str):** |
| |
| Mostly equivalent to os.path.expandvars, with some limitations. |
| |
| This is limited to variables set in the context module. Also, variables |
| must be of the form '${VARNAME}', not just '$VARNAME'. |
| |
|   **@property**<br>— **def [home\_dir](/recipe_modules/path/api.py#650)(self):** |
| |
| This is the path to the current $HOME directory. |
| |
| It is generally recommended to avoid using this, because it is an indicator |
| that the recipe is non-hermetic. |
| |
| — **def [initialize](/recipe_modules/path/api.py#430)(self):** |
| |
| This is called by the recipe engine immediately after __init__(), but |
| with `self._paths_client` initialized. |
| |
| — **def [isdir](/recipe_modules/path/api.py#876)(self, path: ((config_types.Path | str) | util.InputPlaceholder)):** |
| |
| 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#889)(self, path: ((config_types.Path | str) | util.InputPlaceholder)):** |
| |
| 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#761)(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.joinpath('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#464)(self, prefix: str=tempfile.template):** |
| |
| Makes a new temporary directory, returns Path to it. |
| |
| Args: |
| * prefix - a tempfile template for the directory name (defaults to "tmp"). |
| |
| Returns a Path to the new directory. |
| |
| — **def [mkstemp](/recipe_modules/path/api.py#489)(self, prefix: str=tempfile.template):** |
| |
| Makes a new temporary file, returns Path to it. |
| |
| Args: |
| * prefix - a tempfile template for the file name (defaults to "tmp"). |
| |
| Returns a Path to the new file. |
| |
| *** promo |
| NOTE: Unlike tempfile.mkstemp, the file's file descriptor is closed. If you |
| need the full security properties of mkstemp, please outsource this to e.g. |
| either a resource script of your recipe module or recipe. |
| *** |
| |
| — **def [mock\_add\_directory](/recipe_modules/path/api.py#913)(self, path: config_types.Path):** |
| |
| For testing purposes, mark that file |path| exists. |
| |
| — **def [mock\_add\_file](/recipe_modules/path/api.py#909)(self, path: config_types.Path):** |
| |
| For testing purposes, mark that file |path| exists. |
| |
| — **def [mock\_add\_paths](/recipe_modules/path/api.py#902)(self, path: config_types.Path, kind: FileType=FileType.FILE):** |
| |
| For testing purposes, mark that |path| exists. |
| |
| — **def [mock\_copy\_paths](/recipe_modules/path/api.py#917)(self, source: config_types.Path, dest: config_types.Path):** |
| |
| For testing purposes, copy |source| to |dest|. |
| |
| — **def [mock\_remove\_paths](/recipe_modules/path/api.py#924)(self, path: config_types.Path, should_remove: Callable[([str], bool)]=(lambda p: True)):** |
| |
| For testing purposes, mark that |path| doesn't exist. |
| |
| Args: |
| path: The path to remove. |
| should_remove: Called for every candidate path. Return True to remove this |
| path. |
| |
| — **def [normpath](/recipe_modules/path/api.py#833)(self, path):** |
| |
| Equivalent to os.path.normpath. |
| |
|   **@property**<br>— **def [pardir](/recipe_modules/path/api.py#719)(self):** |
| |
| Equivalent to os.pardir. |
| |
|   **@property**<br>— **def [pathsep](/recipe_modules/path/api.py#729)(self):** |
| |
| Equivalent to os.pathsep. |
| |
| — **def [realpath](/recipe_modules/path/api.py#821)(self, path: (config_types.Path | str)):** |
| |
| Equivalent to os.path.realpath. |
| |
| — **def [relpath](/recipe_modules/path/api.py#825)(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#724)(self):** |
| |
| Equivalent to os.sep. |
| |
| — **def [split](/recipe_modules/path/api.py#776)(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#797)(self, path: (config_types.Path | str)):** |
| |
| 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 to split into name and extension |
| |
| Returns: |
| (name, extension_including_dot). |
| |
|   **@property**<br>— **def [start\_dir](/recipe_modules/path/api.py#639)(self):** |
| |
| This is the directory that the recipe started in. it's similar to `cwd`, |
| except that it's constant for the duration of the entire program. |
| |
| If you want to modify the current working directory for a set of steps, |
| See the 'recipe_engine/context' module which allows modifying the cwd safely |
| via a context manager. |
| |
|   **@property**<br>— **def [tmp\_base\_dir](/recipe_modules/path/api.py#659)(self):** |
| |
| 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'). |
| ### *recipe_modules* / [platform](/recipe_modules/platform) |
| |
| |
| Mockable system platform identity functions. |
| |
| #### **class [PlatformApi](/recipe_modules/platform/api.py#26)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| 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#106)(self):** |
| |
| Returns the current CPU architecture. |
| |
| Can return "arm" or "intel". |
| |
|   **@property**<br>— **def [bits](/recipe_modules/platform/api.py#96)(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#123)(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#36)(self):** |
| |
|   **@property**<br>— **def [is\_linux](/recipe_modules/platform/api.py#82)(self):** |
| |
| Returns True iff the recipe is running on Linux. |
| |
|   **@property**<br>— **def [is\_mac](/recipe_modules/platform/api.py#77)(self):** |
| |
| Returns True iff the recipe is running on OS X. |
| |
|   **@property**<br>— **def [is\_win](/recipe_modules/platform/api.py#72)(self):** |
| |
| Returns True iff the recipe is running on Windows. |
| |
|   **@property**<br>— **def [name](/recipe_modules/platform/api.py#87)(self):** |
| |
| Returns the current platform name which will be in: |
| * win |
| * mac |
| * linux |
| |
|   **@staticmethod**<br>— **def [normalize\_platform\_name](/recipe_modules/platform/api.py#129)(plat: str):** |
| |
| One of python's sys.platform values -> 'win', 'linux' or 'mac'. |
| |
|   **@property**<br>— **def [total\_memory](/recipe_modules/platform/api.py#114)(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) |
| |
| [DEPS](/recipe_modules/properties/__init__.py#7): [warning](#recipe_modules-warning) |
| |
| |
| 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#29)([RecipeApi](/recipe_engine/recipe_api.py#439), collections.abc.Mapping):** |
| |
| PropertiesApi implements all the standard Mapping functions, so you |
| can use it like a read-only dict. |
| |
| — **def [thaw](/recipe_modules/properties/api.py#55)(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) |
| |
| |
| Methods for producing and consuming protobuf data to/from steps and the |
| filesystem. |
| |
| #### **class [ProtoApi](/recipe_modules/proto/api.py#92)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
|   **@staticmethod**<br>— **def [decode](/recipe_modules/proto/api.py#179)(data, msg_class, codec: Codec, \*\*decoding_kwargs):** |
| |
| Decodes a proto message from a string. |
| |
| Args: |
| * msg_class (protobuf Message subclass) - The message type to decode. |
| * codec - 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#164)(proto_msg, codec: Codec, \*\*encoding_kwargs):** |
| |
| Encodes a proto message to a string. |
| |
| Args: |
| * codec - 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#163)**<br>— **def [input](/recipe_modules/proto/api.py#98)(self, proto_msg, codec: 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 - 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#163)**<br>— **def [output](/recipe_modules/proto/api.py#129)(self, msg_class, codec: 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 - 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* / [random](/recipe_modules/random) |
| |
| |
| 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#32)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [\_\_getattr\_\_](/recipe_modules/random/api.py#44)(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) |
| |
| |
| Provides objects for reading and writing raw data to and from steps. |
| |
| #### **class [RawIOApi](/recipe_modules/raw_io/api.py#307)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
|   **@[returns\_placeholder](/recipe_engine/util.py#163)**<br>  **@staticmethod**<br>— **def [input](/recipe_modules/raw_io/api.py#308)(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#163)**<br>  **@staticmethod**<br>— **def [input\_text](/recipe_modules/raw_io/api.py#335)(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#163)**<br>  **@staticmethod**<br>— **def [output](/recipe_modules/raw_io/api.py#358)(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#163)**<br>— **def [output\_dir](/recipe_modules/raw_io/api.py#396)(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#163)**<br>  **@staticmethod**<br>— **def [output\_text](/recipe_modules/raw_io/api.py#378)(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) |
| |
| |
| 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#30)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| A module for interacting with ResultDB. |
| |
| — **def [assert\_enabled](/recipe_modules/resultdb/api.py#52)(self):** |
| |
| — **def [config\_test\_presentation](/recipe_modules/resultdb/api.py#875)(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#44)(self):** |
| |
|   **@property**<br>— **def [enabled](/recipe_modules/resultdb/api.py#48)(self):** |
| |
| — **def [exclude\_invocations](/recipe_modules/resultdb/api.py#63)(self, invocations, step_name=None):** |
| |
| Shortcut for resultdb.update_included_invocations(). |
| |
| — **def [exonerate](/recipe_modules/resultdb/api.py#154)(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#104)(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\_invocation\_instructions](/recipe_modules/resultdb/api.py#129)(self, inv_name=None, step_name=None):** |
| |
| Returns instructions from 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: |
| instruction_pb2.Instructions of the invocation requested. |
| |
| — **def [include\_invocations](/recipe_modules/resultdb/api.py#58)(self, invocations, step_name=None):** |
| |
| Shortcut for resultdb.update_included_invocations(). |
| |
| — **def [invocation\_ids](/recipe_modules/resultdb/api.py#196)(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#211)(self, inv_ids, variants_with_unexpected_results=False, merge=False, limit=None, step_name=None, tr_fields=None, test_invocations=None, test_regex=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. |
| test_invocations (dict {invocation_id: api.Invocation}): Default test data |
| to be used to simulate the step in tests. The format is the same as |
| what this method returns. |
| test_regex (str): A regular expression of the relevant test variants |
| to query for. |
| |
| Returns: |
| A dict {invocation_id: api.Invocation}. |
| |
| — **def [query\_new\_test\_variants](/recipe_modules/resultdb/api.py#503)(self, invocation: str, baseline: str, step_name: str=None, step_test_data: dict=None):** |
| |
| Query ResultDB for new tests. |
| |
| Makes a QueryNewTestVariants rpc. |
| |
| Args: |
| inovcation: Name of the invocation, e.g. "invocations/{id}". |
| baseline: The baseline to compare test variants against, to determine if |
| they are new. e.g. “projects/{project}/baselines/{baseline_id}”. |
| |
| Returns: |
| A QueryNewTestVariantsResponse proto message with is_baseline_ready and |
| new_test_variants. |
| |
| — **def [query\_test\_result\_statistics](/recipe_modules/resultdb/api.py#291)(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 [query\_test\_results](/recipe_modules/resultdb/api.py#378)(self, invocations, test_id_regexp=None, variant_predicate=None, field_mask_paths=None, page_size=100, page_token=None, step_name=None):** |
| |
| Retrieve test results from an invocation, recursively. |
| |
| Makes a call to QueryTestResults rpc. Returns a list of test results for the |
| invocations and matching the given filters. |
| |
| Args: |
| invocations (list of str): retrieve the test results included in these |
| invocations. |
| test_id_regexp (str): the subset of test IDs to request history for. |
| Default to None. |
| variant_predicate (resultdb.proto.v1.predicate.VariantPredicate): |
| the subset of test variants to request history for. Defaults to None, |
| but specifying will improve runtime. |
| field_mask_paths (list of str): test result fields in the response. |
| Test result name will always be included regardless of this param value. |
| page_size (int): the maximum number of variants to return. The service may |
| return fewer than this value. The maximum value is 1000; values above |
| 1000 will be coerced to 1000. Defaults to 100. |
| 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 QueryTestResultsResponse proto message with test_results and |
| next_page_token. |
| |
| For value format, see [`QueryTestResultsResponse` message] |
| (https://bit.ly/3dsChbo) |
| |
| — **def [query\_test\_variants](/recipe_modules/resultdb/api.py#440)(self, invocations, test_variant_status=None, field_mask_paths=None, page_size=100, page_token=None, step_name=None):** |
| |
| Retrieve test variants from an invocation, recursively. |
| |
| Makes a call to QueryTestVariants rpc. Returns a list of test variants for |
| the invocations and matching the given filters. |
| |
| Args: |
| invocations (list of str): retrieve the test results included in these |
| invocations. |
| test_variant_status (resultdb.proto.v1.test_variant.TestVariantStatus): |
| Use the UNEXPECTED_MASK status to retrieve only variants with |
| non-EXPECTED status. |
| field_mask_paths (list of str): test variant fields in the response. |
| Test id, variantHash and status will always be included. Example: |
| use ["test_id", "variant", "status", "sources_id"] to exclude results |
| from the response. (Note that test_id and status are still specified for |
| clarity.) |
| page_size (int): the maximum number of variants to return. The service may |
| return fewer than this value. The maximum value is 1000; values above |
| 1000 will be coerced to 1000. Defaults to 100. |
| 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 QueryTestVariantsResponse proto message with test_results and |
| next_page_token. |
| |
| For value format, see [`QueryTestVariantsResponse` message] |
| (http://shortn/_hv3edsXidO) |
| |
| — **def [unwrap](/recipe_modules/resultdb/api.py#861)(self, cmd: list[str]):** |
| |
| Reverses the wrap command |
| |
| If the command is wrapped with the rdb command and delimiter this will |
| return the unwrapped command. |
| |
| Args: |
| cmd (list of strings): the command line to attempt to unwrap |
| |
| — **def [update\_included\_invocations](/recipe_modules/resultdb/api.py#68)(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 IDs to add to the current |
| invocation. |
| remove_invocations (list of str): invocation IDs to remove from the |
| current invocation. |
| |
| This updates the inclusions of the current invocation specified in the |
| LUCI_CONTEXT. |
| |
| — **def [update\_invocation](/recipe_modules/resultdb/api.py#541)(self, parent_inv='', step_name=None, source_spec=None, is_source_spec_final=None, baseline_id=None, instructions=None, raise_on_failure=True):** |
| |
| Makes a call to the UpdateInvocation API to update the invocation |
| |
| Args: |
| parent_inv (str): the name of the invocation to be updated. |
| step_name (str): name of the step. |
| source_spec (luci.resultdb.v1.SourceSpec): The source information |
| to apply to the given invocation. |
| is_source_spec_final (bool): Whether the source spec is final and won't |
| be changed again. |
| baseline_id (str): Baseline identifier for this invocation, usually of |
| the format {buildbucket bucket}:{buildbucket builder name}. For example, |
| 'try:linux-rel'. Baselines are used to detect new tests in invocations. |
| instructions (luci.resultdb.v1.Instructions): The reproduction |
| instructions for this invocation. It may contain step instructions and |
| test result instructions. The test instructions may contain instructions |
| for test results in this invocation and in included invocations. |
| raise_on_failure (bool): If set, and `status` is not SUCCESS, raise |
| the appropriate exception. |
| |
| — **def [upload\_invocation\_artifacts](/recipe_modules/resultdb/api.py#324)(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#664)(self, cmd, module_name='', module_scheme='', 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, inv_properties='', inv_properties_file='', inherit_sources=False, sources='', sources_file='', baseline_id='', inv_extended_properties_dir='', previous_test_id_prefix=None, test_id_prefix='', shorten_ids=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. |
| module_name(str): Module name to upload results to. Requires command to |
| supply structured test IDs to ResultSink's ReportTestResults RPC. |
| Do not set in conjunction with test_id_prefix. |
| module_scheme(str): Module scheme to upload results to. |
| See go/resultdb-schemes. Must be set whenever module_name is set. |
| 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. |
| inv_properties(str): stringified JSON object that contains structured, |
| domain-specific properties of the invocation. When not specified, |
| invocation-level properties will not be updated. |
| inv_properties_file(string): Similar to inv_properties but takes a path |
| to the file that contains the JSON object. Cannot be used when |
| inv_properties is specified. |
| inherit_sources(bool): flag to enable inheriting sources from the parent |
| invocation. |
| sources(string): JSON-serialized luci.resultdb.v1.Sources object that |
| contains information about the code sources tested by the invocation. |
| Cannot be used when inherit_sources or sources_file is specified. |
| sources_file(string): Similar to sources, but takes a path to the |
| file that contains the JSON object. Cannot be used when |
| inherit_sources or sources is specified. |
| baseline_id(string): Baseline identifier for this invocation, usually of |
| the format {buildbucket bucket}:{buildbucket builder name}. |
| For example, 'try:linux-rel'. |
| inv_extended_properties_dir(str): Path to a directory that contains files |
| for the invocation's extended_properties in JSON format. |
| Only files directly under this dir with the extension ".jsonpb" will be |
| read. The filename after removing ".jsonpb" and the file content will be |
| added as a key-value pair to the invocation's extended_properties map. |
| test_id_prefix (str): Deprecated. A prefix to prepend to test IDs of test |
| results reported by cmd. Requires command to supply legacy test IDs to |
| ResultSink's ReportTestResults RPC. |
| previous_test_id_prefix(str): Sets the test ID prefix that was previously |
| used for these tests (i.e. test_id_prefix). This prefix will be combined |
| with the legacy test ID reported to ResultSink's ReportTestResults RPC |
| to populate test_metadata.previous_test_id. Note that empty string ('') |
| is a valid prior prefix and can be set for this option. |
| shorten_ids(bool): flag to enable shortening of test IDs. When set, the |
| uploaded test_id/test_id_structured will be limited to 350 bytes. |
| Set this flag cautiously as processes may depend on the test ID matching |
| the harness-reported value (e.g. for re-run instructions) and shortening |
| will break this. |
| ### *recipe_modules* / [runtime](/recipe_modules/runtime) |
| |
| |
| #### **class [RuntimeApi](/recipe_modules/runtime/api.py#12)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| 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#35)(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 received |
| 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 |
| received 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#22)(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#16): [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) |
| |
| |
| 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#29)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| A module for interacting with LUCI Scheduler service. |
| |
| — **def [emit\_trigger](/recipe_modules/scheduler/api.py#216)(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#228)(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#49)(self):** |
| |
| Returns the backend hostname used by this module. |
| |
|   **@property**<br>— **def [invocation\_id](/recipe_modules/scheduler/api.py#70)(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#62)(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#54)(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#41)(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) |
| |
| |
| 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#18)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [default](/recipe_modules/service_account/api.py#74)(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#83)(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#11): [context](#recipe_modules-context), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [proto](#recipe_modules-proto), [warning](#recipe_modules-warning) |
| |
| |
| Step is the primary API for running steps (external programs, etc.) |
| |
| #### **class [StepApi](/recipe_modules/step/api.py#32)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
|   **@property**<br>— **def [InfraFailure](/recipe_modules/step/api.py#151)(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#123)(self):** |
| |
| Returns the maximum number of millicores this system has. |
| |
|   **@property**<br>— **def [MAX\_MEMORY](/recipe_modules/step/api.py#128)(self):** |
| |
| Returns the maximum amount of memory on the system in MB. |
| |
| — **def [ResourceCost](/recipe_modules/step/api.py#56)(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#133)(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#145)(self):** |
| |
| StepWarning is a subclass of StepFailure, and will translate to a yellow |
| build. |
| |
| — **def [\_\_call\_\_](/recipe_modules/step/api.py#632)(self, name: str, cmd: (list[(((int | str) | Placeholder) | Path)] | None), ok_ret: ((Sequence[int] | Literal['any']) | Literal['all'])=(0,), infra_step: bool=False, raise_on_failure: bool=True, wrapper: Sequence[(((int | str) | Placeholder) | Path)]=(), timeout: ((int | timedelta) | None)=None, stdout: (Placeholder | None)=None, stderr: (Placeholder | None)=None, stdin: (Placeholder | None)=None, step_test_data: (Callable[([], StepTestData)] | None)=None, cost: _ResourceCost=_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 (and always has a retcode of 0). See the |
| `empty()` method on this module for a more useful version of this mode. |
| |
| Otherwise: |
| * 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#161)(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#194)(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. |
| |
| — **def [empty](/recipe_modules/step/api.py#304)(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. |
| |
| — **def [funcall](/recipe_modules/step/api.py#747)(self, name, func, \*args, \*\*kwargs):** |
| |
| Call a function and store the results and exception in a step. |
| |
| Sample usage: |
| |
| >>> api.step.funcall(None, some_function, 4, json=True) |
| |
|   **@contextlib.contextmanager**<br>— **def [nest](/recipe_modules/step/api.py#204)(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, EXCEPTION, or CANCELED |
| (depending on the type of exception and whether it resulted from the |
| child step being canceled). |
| 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: |
| |
| with api.step.nest('run shards'): # status='worst' is the default. |
| with api.defer.context() as defer: |
| for shard in shards: |
| defer(run_shard, shard) |
| |
| # status='last' |
| with api.step.nest('do upload', status='last'): |
| for attempt in range(num_attempts): |
| try: |
| do_upload() # first one fails, but second succeeds. |
| except api.step.StepFailure: |
| if range >= num_attempts - 1: |
| raise |
| pass |
| |
| # manually adjust status |
| with api.step.nest('custom thing') as presentation: |
| # stuff! |
| presentation.status = 'FAILURE' # or whatever |
| |
| 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#456)(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 |
| |
| — **def [sub\_build](/recipe_modules/step/api.py#495)(self, name: str, cmd: (((int | str) | Placeholder) | Path), build: build_pb2.Build, raise_on_failure: bool=True, output_path: ((str | Path) | None)=None, legacy_global_namespace=False, merge_output_properties_to: (None | list[str])=None, 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 / 'subdir', |
| # Change the cache_dir of the launched LUCI executable. Defaults to |
| # api.path.cache_dir if unchanged. |
| luciexe=sections_pb2.LUCIExe(cache_dir=api.path.cache_dir / '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_dir / '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. |
| * merge_output_properties_to: If set, will cause the sub-build's output |
| properties to be merged into THIS build's output properties at the given |
| path. The special token RootOutputProperties on StepApi means to merge |
| the sub-build's properties to the root of this build's output. Otherwise |
| this should be a key path through the output properties' JSON objects. |
| For example if this was ["a", "b"], and the sub build emitted {"hello": |
| 100}, then this build would show {"a": {"b": {"hello": 100}}}. |
| * 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) |
| |
| |
| #### **class [SwarmingApi](/recipe_modules/swarming/api.py#1247)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| 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#1266)(self):** |
| |
| Swarming bot ID executing this task. |
| |
| — **def [collect](/recipe_modules/swarming/api.py#1409)(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 task IDs or metadata |
| objects corresponding to tasks to wait for. |
| 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|Path|Iterable(str|Path)): Where to output each |
| task's text output. If given an iterable, will output it into multiple |
| locations. Supported values are 'none', 'json', 'console' or a Path. At |
| most one output Path is allowed. Accepts 'all' as a legacy alias for |
| ['json', 'console']. |
| 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#1276)(self):** |
| |
| Swarming server executing this task. |
| |
| — **def [ensure\_client](/recipe_modules/swarming/api.py#1303)(self):** |
| |
| — **def [initialize](/recipe_modules/swarming/api.py#1281)(self):** |
| |
| — **def [list\_bots](/recipe_modules/swarming/api.py#1552)(self, step_name, dimensions=None, fields=None):** |
| |
| List bots matching the given options. |
| |
| Args: |
| step_name (str): The name of the step. |
| dimensions (None|Dict[str, str]): Select bots that match the given |
| dimensions. |
| fields (None|List[str]): Fields to include in the response. If not |
| specified, all fields will be included. |
| |
| Returns: |
| A list of BotMetadata objects. |
| |
| — **def [list\_tasks](/recipe_modules/swarming/api.py#1602)(self, step_name, start=None, tags=None, server=None):** |
| |
| List tasks matching the given options. |
| |
| Args: |
| step_name (str): The name of the step. |
| start (None|float): Number of seconds since epoch. |
| tags (None|List[str]): Select tasks that contain the given |
| tags. |
| server (string): Address of the server to query, e.g. |
| https://chromium-swarm.appspot.com. If not set, the server the current |
| task is running on is used. |
| |
| Returns: |
| Json listing the resulting tasks. |
| |
|   **@contextlib.contextmanager**<br>— **def [on\_path](/recipe_modules/swarming/api.py#1319)(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#1515)(self, name, task):** |
| |
| Retrieve 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 retrieved. |
| |
| Returns: |
| TaskRequest objects. |
| |
|   **@property**<br>— **def [task\_id](/recipe_modules/swarming/api.py#1271)(self):** |
| |
| This task's Swarming ID. |
| |
| — **def [task\_request](/recipe_modules/swarming/api.py#1333)(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#1344)(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#1352)(self, step_name, requests, verbose=False, server=None):** |
| |
| 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. |
| server (string): Address of the server to trigger the task on, e.g. |
| https://chromium-swarm.appspot.com. If not set, the server the current |
| task is running on is used. |
| |
| Returns: |
| A list of TaskRequestMetadata objects. |
| ### *recipe_modules* / [time](/recipe_modules/time) |
| |
| [DEPS](/recipe_modules/time/__init__.py#7): [context](#recipe_modules-context), [random](#recipe_modules-random), [step](#recipe_modules-step) |
| |
| |
| Allows mockable access to the current time. |
| |
| #### **class [TimeApi](/recipe_modules/time/api.py#111)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [exponential\_retry](/recipe_modules/time/api.py#147)(self, retries: int, delay: datetime.timedelta, condition: Callable[([Exception], bool)]=None, raise_on_failure: bool=True):** |
| |
| Adds exponential retry to a function. |
| |
| Decorator which retries the function with exponential backoff. |
| |
| Each time the decorated function throws an exception, we sleep for some |
| amount of time. We increase the amount of time exponentially to prevent |
| cascading failures from overwhelming systems. We also add a jitter to avoid |
| the thundering herd problem. |
| |
| Example usage: |
| |
| ``` |
| def RunSteps(api): |
| @api.time.exponential_retry(5, datetime.timedelta(seconds=1)) |
| def test_retries(): |
| api.step('running', None) |
| raise Exception() |
| |
| test_retries() |
| # Executes 6 steps with 'running' as a common prefix of their step names. |
| ``` |
| |
| When writing a recipe module whose method needs to be retried, you won't |
| have access to the time module in the class body, but you can import a |
| class-method decorator like: |
| |
| from RECIPE_MODULES.recipe_engine.time.api import exponential_retry |
| |
| This decorator can be used on class methods or on functions |
| (for example, functions in a recipe file). |
| |
| *** promo |
| NOTE: Your module/recipe MUST ALSO depend on |
| "recipe_engine/time" in its DEPS. |
| *** |
| |
| *** promo |
| NOTE: For non-class-method functions, the first parameter to those functions |
| must be an api object, such as the passed to RunSteps. |
| *** |
| |
| Example usage 1 (class method decorator): |
| |
| ``` |
| from recipe_engine.recipe_api import RecipeApi |
| from RECIPE_MODULES.recipe_engine.time.api import exponential_retry |
| |
| # NOTE: Don't forget to put "recipe_engine/time" in the module DEPS. |
| |
| class MyRecipeModule(RecipeApi): |
| @exponential_retry(5, datetime.timedelta(seconds=1)) |
| def my_retriable_function(self, ...): |
| self.m.step('running', None) |
| ``` |
| |
| Example usage 2 (function with api as first arg): |
| |
| ``` |
| from RECIPE_MODULES.recipe_engine.time.api import exponential_retry |
| |
| # NOTE: Don't forget to put "recipe_engine/time" in DEPS. |
| |
| @exponential_retry(5, datetime.timedelta(seconds=1)) |
| def helper_function(api): |
| api.step('running', None) |
| |
| def RunSteps(api): |
| helper_funciton(api) |
| ``` |
| |
| — **def [ms\_since\_epoch](/recipe_modules/time/api.py#230)(self):** |
| |
| Returns current timestamp as an int number of milliseconds since epoch. |
| |
| |
| — **def [sleep](/recipe_modules/time/api.py#120)(self, secs: (float | int), with_step: (bool | None)=None, step_result: (step_data.StepData | None)=None):** |
| |
| Suspend execution of |secs| (float) seconds, waiting for GLOBAL_SHUTDOWN. |
| Does nothing in testing. |
| |
| Args: |
| * secs - The number of seconds to sleep. |
| * with_step - If True, emits a step to indicate to users that the recipe is |
| sleeping (not just hanging). If None, then will default to True if |
| sleeping for a long time (>60sec); this can be disabled by setting |
| explicitly to None. If the GLOBAL_SHUTDOWN event has already occurred, |
| then a step will always be emitted in order to force raising an |
| exception. |
| * step_result - Result of running a step. Should be None if with_step is |
| True or None. |
| |
| — **def [time](/recipe_modules/time/api.py#222)(self):** |
| |
| Returns current timestamp as a float number of seconds since epoch. |
| |
| — **def [timeout](/recipe_modules/time/api.py#253)(self, seconds: ((float | int) | datetime.timedelta)=None):** |
| |
| Provides a context that times out after the given time. |
| |
| Usage: |
| with api.time.timeout(datetime.timedelta(minutes=5)): |
| # your steps |
| |
| Look at the "deadline" section of https://chromium.googlesource.com/infra/luci/luci-py/+/HEAD/client/LUCI_CONTEXT.md |
| to see how this works. |
| |
| If the new deadline would be later than the old deadline (if any), the |
| deadline will not be updated, making this a no-op. For example, if |
| `api.time.timeout(timedelta(minutes=10))` is used in a builder that has a |
| 5-minute execution timeout, it will not have any effect. |
| |
| — **def [utcnow](/recipe_modules/time/api.py#235)(self):** |
| |
| Returns current UTC time as a datetime.datetime. |
| ### *recipe_modules* / [tricium](/recipe_modules/tricium) |
| |
| [DEPS](/recipe_modules/tricium/__init__.py#7): [buildbucket](#recipe_modules-buildbucket), [cipd](#recipe_modules-cipd), [context](#recipe_modules-context), [file](#recipe_modules-file), [findings](#recipe_modules-findings), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [proto](#recipe_modules-proto), [resultdb](#recipe_modules-resultdb), [step](#recipe_modules-step) |
| |
| |
| 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#30)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| TriciumApi provides basic support for Tricium. |
| |
| — **def [\_\_init\_\_](/recipe_modules/tricium/api.py#42)(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#52)(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 [is\_binary](/recipe_modules/tricium/api.py#281)(self, path):** |
| |
| — **def [run\_legacy](/recipe_modules/tricium/api.py#207)(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#133)(comment):** |
| |
| Validates comment to comply with Tricium/Gerrit requirements. |
| |
| Raise ValueError on the first detected problem. |
| |
| — **def [write\_comments](/recipe_modules/tricium/api.py#180)(self, upload_findings=True):** |
| |
| 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) |
| |
| |
| Methods for interacting with HTTP(s) URLs. |
| |
| #### **class [UrlApi](/recipe_modules/url/api.py#17)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [get\_file](/recipe_modules/url/api.py#133)(self, url, path, step_name=None, headers=None, transient_retry=True, strip_prefix=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). |
| |
| 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#241)(self, url, step_name=None, headers=None, transient_retry=True, strip_prefix=None, log=False, 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. |
| * 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\_raw](/recipe_modules/url/api.py#206)(self, url, step_name=None, headers=None, transient_retry=True, 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. |
| * 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 [get\_text](/recipe_modules/url/api.py#172)(self, url, step_name=None, headers=None, transient_retry=True, 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. |
| * 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#96)(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#112)(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) |
| |
| |
| Allows test-repeatable access to a random UUID. |
| |
| #### **class [UuidApi](/recipe_modules/uuid/api.py#13)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [random](/recipe_modules/uuid/api.py#22)(self):** |
| |
| Returns a random UUID string. |
| ### *recipe_modules* / [version](/recipe_modules/version) |
| |
| |
| Thin API for parsing semver strings into comparable object. |
| |
| #### **class [VersionApi](/recipe_modules/version/api.py#15)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
|   **@staticmethod**<br>— **def [parse](/recipe_modules/version/api.py#17)(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 |
| (for strict parsing) and https://github.com/di/packaging_legacy (for the fallback |
| behavior). |
| ### *recipe_modules* / [warning](/recipe_modules/warning) |
| |
| |
| Allows recipe modules to issue warnings in simulation test. |
| |
| #### **class [WarningApi](/recipe_modules/warning/api.py#12)([RecipeApi](/recipe_engine/recipe_api.py#439)):** |
| |
| — **def [issue](/recipe_modules/warning/api.py#13)(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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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), [cipd](#recipe_modules-cipd), [path](#recipe_modules-path) |
| |
| |
| — **def [RunSteps](/recipe_modules/bcid_reporter/examples/usage.py#13)(api):** |
| ### *recipes* / [bcid\_reporter:tests/retry](/recipe_modules/bcid_reporter/tests/retry.py) |
| |
| [DEPS](/recipe_modules/bcid_reporter/tests/retry.py#7): [bcid\_reporter](#recipe_modules-bcid_reporter), [path](#recipe_modules-path), [raw\_io](#recipe_modules-raw_io) |
| |
| |
| — **def [RunSteps](/recipe_modules/bcid_reporter/tests/retry.py#13)(api):** |
| ### *recipes* / [bcid\_verifier:tests/test-verify](/recipe_modules/bcid_verifier/tests/test-verify.py) |
| |
| [DEPS](/recipe_modules/bcid_verifier/tests/test-verify.py#9): [assertions](#recipe_modules-assertions), [bcid\_verifier](#recipe_modules-bcid_verifier), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/bcid_verifier/tests/test-verify.py#17)(api):** |
| ### *recipes* / [buildbucket:examples/full](/recipe_modules/buildbucket/examples/full.py) |
| |
| [DEPS](/recipe_modules/buildbucket/examples/full.py#17): [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) |
| |
| |
| This file is a recipe demonstrating the buildbucket recipe module. |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/examples/full.py#28)(api):** |
| ### *recipes* / [buildbucket:tests/add\_build\_tags](/recipe_modules/buildbucket/tests/add_build_tags.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/add_build_tags.py#7): [buildbucket](#recipe_modules-buildbucket), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/add_build_tags.py#13)(api):** |
| ### *recipes* / [buildbucket:tests/add\_step\_tags](/recipe_modules/buildbucket/tests/add_step_tags.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/add_step_tags.py#7): [buildbucket](#recipe_modules-buildbucket), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/add_step_tags.py#13)(api):** |
| ### *recipes* / [buildbucket:tests/backend](/recipe_modules/buildbucket/tests/backend.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/backend.py#13): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/backend.py#16)(api):** |
| ### *recipes* / [buildbucket:tests/backend\_utilities\_fail](/recipe_modules/buildbucket/tests/backend_utilities_fail.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/backend_utilities_fail.py#15): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/backend_utilities_fail.py#21)(api):** |
| ### *recipes* / [buildbucket:tests/build](/recipe_modules/buildbucket/tests/build.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/build.py#19): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/build.py#27)(api):** |
| ### *recipes* / [buildbucket:tests/cancel](/recipe_modules/buildbucket/tests/cancel.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/cancel.py#12): [buildbucket](#recipe_modules-buildbucket) |
| |
| |
| — **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#9): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/collect.py#16)(api):** |
| ### *recipes* / [buildbucket:tests/get](/recipe_modules/buildbucket/tests/get.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/get.py#11): [buildbucket](#recipe_modules-buildbucket) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/get.py#18)(api):** |
| ### *recipes* / [buildbucket:tests/list\_builders](/recipe_modules/buildbucket/tests/list_builders.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/list_builders.py#12): [buildbucket](#recipe_modules-buildbucket) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/list_builders.py#16)(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) |
| |
| |
| 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#17): [buildbucket](#recipe_modules-buildbucket), [json](#recipe_modules-json), [properties](#recipe_modules-properties), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/schedule.py#26)(api):** |
| ### *recipes* / [buildbucket:tests/search](/recipe_modules/buildbucket/tests/search.py) |
| |
| [DEPS](/recipe_modules/buildbucket/tests/search.py#18): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/buildbucket/tests/search.py#38)(api, props):** |
| ### *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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/cas_input/examples/full.py#18)(api):** |
| ### *recipes* / [change\_verifier:tests/match\_config](/recipe_modules/change_verifier/tests/match_config.py) |
| |
| [DEPS](/recipe_modules/change_verifier/tests/match_config.py#9): [buildbucket](#recipe_modules-buildbucket), [change\_verifier](#recipe_modules-change_verifier), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/change_verifier/tests/match_config.py#16)(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) |
| |
| |
| — **def [RunSteps](/recipe_modules/change_verifier/tests/search.py#16)(api):** |
| |
| — **def [make\_runs](/recipe_modules/change_verifier/tests/search.py#39)(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#16): [buildbucket](#recipe_modules-buildbucket), [cipd](#recipe_modules-cipd), [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cipd/examples/full.py#49)(api, props: full_pb.InputProperties):** |
| ### *recipes* / [cipd:tests/platform](/recipe_modules/cipd/tests/platform.py) |
| |
| [DEPS](/recipe_modules/cipd/tests/platform.py#11): [cipd](#recipe_modules-cipd), [platform](#recipe_modules-platform), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cipd/tests/platform.py#18)(api):** |
| ### *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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **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) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **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) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/cq/tests/cl_group_key.py#18)(api):** |
| ### *recipes* / [cq:tests/do\_not\_retry](/recipe_modules/cq/tests/do_not_retry.py) |
| |
| [DEPS](/recipe_modules/cq/tests/do_not_retry.py#9): [buildbucket](#recipe_modules-buildbucket), [cq](#recipe_modules-cq), [step](#recipe_modules-step) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/cq/tests/do_not_retry.py#19)(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) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **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) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **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#9): [cq](#recipe_modules-cq), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/cq/tests/mode_of_run.py#16)(api):** |
| ### *recipes* / [cq:tests/owner\_is\_googler](/recipe_modules/cq/tests/owner_is_googler.py) |
| |
| [DEPS](/recipe_modules/cq/tests/owner_is_googler.py#9): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [cq](#recipe_modules-cq), [properties](#recipe_modules-properties) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/cq/tests/owner_is_googler.py#17)(api):** |
| ### *recipes* / [cq:tests/reuse](/recipe_modules/cq/tests/reuse.py) |
| |
| [DEPS](/recipe_modules/cq/tests/reuse.py#9): [assertions](#recipe_modules-assertions), [cq](#recipe_modules-cq), [step](#recipe_modules-step) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/cq/tests/reuse.py#16)(api):** |
| ### *recipes* / [cq:tests/triggered\_build\_ids](/recipe_modules/cq/tests/triggered_build_ids.py) |
| |
| [DEPS](/recipe_modules/cq/tests/triggered_build_ids.py#10): [buildbucket](#recipe_modules-buildbucket), [cq](#recipe_modules-cq), [step](#recipe_modules-step) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CQ_MODULE_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/cq/tests/triggered_build_ids.py#17)(api):** |
| ### *recipes* / [cv:examples/ordered\_cls](/recipe_modules/cv/examples/ordered_cls.py) |
| |
| [DEPS](/recipe_modules/cv/examples/ordered_cls.py#12): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [cv](#recipe_modules-cv), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/examples/ordered_cls.py#21)(api):** |
| ### *recipes* / [cv:examples/trigger\_child\_builds](/recipe_modules/cv/examples/trigger_child_builds.py) |
| |
| [DEPS](/recipe_modules/cv/examples/trigger_child_builds.py#11): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [cv](#recipe_modules-cv), [json](#recipe_modules-json), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/examples/trigger_child_builds.py#21)(api):** |
| ### *recipes* / [cv:tests/attempt\_key](/recipe_modules/cv/tests/attempt_key.py) |
| |
| [DEPS](/recipe_modules/cv/tests/attempt_key.py#9): [buildbucket](#recipe_modules-buildbucket), [cv](#recipe_modules-cv) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/attempt_key.py#15)(api):** |
| ### *recipes* / [cv:tests/cl\_group\_key](/recipe_modules/cv/tests/cl_group_key.py) |
| |
| [DEPS](/recipe_modules/cv/tests/cl_group_key.py#9): [buildbucket](#recipe_modules-buildbucket), [cv](#recipe_modules-cv) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/cl_group_key.py#17)(api):** |
| ### *recipes* / [cv:tests/cl\_owner](/recipe_modules/cv/tests/cl_owner.py) |
| |
| [DEPS](/recipe_modules/cv/tests/cl_owner.py#9): [buildbucket](#recipe_modules-buildbucket), [cv](#recipe_modules-cv) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/cl_owner.py#17)(api):** |
| ### *recipes* / [cv:tests/do\_not\_retry](/recipe_modules/cv/tests/do_not_retry.py) |
| |
| [DEPS](/recipe_modules/cv/tests/do_not_retry.py#7): [buildbucket](#recipe_modules-buildbucket), [cv](#recipe_modules-cv), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/do_not_retry.py#16)(api):** |
| ### *recipes* / [cv:tests/experimental](/recipe_modules/cv/tests/experimental.py) |
| |
| [DEPS](/recipe_modules/cv/tests/experimental.py#9): [assertions](#recipe_modules-assertions), [cv](#recipe_modules-cv), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/experimental.py#17)(api):** |
| ### *recipes* / [cv:tests/inactive](/recipe_modules/cv/tests/inactive.py) |
| |
| [DEPS](/recipe_modules/cv/tests/inactive.py#9): [assertions](#recipe_modules-assertions), [cv](#recipe_modules-cv), [properties](#recipe_modules-properties) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/inactive.py#16)(api):** |
| ### *recipes* / [cv:tests/mode\_of\_run](/recipe_modules/cv/tests/mode_of_run.py) |
| |
| [DEPS](/recipe_modules/cv/tests/mode_of_run.py#7): [cv](#recipe_modules-cv), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/mode_of_run.py#14)(api):** |
| ### *recipes* / [cv:tests/owner\_is\_googler](/recipe_modules/cv/tests/owner_is_googler.py) |
| |
| [DEPS](/recipe_modules/cv/tests/owner_is_googler.py#9): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [cv](#recipe_modules-cv), [properties](#recipe_modules-properties) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/owner_is_googler.py#17)(api):** |
| ### *recipes* / [cv:tests/reuse](/recipe_modules/cv/tests/reuse.py) |
| |
| [DEPS](/recipe_modules/cv/tests/reuse.py#7): [assertions](#recipe_modules-assertions), [cv](#recipe_modules-cv), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/reuse.py#14)(api):** |
| ### *recipes* / [cv:tests/triggered\_build\_ids](/recipe_modules/cv/tests/triggered_build_ids.py) |
| |
| [DEPS](/recipe_modules/cv/tests/triggered_build_ids.py#7): [buildbucket](#recipe_modules-buildbucket), [cv](#recipe_modules-cv), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/cv/tests/triggered_build_ids.py#16)(api):** |
| ### *recipes* / [defer:tests/collect](/recipe_modules/defer/tests/collect.py) |
| |
| [DEPS](/recipe_modules/defer/tests/collect.py#15): [context](#recipe_modules-context), [defer](#recipe_modules-defer), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/defer/tests/collect.py#29)(api, props):** |
| ### *recipes* / [defer:tests/context](/recipe_modules/defer/tests/context.py) |
| |
| [DEPS](/recipe_modules/defer/tests/context.py#15): [context](#recipe_modules-context), [defer](#recipe_modules-defer), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/defer/tests/context.py#29)(api, props):** |
| ### *recipes* / [defer:tests/non\_deferred](/recipe_modules/defer/tests/non_deferred.py) |
| |
| [DEPS](/recipe_modules/defer/tests/non_deferred.py#14): [context](#recipe_modules-context), [defer](#recipe_modules-defer), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/defer/tests/non_deferred.py#28)(api, props):** |
| ### *recipes* / [defer:tests/result](/recipe_modules/defer/tests/result.py) |
| |
| [DEPS](/recipe_modules/defer/tests/result.py#14): [context](#recipe_modules-context), [defer](#recipe_modules-defer), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/defer/tests/result.py#28)(api, props):** |
| ### *recipes* / [defer:tests/suppressed](/recipe_modules/defer/tests/suppressed.py) |
| |
| [DEPS](/recipe_modules/defer/tests/suppressed.py#15): [defer](#recipe_modules-defer), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/defer/tests/suppressed.py#32)(api: recipe_api.RecipeApi, props: properties_pb2.SuppressedInputProps):** |
| ### *recipes* / [engine\_tests/allowlist\_steps](/recipes/engine_tests/allowlist_steps.py) |
| |
| [DEPS](/recipes/engine_tests/allowlist_steps.py#18): [context](#recipe_modules-context), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| Tests that step_data can accept multiple specs at once. |
| |
| — **def [RunSteps](/recipes/engine_tests/allowlist_steps.py#32)(api, props: allowlist_steps_pb.InputProperties):** |
| ### *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) |
| |
| |
| 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) |
| |
| |
| A fast-running recipe which comprehensively covers all StepPresentation |
| features available in the recipe engine. |
| |
| — **def [RunSteps](/recipes/engine_tests/comprehensive_ui.py#28)(api):** |
| |
| — **def [named\_step](/recipes/engine_tests/comprehensive_ui.py#24)(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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| Tests that tests with a single exception are handled correctly. |
| |
| — **def [RunSteps](/recipes/engine_tests/expect_exception.py#18)(api):** |
| |
| — **def [my\_function](/recipes/engine_tests/expect_exception.py#14)():** |
| ### *recipes* / [engine\_tests/expect\_exceptions](/recipes/engine_tests/expect_exceptions.py) |
| |
| |
| Tests that tests with multiple exceptions are handled correctly. |
| |
| — **def [RunSteps](/recipes/engine_tests/expect_exceptions.py#25)(api):** |
| |
| — **def [my\_function](/recipes/engine_tests/expect_exceptions.py#13)():** |
| ### *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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| Tests that engine.py can handle unknown recipe results. |
| |
| — **def [RunSteps](/recipes/engine_tests/incorrect_recipe_result.py#23)(api, props):** |
| ### *recipes* / [engine\_tests/long\_sleep](/recipes/engine_tests/long_sleep.py) |
| |
| [DEPS](/recipes/engine_tests/long_sleep.py#10): [futures](#recipe_modules-futures), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| Simple recipe which sleeps in a subprocess forever to facilitate early |
| termination tests. |
| |
| — **def [RunSteps](/recipes/engine_tests/long_sleep.py#24)(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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| — **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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| — **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) |
| |
| |
| Tests that recipes have access to names, resources and their repo. |
| |
| — **def [RunSteps](/recipes/engine_tests/recipe_paths.py#14)(api):** |
| ### *recipes* / [engine\_tests/recipe\_test\_data](/recipes/engine_tests/recipe_test_data.py) |
| |
| [DEPS](/recipes/engine_tests/recipe_test_data.py#11): [step](#recipe_modules-step) |
| |
| |
| Tests that we can pass data via api.recipe_test_data. |
| |
| — **def [RunSteps](/recipes/engine_tests/recipe_test_data.py#16)(api):** |
| ### *recipes* / [engine\_tests/sort\_properties](/recipes/engine_tests/sort_properties.py) |
| |
| [DEPS](/recipes/engine_tests/sort_properties.py#9): [step](#recipe_modules-step) |
| |
| |
| 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#14): [cipd](#recipe_modules-cipd), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipes/engine_tests/undeclared_method.py#30)(api, props: undeclared_method_pb.InputProperties):** |
| ### *recipes* / [engine\_tests/unicode](/recipes/engine_tests/unicode.py) |
| |
| [DEPS](/recipes/engine_tests/unicode.py#8): [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipes/engine_tests/unicode.py#13)(api):** |
| ### *recipes* / [file:examples/chmod](/recipe_modules/file/examples/chmod.py) |
| |
| [DEPS](/recipe_modules/file/examples/chmod.py#7): [file](#recipe_modules-file), [path](#recipe_modules-path) |
| |
| |
| — **def [RunSteps](/recipe_modules/file/examples/chmod.py#13)(api):** |
| ### *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) |
| |
| |
| — **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) |
| |
| |
| — **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#9): [file](#recipe_modules-file), [path](#recipe_modules-path), [properties](#recipe_modules-properties) |
| |
| |
| — **def [RunSteps](/recipe_modules/file/examples/copytree.py#18)(api, properties):** |
| ### *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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/file/examples/truncate.py#13)(api):** |
| ### *recipes* / [findings:tests/infer\_source](/recipe_modules/findings/tests/infer_source.py) |
| |
| [DEPS](/recipe_modules/findings/tests/infer_source.py#12): [assertions](#recipe_modules-assertions), [buildbucket](#recipe_modules-buildbucket), [findings](#recipe_modules-findings), [properties](#recipe_modules-properties) |
| |
| |
| — **def [RunSteps](/recipe_modules/findings/tests/infer_source.py#22)(api, expected_loc):** |
| ### *recipes* / [findings:tests/upload\_findings](/recipe_modules/findings/tests/upload_findings.py) |
| |
| [DEPS](/recipe_modules/findings/tests/upload_findings.py#11): [buildbucket](#recipe_modules-buildbucket), [findings](#recipe_modules-findings), [properties](#recipe_modules-properties) |
| |
| |
| — **def [RunSteps](/recipe_modules/findings/tests/upload_findings.py#20)(api, props):** |
| ### *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) |
| |
| |
| — **def [RunSteps](/recipe_modules/futures/examples/background_helper.py#87)(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#60)(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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| — **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) |
| |
| |
| — **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#10): [generator\_script](#recipe_modules-generator_script), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/generator_script/examples/full.py#26)(api, props: full_pb.InputProperties):** |
| ### *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) |
| |
| |
| — **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) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/JSON_READ_DEPRECATED')**<br>— **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/json/tests/add_json_log.py#12)(api):** |
| ### *recipes* / [json:tests/unsorted](/recipe_modules/json/tests/unsorted.py) |
| |
| [DEPS](/recipe_modules/json/tests/unsorted.py#14): [json](#recipe_modules-json), [step](#recipe_modules-step) |
| |
| |
| Test to assert that sort_keys=False preserves insertion order. |
| |
| — **def [RunSteps](/recipe_modules/json/tests/unsorted.py#19)(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) |
| |
| |
| — **def [RunSteps](/recipe_modules/led/tests/full.py#36)(api, props: full_pb.InputProperties):** |
| ### *recipes* / [led:tests/led\_real\_build](/recipe_modules/led/tests/led_real_build.py) |
| |
| [DEPS](/recipe_modules/led/tests/led_real_build.py#11): [buildbucket](#recipe_modules-buildbucket), [led](#recipe_modules-led), [properties](#recipe_modules-properties), [proto](#recipe_modules-proto), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/led/tests/led_real_build.py#27)(api, props: led_real_build_pb.InputProperties):** |
| ### *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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/led/tests/trigger_build.py#15)(api):** |
| ### *recipes* / [led:tests/trigger\_build\_with\_payload](/recipe_modules/led/tests/trigger_build_with_payload.py) |
| |
| [DEPS](/recipe_modules/led/tests/trigger_build_with_payload.py#10): [led](#recipe_modules-led), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/led/tests/trigger_build_with_payload.py#17)(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) |
| |
| |
| — **def [RunSteps](/recipe_modules/legacy_annotation/examples/full.py#20)(api):** |
| ### *recipes* / [luci\_analysis:tests/query\_failure\_rate\_test](/recipe_modules/luci_analysis/tests/query_failure_rate_test.py) |
| |
| [DEPS](/recipe_modules/luci_analysis/tests/query_failure_rate_test.py#11): [assertions](#recipe_modules-assertions), [json](#recipe_modules-json), [luci\_analysis](#recipe_modules-luci_analysis), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io) |
| |
| |
| Tests for query_failure_rate. |
| |
| — **def [RunSteps](/recipe_modules/luci_analysis/tests/query_failure_rate_test.py#33)(api, props: query_failure_rate_test_pb.InputProperties):** |
| ### *recipes* / [luci\_analysis:tests/query\_stability\_test](/recipe_modules/luci_analysis/tests/query_stability_test.py) |
| |
| [DEPS](/recipe_modules/luci_analysis/tests/query_stability_test.py#13): [assertions](#recipe_modules-assertions), [json](#recipe_modules-json), [luci\_analysis](#recipe_modules-luci_analysis), [properties](#recipe_modules-properties), [raw\_io](#recipe_modules-raw_io) |
| |
| |
| Tests for query_stability. |
| |
| — **def [RunSteps](/recipe_modules/luci_analysis/tests/query_stability_test.py#60)(api, props: query_stability_test_pb.InputProperties):** |
| ### *recipes* / [luci\_analysis:tests/test\_generate\_analysis](/recipe_modules/luci_analysis/tests/test_generate_analysis.py) |
| |
| [DEPS](/recipe_modules/luci_analysis/tests/test_generate_analysis.py#9): [json](#recipe_modules-json), [luci\_analysis](#recipe_modules-luci_analysis), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| |
| Tests for generate_analysis. |
| |
| — **def [RunSteps](/recipe_modules/luci_analysis/tests/test_generate_analysis.py#17)(api):** |
| ### *recipes* / [luci\_analysis:tests/test\_generate\_stability\_response](/recipe_modules/luci_analysis/tests/test_generate_stability_response.py) |
| |
| [DEPS](/recipe_modules/luci_analysis/tests/test_generate_stability_response.py#9): [json](#recipe_modules-json), [luci\_analysis](#recipe_modules-luci_analysis), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| |
| Tests for generate_stability_response. |
| |
| — **def [RunSteps](/recipe_modules/luci_analysis/tests/test_generate_stability_response.py#17)(api):** |
| ### *recipes* / [luci\_analysis:tests/test\_history\_query](/recipe_modules/luci_analysis/tests/test_history_query.py) |
| |
| [DEPS](/recipe_modules/luci_analysis/tests/test_history_query.py#15): [json](#recipe_modules-json), [luci\_analysis](#recipe_modules-luci_analysis), [raw\_io](#recipe_modules-raw_io), [step](#recipe_modules-step) |
| |
| |
| Tests for query_failure_rate. |
| |
| — **def [RunSteps](/recipe_modules/luci_analysis/tests/test_history_query.py#23)(api):** |
| ### *recipes* / [luci\_analysis:tests/test\_lookup\_bug](/recipe_modules/luci_analysis/tests/test_lookup_bug.py) |
| |
| [DEPS](/recipe_modules/luci_analysis/tests/test_lookup_bug.py#8): [assertions](#recipe_modules-assertions), [json](#recipe_modules-json), [luci\_analysis](#recipe_modules-luci_analysis), [step](#recipe_modules-step) |
| |
| |
| Tests for lookup_bug. |
| |
| — **def [RunSteps](/recipe_modules/luci_analysis/tests/test_lookup_bug.py#16)(api):** |
| ### *recipes* / [luci\_analysis:tests/test\_query\_cluster\_failures](/recipe_modules/luci_analysis/tests/test_query_cluster_failures.py) |
| |
| [DEPS](/recipe_modules/luci_analysis/tests/test_query_cluster_failures.py#9): [assertions](#recipe_modules-assertions), [luci\_analysis](#recipe_modules-luci_analysis), [step](#recipe_modules-step) |
| |
| |
| Tests for query_cluster_failres. |
| |
| — **def [RunSteps](/recipe_modules/luci_analysis/tests/test_query_cluster_failures.py#16)(api):** |
| ### *recipes* / [luci\_analysis:tests/test\_query\_variants](/recipe_modules/luci_analysis/tests/test_query_variants.py) |
| |
| [DEPS](/recipe_modules/luci_analysis/tests/test_query_variants.py#12): [luci\_analysis](#recipe_modules-luci_analysis), [step](#recipe_modules-step) |
| |
| |
| Tests for query_variants. |
| |
| — **def [RunSteps](/recipe_modules/luci_analysis/tests/test_query_variants.py#18)(api):** |
| ### *recipes* / [luci\_config:tests/full](/recipe_modules/luci_config/tests/full.py) |
| |
| [DEPS](/recipe_modules/luci_config/tests/full.py#10): [buildbucket](#recipe_modules-buildbucket), [luci\_config](#recipe_modules-luci_config), [path](#recipe_modules-path) |
| |
| |
| — **def [RunSteps](/recipe_modules/luci_config/tests/full.py#17)(api):** |
| ### *recipes* / [milo:examples/full](/recipe_modules/milo/examples/full.py) |
| |
| [DEPS](/recipe_modules/milo/examples/full.py#9): [buildbucket](#recipe_modules-buildbucket), [milo](#recipe_modules-milo) |
| |
| |
| — **def [RunSteps](/recipe_modules/milo/examples/full.py#14)(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) |
| |
| |
| — **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#9): [json](#recipe_modules-json), [path](#recipe_modules-path), [platform](#recipe_modules-platform), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CHECKOUT_DIR_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/path/examples/full.py#20)(api):** |
| ### *recipes* / [path:tests/cast\_to\_path](/recipe_modules/path/tests/cast_to_path.py) |
| |
| [DEPS](/recipe_modules/path/tests/cast_to_path.py#10): [path](#recipe_modules-path), [platform](#recipe_modules-platform) |
| |
| |
| — **def [RunSteps](/recipe_modules/path/tests/cast_to_path.py#16)(api):** |
| ### *recipes* / [path:tests/dynamic\_paths](/recipe_modules/path/tests/dynamic_paths.py) |
| |
| [DEPS](/recipe_modules/path/tests/dynamic_paths.py#10): [path](#recipe_modules-path) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CHECKOUT_DIR_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/path/tests/dynamic_paths.py#13)(api):** |
| ### *recipes* / [path:tests/exists](/recipe_modules/path/tests/exists.py) |
| |
| [DEPS](/recipe_modules/path/tests/exists.py#10): [path](#recipe_modules-path), [raw\_io](#recipe_modules-raw_io) |
| |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CHECKOUT_DIR_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/path/tests/exists.py#16)(api):** |
| ### *recipes* / [path:tests/expand](/recipe_modules/path/tests/expand.py) |
| |
| [DEPS](/recipe_modules/path/tests/expand.py#9): [context](#recipe_modules-context), [path](#recipe_modules-path), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/path/tests/expand.py#16)(api):** |
| ### *recipes* / [path:tests/test\_api\_legacy](/recipe_modules/path/tests/test_api_legacy.py) |
| |
| [DEPS](/recipe_modules/path/tests/test_api_legacy.py#11): [path](#recipe_modules-path) |
| |
| |
| Test to cover legacy aspects of PathTestApi. |
| |
|   **@recipe_api.ignore_warnings('recipe_engine/CHECKOUT_DIR_DEPRECATED')**<br>— **def [RunSteps](/recipe_modules/path/tests/test_api_legacy.py#22)(api):** |
| ### *recipes* / [placeholder](/recipes/placeholder.py) |
| |
| [DEPS](/recipes/placeholder.py#11): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step), [swarming](#recipe_modules-swarming), [time](#recipe_modules-time) |
| |
| |
| — **def [RunSteps](/recipes/placeholder.py#41)(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) |
| |
| |
| — **def [RunSteps](/recipe_modules/platform/examples/full.py#12)(api):** |
| ### *recipes* / [properties:examples/full](/recipe_modules/properties/examples/full.py) |
| |
| [DEPS](/recipe_modules/properties/examples/full.py#15): [json](#recipe_modules-json), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/properties/examples/full.py#24)(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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/get_included_invocations.py#15)(api):** |
| ### *recipes* / [resultdb:examples/get\_invocation\_instructions](/recipe_modules/resultdb/examples/get_invocation_instructions.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/get_invocation_instructions.py#12): [assertions](#recipe_modules-assertions), [resultdb](#recipe_modules-resultdb) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/get_invocation_instructions.py#18)(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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/query.py#24)(api):** |
| ### *recipes* / [resultdb:examples/query\_new\_test\_variants](/recipe_modules/resultdb/examples/query_new_test_variants.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/query_new_test_variants.py#11): [properties](#recipe_modules-properties), [resultdb](#recipe_modules-resultdb) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/query_new_test_variants.py#26)(api, props: query_new_test_variants_pb.InputProperties):** |
| ### *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) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/query_test_result_statistics.py#18)(api):** |
| ### *recipes* / [resultdb:examples/query\_test\_results](/recipe_modules/resultdb/examples/query_test_results.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/query_test_results.py#11): [properties](#recipe_modules-properties), [resultdb](#recipe_modules-resultdb) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/query_test_results.py#25)(api, props: query_test_results_pb.InputProperties):** |
| ### *recipes* / [resultdb:examples/query\_test\_variants](/recipe_modules/resultdb/examples/query_test_variants.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/query_test_variants.py#11): [properties](#recipe_modules-properties), [resultdb](#recipe_modules-resultdb) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/query_test_variants.py#27)(api, props: query_test_variants_pb.InputProperties):** |
| ### *recipes* / [resultdb:examples/resultsink](/recipe_modules/resultdb/examples/resultsink.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/resultsink.py#10): [context](#recipe_modules-context), [resultdb](#recipe_modules-resultdb), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/resultsink.py#17)(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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/test_presentation_default.py#11)(api):** |
| ### *recipes* / [resultdb:examples/update\_invocation](/recipe_modules/resultdb/examples/update_invocation.py) |
| |
| [DEPS](/recipe_modules/resultdb/examples/update_invocation.py#15): [properties](#recipe_modules-properties), [resultdb](#recipe_modules-resultdb) |
| |
| |
| — **def [RunSteps](/recipe_modules/resultdb/examples/update_invocation.py#44)(api, props: update_invocation_pb.InputProperties):** |
| ### *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) |
| |
| |
| — **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#11): [runtime](#recipe_modules-runtime), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/runtime/tests/full.py#17)(api: recipe_api.RecipeScriptApi):** |
| ### *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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| 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) |
| |
| |
| — **def [RunSteps](/recipe_modules/service_account/examples/full.py#27)(api, props: full_pb.InputProperties):** |
| ### *recipes* / [step:examples/full](/recipe_modules/step/examples/full.py) |
| |
| [DEPS](/recipe_modules/step/examples/full.py#10): [buildbucket](#recipe_modules-buildbucket), [context](#recipe_modules-context), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/step/examples/full.py#31)(api, props: full_pb.InputProperties):** |
| ### *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) |
| |
| |
| — **def [RunSteps](/recipe_modules/step/tests/active_result.py#12)(api):** |
| ### *recipes* / [step:tests/drop\_expectation](/recipe_modules/step/tests/drop_expectation.py) |
| |
| [DEPS](/recipe_modules/step/tests/drop_expectation.py#12): [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/step/tests/drop_expectation.py#17)(api):** |
| ### *recipes* / [step:tests/empty](/recipe_modules/step/tests/empty.py) |
| |
| [DEPS](/recipe_modules/step/tests/empty.py#18): [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/step/tests/empty.py#23)(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) |
| |
| |
| — **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#12): [context](#recipe_modules-context), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/step/tests/nested.py#18)(api):** |
| ### *recipes* / [step:tests/raise\_on\_failure](/recipe_modules/step/tests/raise_on_failure.py) |
| |
| [DEPS](/recipe_modules/step/tests/raise_on_failure.py#10): [properties](#recipe_modules-properties), [step](#recipe_modules-step) |
| |
| |
| — **def [RunSteps](/recipe_modules/step/tests/raise_on_failure.py#24)(api, props: raise_on_failure_pb.InputProperties):** |
| ### *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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/step/tests/timeout.py#23)(api, props: timeout_pb.InputProperties):** |
| ### *recipes* / [swarming:examples/full](/recipe_modules/swarming/examples/full.py) |
| |
| [DEPS](/recipe_modules/swarming/examples/full.py#13): [buildbucket](#recipe_modules-buildbucket), [cipd](#recipe_modules-cipd), [json](#recipe_modules-json), [path](#recipe_modules-path), [properties](#recipe_modules-properties), [step](#recipe_modules-step), [swarming](#recipe_modules-swarming) |
| |
| |
| — **def [RunSteps](/recipe_modules/swarming/examples/full.py#18)(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) |
| |
| |
| — **def [RunSteps](/recipe_modules/swarming/examples/this_task.py#13)(api):** |
| ### *recipes* / [swarming:tests/collect\_errors](/recipe_modules/swarming/tests/collect_errors.py) |
| |
| [DEPS](/recipe_modules/swarming/tests/collect_errors.py#9): [assertions](#recipe_modules-assertions), [path](#recipe_modules-path), [swarming](#recipe_modules-swarming) |
| |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/collect_errors.py#16)(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) |
| |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/copy.py#15)(api):** |
| ### *recipes* / [swarming:tests/list\_bots](/recipe_modules/swarming/tests/list_bots.py) |
| |
| [DEPS](/recipe_modules/swarming/tests/list_bots.py#10): [assertions](#recipe_modules-assertions), [swarming](#recipe_modules-swarming) |
| |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/list_bots.py#16)(api):** |
| ### *recipes* / [swarming:tests/list\_tasks](/recipe_modules/swarming/tests/list_tasks.py) |
| |
| [DEPS](/recipe_modules/swarming/tests/list_tasks.py#9): [assertions](#recipe_modules-assertions), [swarming](#recipe_modules-swarming), [time](#recipe_modules-time) |
| |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/list_tasks.py#16)(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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/task_request_from_jsonish.py#15)(api):** |
| ### *recipes* / [swarming:tests/task\_result\_from\_jsonish](/recipe_modules/swarming/tests/task_result_from_jsonish.py) |
| |
| [DEPS](/recipe_modules/swarming/tests/task_result_from_jsonish.py#11): [assertions](#recipe_modules-assertions), [path](#recipe_modules-path), [swarming](#recipe_modules-swarming) |
| |
| |
| — **def [RunSteps](/recipe_modules/swarming/tests/task_result_from_jsonish.py#18)(api):** |
| ### *recipes* / [time:examples/full](/recipe_modules/time/examples/full.py) |
| |
| [DEPS](/recipe_modules/time/examples/full.py#20): [assertions](#recipe_modules-assertions), [properties](#recipe_modules-properties), [runtime](#recipe_modules-runtime), [step](#recipe_modules-step), [time](#recipe_modules-time) |
| |
| |
| — **def [RunSteps](/recipe_modules/time/examples/full.py#46)(api):** |
| |
|   **@exponential_retry(5, datetime.timedelta(seconds=1))**<br>— **def [helper\_fn\_that\_needs\_retries](/recipe_modules/time/examples/full.py#40)(api):** |
| ### *recipes* / [time:examples/jitter](/recipe_modules/time/examples/jitter.py) |
| |
| [DEPS](/recipe_modules/time/examples/jitter.py#10): [assertions](#recipe_modules-assertions), [properties](#recipe_modules-properties), [step](#recipe_modules-step), [time](#recipe_modules-time) |
| |
| |
| — **def [RunSteps](/recipe_modules/time/examples/jitter.py#27)(api, properties):** |
| ### *recipes* / [tricium:examples/add\_comment](/recipe_modules/tricium/examples/add_comment.py) |
| |
| [DEPS](/recipe_modules/tricium/examples/add_comment.py#13): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [proto](#recipe_modules-proto), [tricium](#recipe_modules-tricium) |
| |
| |
| — **def [CreateExpectedFinding](/recipe_modules/tricium/examples/add_comment.py#71)(api, input_comment):** |
| |
| — **def [RunSteps](/recipe_modules/tricium/examples/add_comment.py#119)(api, props: add_comment_pb.InputProperties):** |
| ### *recipes* / [tricium:examples/wrapper](/recipe_modules/tricium/examples/wrapper.py) |
| |
| [DEPS](/recipe_modules/tricium/examples/wrapper.py#14): [buildbucket](#recipe_modules-buildbucket), [file](#recipe_modules-file), [path](#recipe_modules-path), [tricium](#recipe_modules-tricium) |
| |
| |
| An example of a recipe wrapping legacy analyzers. |
| |
| — **def [RunSteps](/recipe_modules/tricium/examples/wrapper.py#22)(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): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [tricium](#recipe_modules-tricium) |
| |
| |
| — **def [RunSteps](/recipe_modules/tricium/tests/add_comment_validation.py#47)(api, props: add_comment_validation_pb.InputProperties):** |
| ### *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), [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [proto](#recipe_modules-proto), [tricium](#recipe_modules-tricium) |
| |
| |
| — **def [RunSteps](/recipe_modules/tricium/tests/enforce_comments_num_limit.py#23)(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) |
| |
| |
| — **def [RunSteps](/recipe_modules/url/examples/full.py#30)(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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **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) |
| |
| |
| — **def [RunSteps](/recipe_modules/version/examples/full.py#12)(api):** |
| ### *recipes* / [warning:tests/fakes](/recipe_modules/warning/tests/fakes.py) |
| |
| |
| 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):** |
| |