cumulusci-plus 5.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cumulusci-plus might be problematic. Click here for more details.
- cumulusci/__about__.py +1 -0
- cumulusci/__init__.py +22 -0
- cumulusci/__main__.py +3 -0
- cumulusci/cli/__init__.py +0 -0
- cumulusci/cli/cci.py +244 -0
- cumulusci/cli/error.py +125 -0
- cumulusci/cli/flow.py +185 -0
- cumulusci/cli/logger.py +72 -0
- cumulusci/cli/org.py +692 -0
- cumulusci/cli/plan.py +181 -0
- cumulusci/cli/project.py +391 -0
- cumulusci/cli/robot.py +116 -0
- cumulusci/cli/runtime.py +190 -0
- cumulusci/cli/service.py +521 -0
- cumulusci/cli/task.py +295 -0
- cumulusci/cli/tests/__init__.py +0 -0
- cumulusci/cli/tests/test_cci.py +545 -0
- cumulusci/cli/tests/test_error.py +170 -0
- cumulusci/cli/tests/test_flow.py +276 -0
- cumulusci/cli/tests/test_logger.py +25 -0
- cumulusci/cli/tests/test_org.py +1438 -0
- cumulusci/cli/tests/test_plan.py +245 -0
- cumulusci/cli/tests/test_project.py +235 -0
- cumulusci/cli/tests/test_robot.py +177 -0
- cumulusci/cli/tests/test_runtime.py +197 -0
- cumulusci/cli/tests/test_service.py +853 -0
- cumulusci/cli/tests/test_task.py +266 -0
- cumulusci/cli/tests/test_ui.py +310 -0
- cumulusci/cli/tests/test_utils.py +122 -0
- cumulusci/cli/tests/utils.py +52 -0
- cumulusci/cli/ui.py +234 -0
- cumulusci/cli/utils.py +150 -0
- cumulusci/conftest.py +181 -0
- cumulusci/core/__init__.py +0 -0
- cumulusci/core/config/BaseConfig.py +5 -0
- cumulusci/core/config/BaseTaskFlowConfig.py +5 -0
- cumulusci/core/config/OrgConfig.py +5 -0
- cumulusci/core/config/ScratchOrgConfig.py +5 -0
- cumulusci/core/config/__init__.py +125 -0
- cumulusci/core/config/base_config.py +111 -0
- cumulusci/core/config/base_task_flow_config.py +82 -0
- cumulusci/core/config/marketing_cloud_service_config.py +83 -0
- cumulusci/core/config/oauth2_service_config.py +17 -0
- cumulusci/core/config/org_config.py +604 -0
- cumulusci/core/config/project_config.py +782 -0
- cumulusci/core/config/scratch_org_config.py +251 -0
- cumulusci/core/config/sfdx_org_config.py +220 -0
- cumulusci/core/config/tests/_test_config_backwards_compatibility.py +33 -0
- cumulusci/core/config/tests/test_config.py +1895 -0
- cumulusci/core/config/tests/test_config_expensive.py +839 -0
- cumulusci/core/config/tests/test_config_util.py +91 -0
- cumulusci/core/config/universal_config.py +88 -0
- cumulusci/core/config/util.py +18 -0
- cumulusci/core/datasets.py +303 -0
- cumulusci/core/debug.py +33 -0
- cumulusci/core/dependencies/__init__.py +55 -0
- cumulusci/core/dependencies/base.py +561 -0
- cumulusci/core/dependencies/dependencies.py +273 -0
- cumulusci/core/dependencies/github.py +177 -0
- cumulusci/core/dependencies/github_resolvers.py +244 -0
- cumulusci/core/dependencies/resolvers.py +580 -0
- cumulusci/core/dependencies/tests/__init__.py +0 -0
- cumulusci/core/dependencies/tests/conftest.py +385 -0
- cumulusci/core/dependencies/tests/test_dependencies.py +950 -0
- cumulusci/core/dependencies/tests/test_github.py +83 -0
- cumulusci/core/dependencies/tests/test_resolvers.py +1027 -0
- cumulusci/core/dependencies/utils.py +13 -0
- cumulusci/core/enums.py +11 -0
- cumulusci/core/exceptions.py +311 -0
- cumulusci/core/flowrunner.py +888 -0
- cumulusci/core/github.py +665 -0
- cumulusci/core/keychain/__init__.py +24 -0
- cumulusci/core/keychain/base_project_keychain.py +441 -0
- cumulusci/core/keychain/encrypted_file_project_keychain.py +945 -0
- cumulusci/core/keychain/environment_project_keychain.py +7 -0
- cumulusci/core/keychain/serialization.py +152 -0
- cumulusci/core/keychain/subprocess_keychain.py +24 -0
- cumulusci/core/keychain/tests/conftest.py +50 -0
- cumulusci/core/keychain/tests/test_base_project_keychain.py +299 -0
- cumulusci/core/keychain/tests/test_encrypted_file_project_keychain.py +1228 -0
- cumulusci/core/metadeploy/__init__.py +0 -0
- cumulusci/core/metadeploy/api.py +88 -0
- cumulusci/core/metadeploy/plans.py +25 -0
- cumulusci/core/metadeploy/tests/test_api.py +276 -0
- cumulusci/core/runtime.py +115 -0
- cumulusci/core/sfdx.py +162 -0
- cumulusci/core/source/__init__.py +16 -0
- cumulusci/core/source/github.py +50 -0
- cumulusci/core/source/local_folder.py +35 -0
- cumulusci/core/source_transforms/__init__.py +0 -0
- cumulusci/core/source_transforms/tests/test_transforms.py +1091 -0
- cumulusci/core/source_transforms/transforms.py +532 -0
- cumulusci/core/tasks.py +404 -0
- cumulusci/core/template_utils.py +59 -0
- cumulusci/core/tests/__init__.py +0 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_e2e.yaml +215 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_extract_standard_objects.yaml +199 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml +3 -0
- cumulusci/core/tests/fake_remote_repo/cumulusci.yml +32 -0
- cumulusci/core/tests/fake_remote_repo/tasks/directory/example_2.py +6 -0
- cumulusci/core/tests/fake_remote_repo/tasks/example.py +43 -0
- cumulusci/core/tests/fake_remote_repo_2/cumulusci.yml +11 -0
- cumulusci/core/tests/fake_remote_repo_2/tasks/example_3.py +6 -0
- cumulusci/core/tests/test_datasets_e2e.py +386 -0
- cumulusci/core/tests/test_exceptions.py +11 -0
- cumulusci/core/tests/test_flowrunner.py +836 -0
- cumulusci/core/tests/test_github.py +942 -0
- cumulusci/core/tests/test_sfdx.py +138 -0
- cumulusci/core/tests/test_source.py +678 -0
- cumulusci/core/tests/test_tasks.py +262 -0
- cumulusci/core/tests/test_utils.py +141 -0
- cumulusci/core/tests/test_utils_merge_config.py +276 -0
- cumulusci/core/tests/test_versions.py +76 -0
- cumulusci/core/tests/untrusted_repo_child/cumulusci.yml +7 -0
- cumulusci/core/tests/untrusted_repo_child/tasks/untrusted_child.py +6 -0
- cumulusci/core/tests/untrusted_repo_parent/cumulusci.yml +26 -0
- cumulusci/core/tests/untrusted_repo_parent/tasks/untrusted_parent.py +6 -0
- cumulusci/core/tests/utils.py +116 -0
- cumulusci/core/tests/yaml/global.yaml +0 -0
- cumulusci/core/utils.py +402 -0
- cumulusci/core/versions.py +149 -0
- cumulusci/cumulusci.yml +1621 -0
- cumulusci/files/admin_profile.xml +20 -0
- cumulusci/files/delete_excludes.txt +424 -0
- cumulusci/files/templates/project/README.md +12 -0
- cumulusci/files/templates/project/cumulusci.yml +63 -0
- cumulusci/files/templates/project/dot-gitignore +60 -0
- cumulusci/files/templates/project/mapping.yml +45 -0
- cumulusci/files/templates/project/scratch_def.json +25 -0
- cumulusci/oauth/__init__.py +0 -0
- cumulusci/oauth/client.py +400 -0
- cumulusci/oauth/exceptions.py +9 -0
- cumulusci/oauth/salesforce.py +95 -0
- cumulusci/oauth/tests/__init__.py +0 -0
- cumulusci/oauth/tests/cassettes/test_get_device_code.yaml +22 -0
- cumulusci/oauth/tests/cassettes/test_get_device_oauth_token.yaml +74 -0
- cumulusci/oauth/tests/test_client.py +308 -0
- cumulusci/oauth/tests/test_salesforce.py +46 -0
- cumulusci/plugins/__init__.py +3 -0
- cumulusci/plugins/plugin_base.py +93 -0
- cumulusci/plugins/plugin_loader.py +59 -0
- cumulusci/robotframework/CumulusCI.py +340 -0
- cumulusci/robotframework/CumulusCI.robot +7 -0
- cumulusci/robotframework/Performance.py +165 -0
- cumulusci/robotframework/Salesforce.py +936 -0
- cumulusci/robotframework/Salesforce.robot +192 -0
- cumulusci/robotframework/SalesforceAPI.py +416 -0
- cumulusci/robotframework/SalesforcePlaywright.py +220 -0
- cumulusci/robotframework/SalesforcePlaywright.robot +40 -0
- cumulusci/robotframework/__init__.py +2 -0
- cumulusci/robotframework/base_library.py +39 -0
- cumulusci/robotframework/faker_mixin.py +89 -0
- cumulusci/robotframework/form_handlers.py +222 -0
- cumulusci/robotframework/javascript/cci_init.js +34 -0
- cumulusci/robotframework/javascript/cumulusci.js +4 -0
- cumulusci/robotframework/locator_manager.py +197 -0
- cumulusci/robotframework/locators_56.py +88 -0
- cumulusci/robotframework/locators_57.py +5 -0
- cumulusci/robotframework/pageobjects/BasePageObjects.py +433 -0
- cumulusci/robotframework/pageobjects/ObjectManagerPageObject.py +246 -0
- cumulusci/robotframework/pageobjects/PageObjectLibrary.py +45 -0
- cumulusci/robotframework/pageobjects/PageObjects.py +351 -0
- cumulusci/robotframework/pageobjects/__init__.py +12 -0
- cumulusci/robotframework/pageobjects/baseobjects.py +120 -0
- cumulusci/robotframework/perftests/short/collection_perf.robot +105 -0
- cumulusci/robotframework/tests/CustomObjectTestPage.py +10 -0
- cumulusci/robotframework/tests/FooTestPage.py +8 -0
- cumulusci/robotframework/tests/cumulusci/base.robot +40 -0
- cumulusci/robotframework/tests/cumulusci/bulkdata.robot +38 -0
- cumulusci/robotframework/tests/cumulusci/communities.robot +57 -0
- cumulusci/robotframework/tests/cumulusci/datagen.robot +84 -0
- cumulusci/robotframework/tests/salesforce/TestLibraryA.py +24 -0
- cumulusci/robotframework/tests/salesforce/TestLibraryB.py +20 -0
- cumulusci/robotframework/tests/salesforce/TestListener.py +93 -0
- cumulusci/robotframework/tests/salesforce/api.robot +178 -0
- cumulusci/robotframework/tests/salesforce/browsers.robot +143 -0
- cumulusci/robotframework/tests/salesforce/classic.robot +51 -0
- cumulusci/robotframework/tests/salesforce/create_contact.robot +59 -0
- cumulusci/robotframework/tests/salesforce/faker.robot +68 -0
- cumulusci/robotframework/tests/salesforce/forms.robot +172 -0
- cumulusci/robotframework/tests/salesforce/label_locator.robot +244 -0
- cumulusci/robotframework/tests/salesforce/labels.html +33 -0
- cumulusci/robotframework/tests/salesforce/locators.robot +149 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/base_pageobjects.robot +100 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/example_page_object.py +25 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/listing_page.robot +115 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/objectmanager.robot +74 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/pageobjects.robot +171 -0
- cumulusci/robotframework/tests/salesforce/performance.robot +109 -0
- cumulusci/robotframework/tests/salesforce/playwright/javascript_keywords.robot +33 -0
- cumulusci/robotframework/tests/salesforce/playwright/open_test_browser.robot +48 -0
- cumulusci/robotframework/tests/salesforce/playwright/playwright.robot +24 -0
- cumulusci/robotframework/tests/salesforce/playwright/ui.robot +32 -0
- cumulusci/robotframework/tests/salesforce/populate.robot +89 -0
- cumulusci/robotframework/tests/salesforce/test_testlistener.py +37 -0
- cumulusci/robotframework/tests/salesforce/ui.robot +361 -0
- cumulusci/robotframework/tests/test_cumulusci_library.py +304 -0
- cumulusci/robotframework/tests/test_locator_manager.py +158 -0
- cumulusci/robotframework/tests/test_pageobjects.py +291 -0
- cumulusci/robotframework/tests/test_performance.py +38 -0
- cumulusci/robotframework/tests/test_salesforce.py +79 -0
- cumulusci/robotframework/tests/test_salesforce_locators.py +73 -0
- cumulusci/robotframework/tests/test_template_util.py +53 -0
- cumulusci/robotframework/tests/test_utils.py +106 -0
- cumulusci/robotframework/utils.py +283 -0
- cumulusci/salesforce_api/__init__.py +0 -0
- cumulusci/salesforce_api/exceptions.py +23 -0
- cumulusci/salesforce_api/filterable_objects.py +96 -0
- cumulusci/salesforce_api/mc_soap_envelopes.py +89 -0
- cumulusci/salesforce_api/metadata.py +721 -0
- cumulusci/salesforce_api/org_schema.py +571 -0
- cumulusci/salesforce_api/org_schema_models.py +226 -0
- cumulusci/salesforce_api/package_install.py +265 -0
- cumulusci/salesforce_api/package_zip.py +301 -0
- cumulusci/salesforce_api/rest_deploy.py +148 -0
- cumulusci/salesforce_api/retrieve_profile_api.py +301 -0
- cumulusci/salesforce_api/soap_envelopes.py +177 -0
- cumulusci/salesforce_api/tests/__init__.py +0 -0
- cumulusci/salesforce_api/tests/metadata_test_strings.py +24 -0
- cumulusci/salesforce_api/tests/test_metadata.py +1015 -0
- cumulusci/salesforce_api/tests/test_package_install.py +219 -0
- cumulusci/salesforce_api/tests/test_package_zip.py +380 -0
- cumulusci/salesforce_api/tests/test_rest_deploy.py +264 -0
- cumulusci/salesforce_api/tests/test_retrieve_profile_api.py +337 -0
- cumulusci/salesforce_api/tests/test_utils.py +124 -0
- cumulusci/salesforce_api/utils.py +51 -0
- cumulusci/schema/cumulusci.jsonschema.json +782 -0
- cumulusci/tasks/__init__.py +0 -0
- cumulusci/tasks/apex/__init__.py +0 -0
- cumulusci/tasks/apex/anon.py +157 -0
- cumulusci/tasks/apex/batch.py +180 -0
- cumulusci/tasks/apex/testrunner.py +835 -0
- cumulusci/tasks/apex/tests/cassettes/ManualEditTestApexIntegrationTests.test_run_tests__integration_test.yaml +703 -0
- cumulusci/tasks/apex/tests/test_apex_tasks.py +1558 -0
- cumulusci/tasks/base_source_control_task.py +17 -0
- cumulusci/tasks/bulkdata/__init__.py +15 -0
- cumulusci/tasks/bulkdata/base_generate_data_task.py +96 -0
- cumulusci/tasks/bulkdata/dates.py +97 -0
- cumulusci/tasks/bulkdata/delete.py +156 -0
- cumulusci/tasks/bulkdata/extract.py +441 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/calculate_dependencies.py +117 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/extract_yml.py +123 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/hardcoded_default_declarations.py +49 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/synthesize_extract_declarations.py +283 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_extract_yml.py +142 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_synthesize_extract_declarations.py +575 -0
- cumulusci/tasks/bulkdata/factory_utils.py +134 -0
- cumulusci/tasks/bulkdata/generate.py +4 -0
- cumulusci/tasks/bulkdata/generate_and_load_data.py +232 -0
- cumulusci/tasks/bulkdata/generate_and_load_data_from_yaml.py +19 -0
- cumulusci/tasks/bulkdata/generate_from_yaml.py +183 -0
- cumulusci/tasks/bulkdata/generate_mapping.py +434 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/dependency_map.py +169 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/extract_mapping_file_generator.py +45 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/generate_mapping_from_declarations.py +121 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/load_mapping_file_generator.py +127 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_generator_post_processes.py +53 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_transforms.py +139 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_extract_mapping_from_declarations.py +135 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_load_mapping_from_declarations.py +330 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_generator_post_processes.py +60 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_transforms.py +188 -0
- cumulusci/tasks/bulkdata/load.py +1196 -0
- cumulusci/tasks/bulkdata/mapping_parser.py +811 -0
- cumulusci/tasks/bulkdata/query_transformers.py +264 -0
- cumulusci/tasks/bulkdata/select_utils.py +792 -0
- cumulusci/tasks/bulkdata/snowfakery.py +753 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/queue_manager.py +478 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_run_until.py +141 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_working_directory.py +53 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/subtask_configurator.py +64 -0
- cumulusci/tasks/bulkdata/step.py +1242 -0
- cumulusci/tasks/bulkdata/tests/__init__.py +0 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_random_strategy.yaml +147 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_annoy_strategy.yaml +123 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy.yaml +313 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy_bulk.yaml +550 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_strategy.yaml +175 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_standard_strategy.yaml +147 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__multiple_needed.yaml +69 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__none_needed.yaml +22 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__one_needed.yaml +24 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_snowfakery_query_salesforce.yaml +25 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpdatesIntegrationTests.test_updates_task.yaml +80 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_simple_upsert__rest.yaml +270 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert__rest.yaml +267 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field__rest.yaml +369 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field_rest__duplicate_error.yaml +204 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_fields__bulk.yaml +675 -0
- cumulusci/tasks/bulkdata/tests/dummy_data_factory.py +36 -0
- cumulusci/tasks/bulkdata/tests/integration_test_utils.py +49 -0
- cumulusci/tasks/bulkdata/tests/mapping-oid.yml +87 -0
- cumulusci/tasks/bulkdata/tests/mapping_after.yml +38 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly.yml +34 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly_incomplete.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly_wrong.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_strategy.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_number.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_strategy.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__non_float.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_missing_priority_fields.yml +22 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_no_priority_fields.yml +18 -0
- cumulusci/tasks/bulkdata/tests/mapping_simple.yml +27 -0
- cumulusci/tasks/bulkdata/tests/mapping_v1.yml +28 -0
- cumulusci/tasks/bulkdata/tests/mapping_v2.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_v3.yml +32 -0
- cumulusci/tasks/bulkdata/tests/mapping_vanilla_sf.yml +69 -0
- cumulusci/tasks/bulkdata/tests/mock_data_factory_without_mapping.py +12 -0
- cumulusci/tasks/bulkdata/tests/person_accounts.yml +23 -0
- cumulusci/tasks/bulkdata/tests/person_accounts_minimal.yml +15 -0
- cumulusci/tasks/bulkdata/tests/recordtypes.yml +8 -0
- cumulusci/tasks/bulkdata/tests/recordtypes_2.yml +6 -0
- cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml +8 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/child/child2.yml +3 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/child.yml +4 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/gen_npsp_standard_objects.recipe.yml +89 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/include_parent.yml +3 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/npsp_standard_objects_macros.yml +34 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/options.recipe.yml +6 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/query_snowfakery.recipe.yml +16 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/sf_standard_object_macros.yml +83 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.load.yml +2 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.recipe.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_2.load.yml +5 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.load.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.recipe.yml +12 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels_2.load.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/unique_values.recipe.yml +4 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert.recipe.yml +23 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert_2.recipe.yml +29 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert_before.yml +10 -0
- cumulusci/tasks/bulkdata/tests/test_base_generate_data_tasks.py +61 -0
- cumulusci/tasks/bulkdata/tests/test_dates.py +99 -0
- cumulusci/tasks/bulkdata/tests/test_delete.py +404 -0
- cumulusci/tasks/bulkdata/tests/test_extract.py +1311 -0
- cumulusci/tasks/bulkdata/tests/test_factory_utils.py +55 -0
- cumulusci/tasks/bulkdata/tests/test_generate_and_load.py +252 -0
- cumulusci/tasks/bulkdata/tests/test_generate_from_snowfakery_task.py +343 -0
- cumulusci/tasks/bulkdata/tests/test_generatemapping.py +1039 -0
- cumulusci/tasks/bulkdata/tests/test_load.py +3175 -0
- cumulusci/tasks/bulkdata/tests/test_mapping_parser.py +1658 -0
- cumulusci/tasks/bulkdata/tests/test_query_db__joins_self_lookups.yml +12 -0
- cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups.yml +26 -0
- cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups_select.yml +48 -0
- cumulusci/tasks/bulkdata/tests/test_select.py +171 -0
- cumulusci/tasks/bulkdata/tests/test_select_utils.py +1057 -0
- cumulusci/tasks/bulkdata/tests/test_snowfakery.py +1153 -0
- cumulusci/tasks/bulkdata/tests/test_step.py +3957 -0
- cumulusci/tasks/bulkdata/tests/test_updates.py +513 -0
- cumulusci/tasks/bulkdata/tests/test_upsert.py +1015 -0
- cumulusci/tasks/bulkdata/tests/test_utils.py +158 -0
- cumulusci/tasks/bulkdata/tests/testdata.db +0 -0
- cumulusci/tasks/bulkdata/tests/update_describe.py +50 -0
- cumulusci/tasks/bulkdata/tests/update_person_accounts.yml +23 -0
- cumulusci/tasks/bulkdata/tests/utils.py +114 -0
- cumulusci/tasks/bulkdata/update_data.py +260 -0
- cumulusci/tasks/bulkdata/upsert_utils.py +130 -0
- cumulusci/tasks/bulkdata/utils.py +249 -0
- cumulusci/tasks/command.py +178 -0
- cumulusci/tasks/connectedapp.py +186 -0
- cumulusci/tasks/create_package_version.py +778 -0
- cumulusci/tasks/datadictionary.py +745 -0
- cumulusci/tasks/dx_convert_from.py +26 -0
- cumulusci/tasks/github/__init__.py +17 -0
- cumulusci/tasks/github/base.py +16 -0
- cumulusci/tasks/github/commit_status.py +13 -0
- cumulusci/tasks/github/merge.py +11 -0
- cumulusci/tasks/github/publish.py +11 -0
- cumulusci/tasks/github/pull_request.py +11 -0
- cumulusci/tasks/github/release.py +11 -0
- cumulusci/tasks/github/release_report.py +11 -0
- cumulusci/tasks/github/tag.py +11 -0
- cumulusci/tasks/github/tests/__init__.py +0 -0
- cumulusci/tasks/github/tests/test_util.py +202 -0
- cumulusci/tasks/github/tests/test_vcs_migration.py +44 -0
- cumulusci/tasks/github/tests/util_github_api.py +666 -0
- cumulusci/tasks/github/util.py +252 -0
- cumulusci/tasks/marketing_cloud/__init__.py +0 -0
- cumulusci/tasks/marketing_cloud/api.py +188 -0
- cumulusci/tasks/marketing_cloud/base.py +38 -0
- cumulusci/tasks/marketing_cloud/deploy.py +345 -0
- cumulusci/tasks/marketing_cloud/get_user_info.py +40 -0
- cumulusci/tasks/marketing_cloud/mc_constants.py +1 -0
- cumulusci/tasks/marketing_cloud/tests/__init__.py +0 -0
- cumulusci/tasks/marketing_cloud/tests/conftest.py +46 -0
- cumulusci/tasks/marketing_cloud/tests/expected-payload.json +110 -0
- cumulusci/tasks/marketing_cloud/tests/test_api.py +97 -0
- cumulusci/tasks/marketing_cloud/tests/test_api_soap_envelopes.py +145 -0
- cumulusci/tasks/marketing_cloud/tests/test_base.py +14 -0
- cumulusci/tasks/marketing_cloud/tests/test_deploy.py +400 -0
- cumulusci/tasks/marketing_cloud/tests/test_get_user_info.py +141 -0
- cumulusci/tasks/marketing_cloud/tests/validation-response.json +39 -0
- cumulusci/tasks/metadata/__init__.py +0 -0
- cumulusci/tasks/metadata/ee_src.py +94 -0
- cumulusci/tasks/metadata/managed_src.py +100 -0
- cumulusci/tasks/metadata/metadata_map.yml +868 -0
- cumulusci/tasks/metadata/modify.py +99 -0
- cumulusci/tasks/metadata/package.py +684 -0
- cumulusci/tasks/metadata/tests/__init__.py +0 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/.hidden/.keep +0 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/destructiveChanges.xml +9 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package.xml +9 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package_install_uninstall.xml +11 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/reports/namespace__TestFolder/TestReport.report +3 -0
- cumulusci/tasks/metadata/tests/sample_package.xml +9 -0
- cumulusci/tasks/metadata/tests/test_ee_src.py +112 -0
- cumulusci/tasks/metadata/tests/test_managed_src.py +111 -0
- cumulusci/tasks/metadata/tests/test_modify.py +123 -0
- cumulusci/tasks/metadata/tests/test_package.py +476 -0
- cumulusci/tasks/metadata_etl/__init__.py +29 -0
- cumulusci/tasks/metadata_etl/base.py +436 -0
- cumulusci/tasks/metadata_etl/duplicate_rules.py +24 -0
- cumulusci/tasks/metadata_etl/field_sets.py +70 -0
- cumulusci/tasks/metadata_etl/help_text.py +92 -0
- cumulusci/tasks/metadata_etl/layouts.py +550 -0
- cumulusci/tasks/metadata_etl/objects.py +68 -0
- cumulusci/tasks/metadata_etl/permissions.py +167 -0
- cumulusci/tasks/metadata_etl/picklists.py +221 -0
- cumulusci/tasks/metadata_etl/remote_site_settings.py +99 -0
- cumulusci/tasks/metadata_etl/sharing.py +138 -0
- cumulusci/tasks/metadata_etl/tests/test_base.py +512 -0
- cumulusci/tasks/metadata_etl/tests/test_duplicate_rules.py +22 -0
- cumulusci/tasks/metadata_etl/tests/test_field_sets.py +156 -0
- cumulusci/tasks/metadata_etl/tests/test_help_text.py +387 -0
- cumulusci/tasks/metadata_etl/tests/test_ip_ranges.py +85 -0
- cumulusci/tasks/metadata_etl/tests/test_layouts.py +858 -0
- cumulusci/tasks/metadata_etl/tests/test_objects.py +236 -0
- cumulusci/tasks/metadata_etl/tests/test_permissions.py +223 -0
- cumulusci/tasks/metadata_etl/tests/test_picklists.py +547 -0
- cumulusci/tasks/metadata_etl/tests/test_remote_site_settings.py +46 -0
- cumulusci/tasks/metadata_etl/tests/test_sharing.py +333 -0
- cumulusci/tasks/metadata_etl/tests/test_value_sets.py +298 -0
- cumulusci/tasks/metadata_etl/value_sets.py +106 -0
- cumulusci/tasks/metadeploy.py +393 -0
- cumulusci/tasks/metaxml.py +88 -0
- cumulusci/tasks/preflight/__init__.py +0 -0
- cumulusci/tasks/preflight/dataset_load.py +49 -0
- cumulusci/tasks/preflight/licenses.py +86 -0
- cumulusci/tasks/preflight/packages.py +14 -0
- cumulusci/tasks/preflight/permsets.py +23 -0
- cumulusci/tasks/preflight/recordtypes.py +16 -0
- cumulusci/tasks/preflight/retrieve_tasks.py +30 -0
- cumulusci/tasks/preflight/settings.py +77 -0
- cumulusci/tasks/preflight/sobjects.py +202 -0
- cumulusci/tasks/preflight/tests/test_dataset_load.py +85 -0
- cumulusci/tasks/preflight/tests/test_licenses.py +174 -0
- cumulusci/tasks/preflight/tests/test_packages.py +14 -0
- cumulusci/tasks/preflight/tests/test_permset_preflights.py +51 -0
- cumulusci/tasks/preflight/tests/test_recordtypes.py +30 -0
- cumulusci/tasks/preflight/tests/test_retrieve_tasks.py +62 -0
- cumulusci/tasks/preflight/tests/test_settings.py +130 -0
- cumulusci/tasks/preflight/tests/test_sobjects.py +231 -0
- cumulusci/tasks/push/README.md +59 -0
- cumulusci/tasks/push/__init__.py +0 -0
- cumulusci/tasks/push/push_api.py +659 -0
- cumulusci/tasks/push/pushfails.py +136 -0
- cumulusci/tasks/push/tasks.py +476 -0
- cumulusci/tasks/push/tests/conftest.py +263 -0
- cumulusci/tasks/push/tests/test_push_api.py +951 -0
- cumulusci/tasks/push/tests/test_push_tasks.py +659 -0
- cumulusci/tasks/release_notes/README.md +63 -0
- cumulusci/tasks/release_notes/__init__.py +0 -0
- cumulusci/tasks/release_notes/exceptions.py +5 -0
- cumulusci/tasks/release_notes/generator.py +137 -0
- cumulusci/tasks/release_notes/parser.py +232 -0
- cumulusci/tasks/release_notes/provider.py +44 -0
- cumulusci/tasks/release_notes/task.py +300 -0
- cumulusci/tasks/release_notes/tests/__init__.py +0 -0
- cumulusci/tasks/release_notes/tests/change_notes/full/example1.md +17 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/1.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/2.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/3.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/single/1.txt +1 -0
- cumulusci/tasks/release_notes/tests/test_generator.py +582 -0
- cumulusci/tasks/release_notes/tests/test_parser.py +867 -0
- cumulusci/tasks/release_notes/tests/test_provider.py +512 -0
- cumulusci/tasks/release_notes/tests/test_task.py +461 -0
- cumulusci/tasks/release_notes/tests/utils.py +153 -0
- cumulusci/tasks/robotframework/__init__.py +3 -0
- cumulusci/tasks/robotframework/debugger/DebugListener.py +100 -0
- cumulusci/tasks/robotframework/debugger/__init__.py +10 -0
- cumulusci/tasks/robotframework/debugger/model.py +87 -0
- cumulusci/tasks/robotframework/debugger/ui.py +259 -0
- cumulusci/tasks/robotframework/libdoc.py +269 -0
- cumulusci/tasks/robotframework/robotframework.py +392 -0
- cumulusci/tasks/robotframework/stylesheet.css +130 -0
- cumulusci/tasks/robotframework/template.html +109 -0
- cumulusci/tasks/robotframework/tests/TestLibrary.py +18 -0
- cumulusci/tasks/robotframework/tests/TestPageObjects.py +31 -0
- cumulusci/tasks/robotframework/tests/TestResource.robot +8 -0
- cumulusci/tasks/robotframework/tests/failing_tests.robot +16 -0
- cumulusci/tasks/robotframework/tests/performance.robot +23 -0
- cumulusci/tasks/robotframework/tests/test_browser_proxies.py +137 -0
- cumulusci/tasks/robotframework/tests/test_debugger.py +360 -0
- cumulusci/tasks/robotframework/tests/test_robot_parallel.py +141 -0
- cumulusci/tasks/robotframework/tests/test_robotframework.py +860 -0
- cumulusci/tasks/salesforce/BaseRetrieveMetadata.py +58 -0
- cumulusci/tasks/salesforce/BaseSalesforceApiTask.py +45 -0
- cumulusci/tasks/salesforce/BaseSalesforceMetadataApiTask.py +18 -0
- cumulusci/tasks/salesforce/BaseSalesforceTask.py +4 -0
- cumulusci/tasks/salesforce/BaseUninstallMetadata.py +41 -0
- cumulusci/tasks/salesforce/CreateCommunity.py +124 -0
- cumulusci/tasks/salesforce/CreatePackage.py +29 -0
- cumulusci/tasks/salesforce/Deploy.py +240 -0
- cumulusci/tasks/salesforce/DeployBundles.py +88 -0
- cumulusci/tasks/salesforce/DescribeMetadataTypes.py +26 -0
- cumulusci/tasks/salesforce/EnsureRecordTypes.py +202 -0
- cumulusci/tasks/salesforce/GetInstalledPackages.py +8 -0
- cumulusci/tasks/salesforce/ListCommunities.py +40 -0
- cumulusci/tasks/salesforce/ListCommunityTemplates.py +19 -0
- cumulusci/tasks/salesforce/PublishCommunity.py +62 -0
- cumulusci/tasks/salesforce/RetrievePackaged.py +41 -0
- cumulusci/tasks/salesforce/RetrieveReportsAndDashboards.py +82 -0
- cumulusci/tasks/salesforce/RetrieveUnpackaged.py +36 -0
- cumulusci/tasks/salesforce/SOQLQuery.py +39 -0
- cumulusci/tasks/salesforce/UninstallLocal.py +15 -0
- cumulusci/tasks/salesforce/UninstallLocalBundles.py +28 -0
- cumulusci/tasks/salesforce/UninstallLocalNamespacedBundles.py +58 -0
- cumulusci/tasks/salesforce/UninstallPackage.py +32 -0
- cumulusci/tasks/salesforce/UninstallPackaged.py +56 -0
- cumulusci/tasks/salesforce/UpdateAdminProfile.py +8 -0
- cumulusci/tasks/salesforce/__init__.py +79 -0
- cumulusci/tasks/salesforce/activate_flow.py +74 -0
- cumulusci/tasks/salesforce/check_components.py +324 -0
- cumulusci/tasks/salesforce/composite.py +142 -0
- cumulusci/tasks/salesforce/create_permission_sets.py +35 -0
- cumulusci/tasks/salesforce/custom_settings.py +134 -0
- cumulusci/tasks/salesforce/custom_settings_wait.py +132 -0
- cumulusci/tasks/salesforce/enable_prediction.py +107 -0
- cumulusci/tasks/salesforce/insert_record.py +40 -0
- cumulusci/tasks/salesforce/install_package_version.py +242 -0
- cumulusci/tasks/salesforce/license_preflights.py +8 -0
- cumulusci/tasks/salesforce/network_member_group.py +178 -0
- cumulusci/tasks/salesforce/nonsourcetracking.py +228 -0
- cumulusci/tasks/salesforce/org_settings.py +193 -0
- cumulusci/tasks/salesforce/package_upload.py +328 -0
- cumulusci/tasks/salesforce/profiles.py +74 -0
- cumulusci/tasks/salesforce/promote_package_version.py +376 -0
- cumulusci/tasks/salesforce/retrieve_profile.py +195 -0
- cumulusci/tasks/salesforce/salesforce_files.py +244 -0
- cumulusci/tasks/salesforce/sourcetracking.py +507 -0
- cumulusci/tasks/salesforce/tests/__init__.py +3 -0
- cumulusci/tasks/salesforce/tests/test_CreateCommunity.py +278 -0
- cumulusci/tasks/salesforce/tests/test_CreatePackage.py +22 -0
- cumulusci/tasks/salesforce/tests/test_Deploy.py +470 -0
- cumulusci/tasks/salesforce/tests/test_DeployBundles.py +76 -0
- cumulusci/tasks/salesforce/tests/test_EnsureRecordTypes.py +345 -0
- cumulusci/tasks/salesforce/tests/test_ListCommunities.py +84 -0
- cumulusci/tasks/salesforce/tests/test_ListCommunityTemplates.py +49 -0
- cumulusci/tasks/salesforce/tests/test_PackageUpload.py +547 -0
- cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py +699 -0
- cumulusci/tasks/salesforce/tests/test_PublishCommunity.py +181 -0
- cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py +24 -0
- cumulusci/tasks/salesforce/tests/test_RetrieveReportsAndDashboards.py +56 -0
- cumulusci/tasks/salesforce/tests/test_RetrieveUnpackaged.py +21 -0
- cumulusci/tasks/salesforce/tests/test_SOQLQuery.py +30 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocal.py +15 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocalBundles.py +19 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocalNamespacedBundles.py +22 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackage.py +19 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackaged.py +66 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackagedIncremental.py +127 -0
- cumulusci/tasks/salesforce/tests/test_activate_flow.py +132 -0
- cumulusci/tasks/salesforce/tests/test_base_tasks.py +110 -0
- cumulusci/tasks/salesforce/tests/test_check_components.py +445 -0
- cumulusci/tasks/salesforce/tests/test_composite.py +250 -0
- cumulusci/tasks/salesforce/tests/test_create_permission_sets.py +41 -0
- cumulusci/tasks/salesforce/tests/test_custom_settings.py +227 -0
- cumulusci/tasks/salesforce/tests/test_custom_settings_wait.py +174 -0
- cumulusci/tasks/salesforce/tests/test_describemetadatatypes.py +18 -0
- cumulusci/tasks/salesforce/tests/test_enable_prediction.py +240 -0
- cumulusci/tasks/salesforce/tests/test_insert_record.py +110 -0
- cumulusci/tasks/salesforce/tests/test_install_package_version.py +464 -0
- cumulusci/tasks/salesforce/tests/test_network_member_group.py +444 -0
- cumulusci/tasks/salesforce/tests/test_nonsourcetracking.py +235 -0
- cumulusci/tasks/salesforce/tests/test_org_settings.py +407 -0
- cumulusci/tasks/salesforce/tests/test_profiles.py +202 -0
- cumulusci/tasks/salesforce/tests/test_retrieve_profile.py +287 -0
- cumulusci/tasks/salesforce/tests/test_salesforce_files.py +228 -0
- cumulusci/tasks/salesforce/tests/test_sourcetracking.py +350 -0
- cumulusci/tasks/salesforce/tests/test_trigger_handlers.py +300 -0
- cumulusci/tasks/salesforce/tests/test_update_dependencies.py +509 -0
- cumulusci/tasks/salesforce/tests/util.py +79 -0
- cumulusci/tasks/salesforce/trigger_handlers.py +119 -0
- cumulusci/tasks/salesforce/uninstall_packaged_incremental.py +136 -0
- cumulusci/tasks/salesforce/update_dependencies.py +290 -0
- cumulusci/tasks/salesforce/update_profile.py +339 -0
- cumulusci/tasks/salesforce/users/permsets.py +227 -0
- cumulusci/tasks/salesforce/users/photos.py +162 -0
- cumulusci/tasks/salesforce/users/tests/photo.mock.txt +1 -0
- cumulusci/tasks/salesforce/users/tests/test_permsets.py +950 -0
- cumulusci/tasks/salesforce/users/tests/test_photos.py +373 -0
- cumulusci/tasks/sample_data/capture_sample_data.py +77 -0
- cumulusci/tasks/sample_data/load_sample_data.py +85 -0
- cumulusci/tasks/sample_data/test_capture_sample_data.py +117 -0
- cumulusci/tasks/sample_data/test_load_sample_data.py +121 -0
- cumulusci/tasks/sfdx.py +83 -0
- cumulusci/tasks/tests/__init__.py +1 -0
- cumulusci/tasks/tests/conftest.py +30 -0
- cumulusci/tasks/tests/test_command.py +129 -0
- cumulusci/tasks/tests/test_connectedapp.py +236 -0
- cumulusci/tasks/tests/test_create_package_version.py +847 -0
- cumulusci/tasks/tests/test_datadictionary.py +1575 -0
- cumulusci/tasks/tests/test_dx_convert_from.py +60 -0
- cumulusci/tasks/tests/test_metadeploy.py +624 -0
- cumulusci/tasks/tests/test_metaxml.py +99 -0
- cumulusci/tasks/tests/test_promote_package_version.py +488 -0
- cumulusci/tasks/tests/test_pushfails.py +96 -0
- cumulusci/tasks/tests/test_salesforce.py +72 -0
- cumulusci/tasks/tests/test_sfdx.py +105 -0
- cumulusci/tasks/tests/test_util.py +207 -0
- cumulusci/tasks/util.py +261 -0
- cumulusci/tasks/vcs/__init__.py +19 -0
- cumulusci/tasks/vcs/commit_status.py +58 -0
- cumulusci/tasks/vcs/create_commit_status.py +37 -0
- cumulusci/tasks/vcs/download_extract.py +199 -0
- cumulusci/tasks/vcs/merge.py +298 -0
- cumulusci/tasks/vcs/publish.py +207 -0
- cumulusci/tasks/vcs/pull_request.py +9 -0
- cumulusci/tasks/vcs/release.py +134 -0
- cumulusci/tasks/vcs/release_report.py +105 -0
- cumulusci/tasks/vcs/tag.py +31 -0
- cumulusci/tasks/vcs/tests/github/test_commit_status.py +196 -0
- cumulusci/tasks/vcs/tests/github/test_download_extract.py +896 -0
- cumulusci/tasks/vcs/tests/github/test_merge.py +1118 -0
- cumulusci/tasks/vcs/tests/github/test_publish.py +823 -0
- cumulusci/tasks/vcs/tests/github/test_pull_request.py +29 -0
- cumulusci/tasks/vcs/tests/github/test_release.py +390 -0
- cumulusci/tasks/vcs/tests/github/test_release_report.py +109 -0
- cumulusci/tasks/vcs/tests/github/test_tag.py +90 -0
- cumulusci/tasks/vlocity/exceptions.py +2 -0
- cumulusci/tasks/vlocity/tests/test_vlocity.py +283 -0
- cumulusci/tasks/vlocity/vlocity.py +342 -0
- cumulusci/tests/__init__.py +1 -0
- cumulusci/tests/cassettes/GET_sobjects_Account_PersonAccount_describe.yaml +18 -0
- cumulusci/tests/cassettes/TestIntegrationInfrastructure.test_integration_tests.yaml +19 -0
- cumulusci/tests/pytest_plugins/pytest_sf_orgconnect.py +307 -0
- cumulusci/tests/pytest_plugins/pytest_sf_vcr.py +275 -0
- cumulusci/tests/pytest_plugins/pytest_sf_vcr_serializer.py +160 -0
- cumulusci/tests/pytest_plugins/pytest_typeguard.py +5 -0
- cumulusci/tests/pytest_plugins/test_vcr_string_compressor.py +49 -0
- cumulusci/tests/pytest_plugins/vcr_string_compressor.py +97 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Account_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Case_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Contact_describe.yaml +4838 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Custom__c_describe.yaml +242 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Event_describe.yaml +19 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Global_describe.yaml +1338 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Lead_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_OpportunityContactRole_describe.yaml +34 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Opportunity_describe.yaml +1261 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Organization.yaml +49 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfoList_xml.tpl +15 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfo_xml.tpl +13 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_insert_xml.tpl +24 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_upsert_xml.tpl +25 -0
- cumulusci/tests/test_entry_points.py +20 -0
- cumulusci/tests/test_integration_infrastructure.py +131 -0
- cumulusci/tests/test_main.py +9 -0
- cumulusci/tests/test_schema.py +32 -0
- cumulusci/tests/test_utils.py +657 -0
- cumulusci/tests/test_vcr_serializer.py +134 -0
- cumulusci/tests/uncompressed_cassette.yaml +83 -0
- cumulusci/tests/util.py +344 -0
- cumulusci/utils/__init__.py +731 -0
- cumulusci/utils/classutils.py +9 -0
- cumulusci/utils/collections.py +32 -0
- cumulusci/utils/deprecation.py +11 -0
- cumulusci/utils/encryption.py +31 -0
- cumulusci/utils/fileutils.py +295 -0
- cumulusci/utils/git.py +142 -0
- cumulusci/utils/http/multi_request.py +214 -0
- cumulusci/utils/http/requests_utils.py +103 -0
- cumulusci/utils/http/tests/cassettes/ManualEditTestCompositeParallelSalesforce.test_http_headers.yaml +32 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_composite_parallel_salesforce.yaml +65 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_errors.yaml +24 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_reference_ids.yaml +49 -0
- cumulusci/utils/http/tests/test_multi_request.py +255 -0
- cumulusci/utils/iterators.py +21 -0
- cumulusci/utils/logging.py +128 -0
- cumulusci/utils/metaprogramming.py +10 -0
- cumulusci/utils/options.py +138 -0
- cumulusci/utils/parallel/queries_in_parallel/run_queries_in_parallel.py +29 -0
- cumulusci/utils/parallel/queries_in_parallel/tests/test_run_queries_in_parallel.py +50 -0
- cumulusci/utils/parallel/task_worker_queues/parallel_worker.py +238 -0
- cumulusci/utils/parallel/task_worker_queues/parallel_worker_queue.py +243 -0
- cumulusci/utils/parallel/task_worker_queues/tests/test_parallel_worker.py +353 -0
- cumulusci/utils/salesforce/count_sobjects.py +46 -0
- cumulusci/utils/salesforce/soql.py +17 -0
- cumulusci/utils/salesforce/tests/cassettes/ManualEdit_TestCountSObjects.test_count_sobjects__network_errors.yaml +23 -0
- cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects__errors.yaml +33 -0
- cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects_simple.yaml +29 -0
- cumulusci/utils/salesforce/tests/test_count_sobjects.py +29 -0
- cumulusci/utils/salesforce/tests/test_soql.py +30 -0
- cumulusci/utils/tests/cassettes/ManualEditTestDescribeOrg.test_minimal_schema.yaml +36 -0
- cumulusci/utils/tests/cassettes/ManualEdit_test_describe_to_sql.yaml +191 -0
- cumulusci/utils/tests/test_fileutils.py +284 -0
- cumulusci/utils/tests/test_git.py +85 -0
- cumulusci/utils/tests/test_logging.py +70 -0
- cumulusci/utils/tests/test_option_parsing.py +188 -0
- cumulusci/utils/tests/test_org_schema.py +691 -0
- cumulusci/utils/tests/test_org_schema_models.py +79 -0
- cumulusci/utils/tests/test_waiting.py +25 -0
- cumulusci/utils/version_strings.py +391 -0
- cumulusci/utils/waiting.py +42 -0
- cumulusci/utils/xml/__init__.py +91 -0
- cumulusci/utils/xml/metadata_tree.py +299 -0
- cumulusci/utils/xml/robot_xml.py +114 -0
- cumulusci/utils/xml/salesforce_encoding.py +100 -0
- cumulusci/utils/xml/test/test_metadata_tree.py +251 -0
- cumulusci/utils/xml/test/test_salesforce_encoding.py +173 -0
- cumulusci/utils/yaml/cumulusci_yml.py +401 -0
- cumulusci/utils/yaml/model_parser.py +156 -0
- cumulusci/utils/yaml/safer_loader.py +74 -0
- cumulusci/utils/yaml/tests/bad_cci.yml +5 -0
- cumulusci/utils/yaml/tests/cassettes/TestCumulusciYml.test_validate_url__with_errors.yaml +20 -0
- cumulusci/utils/yaml/tests/test_cumulusci_yml.py +286 -0
- cumulusci/utils/yaml/tests/test_model_parser.py +175 -0
- cumulusci/utils/yaml/tests/test_safer_loader.py +88 -0
- cumulusci/utils/ziputils.py +61 -0
- cumulusci/vcs/base.py +143 -0
- cumulusci/vcs/bootstrap.py +272 -0
- cumulusci/vcs/github/__init__.py +24 -0
- cumulusci/vcs/github/adapter.py +689 -0
- cumulusci/vcs/github/release_notes/generator.py +219 -0
- cumulusci/vcs/github/release_notes/parser.py +151 -0
- cumulusci/vcs/github/release_notes/provider.py +143 -0
- cumulusci/vcs/github/service.py +569 -0
- cumulusci/vcs/github/tests/test_adapter.py +138 -0
- cumulusci/vcs/github/tests/test_service.py +408 -0
- cumulusci/vcs/models.py +586 -0
- cumulusci/vcs/tests/conftest.py +41 -0
- cumulusci/vcs/tests/dummy_service.py +241 -0
- cumulusci/vcs/tests/test_vcs_base.py +687 -0
- cumulusci/vcs/tests/test_vcs_bootstrap.py +727 -0
- cumulusci/vcs/utils/__init__.py +31 -0
- cumulusci/vcs/vcs_source.py +287 -0
- cumulusci_plus-5.0.0.dist-info/METADATA +145 -0
- cumulusci_plus-5.0.0.dist-info/RECORD +744 -0
- cumulusci_plus-5.0.0.dist-info/WHEEL +4 -0
- cumulusci_plus-5.0.0.dist-info/entry_points.txt +3 -0
- cumulusci_plus-5.0.0.dist-info/licenses/AUTHORS.rst +41 -0
- cumulusci_plus-5.0.0.dist-info/licenses/LICENSE +30 -0
cumulusci/__about__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "5.0.0"
|
cumulusci/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import warnings
|
|
4
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
5
|
+
|
|
6
|
+
# Suppress pkg_resources deprecation warnings from dependencies
|
|
7
|
+
warnings.filterwarnings("ignore", message=".*pkg_resources.*", category=UserWarning)
|
|
8
|
+
|
|
9
|
+
from simple_salesforce import api, bulk
|
|
10
|
+
|
|
11
|
+
__location__ = os.path.dirname(os.path.realpath(__file__))
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
__version__ = version("cumulusci")
|
|
15
|
+
except PackageNotFoundError:
|
|
16
|
+
__version__ = "unknown"
|
|
17
|
+
|
|
18
|
+
if sys.version_info < (3, 8): # pragma: no cover
|
|
19
|
+
raise Exception("CumulusCI requires Python 3.8+.")
|
|
20
|
+
|
|
21
|
+
api.OrderedDict = dict
|
|
22
|
+
bulk.OrderedDict = dict
|
cumulusci/__main__.py
ADDED
|
File without changes
|
cumulusci/cli/cci.py
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import code
|
|
2
|
+
import contextlib
|
|
3
|
+
import pdb
|
|
4
|
+
import runpy
|
|
5
|
+
import sys
|
|
6
|
+
import traceback
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
import requests
|
|
10
|
+
import rich
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.markup import escape
|
|
13
|
+
|
|
14
|
+
import cumulusci
|
|
15
|
+
from cumulusci.core.debug import set_debug_mode
|
|
16
|
+
from cumulusci.core.exceptions import CumulusCIUsageError
|
|
17
|
+
from cumulusci.utils import get_cci_upgrade_command
|
|
18
|
+
from cumulusci.utils.http.requests_utils import init_requests_trust
|
|
19
|
+
from cumulusci.utils.logging import tee_stdout_stderr
|
|
20
|
+
|
|
21
|
+
from .error import error
|
|
22
|
+
from .flow import flow
|
|
23
|
+
from .logger import get_tempfile_logger, init_logger
|
|
24
|
+
from .org import org
|
|
25
|
+
from .plan import plan
|
|
26
|
+
from .project import project
|
|
27
|
+
from .robot import robot
|
|
28
|
+
from .runtime import CliRuntime, pass_runtime
|
|
29
|
+
from .service import service
|
|
30
|
+
from .task import task
|
|
31
|
+
from .utils import (
|
|
32
|
+
check_latest_version,
|
|
33
|
+
get_installed_version,
|
|
34
|
+
get_latest_final_version,
|
|
35
|
+
warn_if_no_long_paths,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
SUGGEST_ERROR_COMMAND = (
|
|
39
|
+
"""Run this command for more information about debugging errors: cci error --help"""
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
USAGE_ERRORS = (CumulusCIUsageError, click.UsageError)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# Root command
|
|
47
|
+
#
|
|
48
|
+
def main(args=None):
|
|
49
|
+
"""Main CumulusCI CLI entry point.
|
|
50
|
+
|
|
51
|
+
This runs as the first step in processing any CLI command.
|
|
52
|
+
|
|
53
|
+
This wraps the `click` library in order to do some initialization and centralized error handling.
|
|
54
|
+
"""
|
|
55
|
+
with contextlib.ExitStack() as stack:
|
|
56
|
+
args = args or sys.argv
|
|
57
|
+
|
|
58
|
+
# (If enabled) set up requests to validate certs using system CA certs instead of certifi
|
|
59
|
+
init_requests_trust()
|
|
60
|
+
|
|
61
|
+
# Check for updates _unless_ we've been asked to output JSON,
|
|
62
|
+
# or if we're going to check anyway as part of the `version` command.
|
|
63
|
+
is_version_command = len(args) > 1 and args[1] == "version"
|
|
64
|
+
if "--json" not in args and not is_version_command:
|
|
65
|
+
check_latest_version()
|
|
66
|
+
|
|
67
|
+
# Only create logfiles for commands that are not `cci error`
|
|
68
|
+
is_error_command = len(args) > 2 and args[1] == "error"
|
|
69
|
+
tempfile_path = None
|
|
70
|
+
if not is_error_command:
|
|
71
|
+
logger, tempfile_path = get_tempfile_logger()
|
|
72
|
+
stack.enter_context(tee_stdout_stderr(args, logger, tempfile_path))
|
|
73
|
+
|
|
74
|
+
debug = "--debug" in args
|
|
75
|
+
if debug:
|
|
76
|
+
args.remove("--debug")
|
|
77
|
+
|
|
78
|
+
with set_debug_mode(debug):
|
|
79
|
+
try:
|
|
80
|
+
runtime = CliRuntime(load_keychain=False)
|
|
81
|
+
except Exception as e:
|
|
82
|
+
handle_exception(e, is_error_command, tempfile_path, debug)
|
|
83
|
+
sys.exit(1)
|
|
84
|
+
|
|
85
|
+
runtime.check_cumulusci_version()
|
|
86
|
+
should_show_stacktraces = runtime.universal_config.cli__show_stacktraces
|
|
87
|
+
|
|
88
|
+
init_logger(debug=debug)
|
|
89
|
+
# Hand CLI processing over to click, but handle exceptions
|
|
90
|
+
try:
|
|
91
|
+
cli(args[1:], standalone_mode=False, obj=runtime)
|
|
92
|
+
except click.Abort: # Keyboard interrupt
|
|
93
|
+
console = Console()
|
|
94
|
+
show_debug_info() if debug else console.print("\n[red bold]Aborted!")
|
|
95
|
+
sys.exit(1)
|
|
96
|
+
except Exception as e:
|
|
97
|
+
if debug:
|
|
98
|
+
show_debug_info()
|
|
99
|
+
else:
|
|
100
|
+
handle_exception(
|
|
101
|
+
e,
|
|
102
|
+
is_error_command,
|
|
103
|
+
tempfile_path,
|
|
104
|
+
should_show_stacktraces,
|
|
105
|
+
)
|
|
106
|
+
sys.exit(1)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def handle_exception(
|
|
110
|
+
error,
|
|
111
|
+
is_error_cmd,
|
|
112
|
+
logfile_path,
|
|
113
|
+
should_show_stacktraces=False,
|
|
114
|
+
):
|
|
115
|
+
"""Displays error of appropriate message back to user, prompts user to investigate further
|
|
116
|
+
with `cci error` commands, and writes the traceback to the latest logfile.
|
|
117
|
+
"""
|
|
118
|
+
error_console = Console(stderr=True)
|
|
119
|
+
if isinstance(error, requests.exceptions.ConnectionError):
|
|
120
|
+
connection_error_message(error_console)
|
|
121
|
+
elif isinstance(error, click.ClickException):
|
|
122
|
+
error_console.print(f"[red bold]Error: {escape(error.format_message())}")
|
|
123
|
+
else:
|
|
124
|
+
# We call str ourselves to make Typeguard shut up.
|
|
125
|
+
error_console.print(f"[red bold]Error: {escape(str(error))}")
|
|
126
|
+
# Only suggest gist command if it wasn't run
|
|
127
|
+
if not is_error_cmd:
|
|
128
|
+
error_console.print(f"[yellow]{SUGGEST_ERROR_COMMAND}")
|
|
129
|
+
|
|
130
|
+
# This is None if we're handling an exception for a `cci error` command.
|
|
131
|
+
if logfile_path:
|
|
132
|
+
with open(logfile_path, "a") as log_file:
|
|
133
|
+
traceback.print_exc(file=log_file) # log stacktrace silently
|
|
134
|
+
|
|
135
|
+
if should_show_stacktraces and not isinstance(error, USAGE_ERRORS):
|
|
136
|
+
error_console.print_exception()
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def connection_error_message(console: Console):
|
|
140
|
+
message = (
|
|
141
|
+
"We encountered an error with your internet connection. "
|
|
142
|
+
"Please check your connection and try the last cci command again."
|
|
143
|
+
)
|
|
144
|
+
console.print(f"[red bold]{message}")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def show_debug_info():
|
|
148
|
+
"""Displays the traceback and opens pdb"""
|
|
149
|
+
traceback.print_exc()
|
|
150
|
+
pdb.post_mortem()
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def show_version_info():
|
|
154
|
+
console = rich.get_console()
|
|
155
|
+
console.print(f"CumulusCI version: {cumulusci.__version__} ({sys.argv[0]})")
|
|
156
|
+
console.print(f"Python version: {sys.version.split()[0]} ({sys.executable})")
|
|
157
|
+
console.print()
|
|
158
|
+
warn_if_no_long_paths(console=console)
|
|
159
|
+
|
|
160
|
+
current_version = get_installed_version()
|
|
161
|
+
latest_version = get_latest_final_version()
|
|
162
|
+
|
|
163
|
+
if not latest_version > current_version:
|
|
164
|
+
console.print("You have the latest version of CumulusCI :sun_behind_cloud:\n")
|
|
165
|
+
display_release_notes_link(str(latest_version))
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
console.print(
|
|
169
|
+
f"[yellow]There is a newer version of CumulusCI available: {str(latest_version)}"
|
|
170
|
+
)
|
|
171
|
+
console.print(f"To upgrade, run `{get_cci_upgrade_command()}`")
|
|
172
|
+
display_release_notes_link(str(latest_version))
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def display_release_notes_link(latest_version: str) -> None:
|
|
176
|
+
"""Provide a link to the latest CumulusCI Release Notes"""
|
|
177
|
+
release_notes_link = (
|
|
178
|
+
f"https://github.com/SFDO-Tooling/CumulusCI/releases/tag/v{latest_version}"
|
|
179
|
+
)
|
|
180
|
+
console = rich.get_console()
|
|
181
|
+
console.print(
|
|
182
|
+
f"See the latest CumulusCI Release Notes: [link={release_notes_link}]{release_notes_link}[/link]"
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def version_info_wrapper(
|
|
187
|
+
ctx: click.Context, param: click.Parameter, value: bool
|
|
188
|
+
) -> None:
|
|
189
|
+
if not value:
|
|
190
|
+
return
|
|
191
|
+
show_version_info()
|
|
192
|
+
ctx.exit()
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@click.group("main", help="")
|
|
196
|
+
@click.option( # based on https://click.palletsprojects.com/en/8.1.x/options/#callbacks-and-eager-options
|
|
197
|
+
"--version",
|
|
198
|
+
is_flag=True,
|
|
199
|
+
expose_value=False,
|
|
200
|
+
is_eager=True,
|
|
201
|
+
help="Show the version and exit.",
|
|
202
|
+
callback=version_info_wrapper,
|
|
203
|
+
)
|
|
204
|
+
def cli():
|
|
205
|
+
"""Top-level `click` command group."""
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@cli.command(name="version", help="Print the current version of CumulusCI")
|
|
209
|
+
def version():
|
|
210
|
+
show_version_info()
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@cli.command(name="shell", help="Drop into a Python shell")
|
|
214
|
+
@click.option("--script", help="Path to a script to run", type=click.Path())
|
|
215
|
+
@click.option("--python", help="Python code to run directly")
|
|
216
|
+
@pass_runtime(require_project=False, require_keychain=True)
|
|
217
|
+
def shell(runtime, script=None, python=None):
|
|
218
|
+
# alias for backwards-compatibility
|
|
219
|
+
variables = {
|
|
220
|
+
"config": runtime,
|
|
221
|
+
"runtime": runtime,
|
|
222
|
+
"project_config": runtime.project_config,
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if script:
|
|
226
|
+
if python:
|
|
227
|
+
raise click.UsageError("Cannot specify both --script and --python")
|
|
228
|
+
runpy.run_path(script, init_globals=variables)
|
|
229
|
+
elif python:
|
|
230
|
+
exec(python, variables)
|
|
231
|
+
else:
|
|
232
|
+
code.interact(local=variables)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# Top Level Groups
|
|
236
|
+
|
|
237
|
+
cli.add_command(error)
|
|
238
|
+
cli.add_command(project)
|
|
239
|
+
cli.add_command(org)
|
|
240
|
+
cli.add_command(service)
|
|
241
|
+
cli.add_command(task)
|
|
242
|
+
cli.add_command(flow)
|
|
243
|
+
cli.add_command(plan)
|
|
244
|
+
cli.add_command(robot)
|
cumulusci/cli/error.py
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
import sys
|
|
3
|
+
import webbrowser
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
import github3
|
|
9
|
+
|
|
10
|
+
import cumulusci
|
|
11
|
+
from cumulusci.cli.utils import warn_if_no_long_paths, win32_long_paths_enabled
|
|
12
|
+
from cumulusci.core.exceptions import CumulusCIException
|
|
13
|
+
from cumulusci.core.github import check_github_scopes, create_gist, get_github_api
|
|
14
|
+
|
|
15
|
+
from .runtime import pass_runtime
|
|
16
|
+
|
|
17
|
+
GIST_404_ERR_MSG = """A 404 error code was returned when trying to create your gist.
|
|
18
|
+
Please ensure that your GitHub personal access token has the 'Create gists' scope."""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@click.group("error", short_help="Get or share information about an error")
|
|
22
|
+
def error():
|
|
23
|
+
"""
|
|
24
|
+
Get or share information about an error
|
|
25
|
+
|
|
26
|
+
If you'd like to dig into an error more yourself,
|
|
27
|
+
you can get the last few lines of context about it
|
|
28
|
+
from `cci error info`.
|
|
29
|
+
|
|
30
|
+
If you'd like to submit it to a developer for conversation,
|
|
31
|
+
you can use the `cci error gist` command. Just make sure
|
|
32
|
+
that your GitHub access token has the 'create gist' scope.
|
|
33
|
+
|
|
34
|
+
If you'd like to regularly see stack traces, set the `show_stacktraces`
|
|
35
|
+
option to `True` in the "cli" section of `~/.cumulusci/cumulusci.yml`, or to
|
|
36
|
+
see a stack-trace (and other debugging information) just once, use the `--debug`
|
|
37
|
+
command line option.
|
|
38
|
+
|
|
39
|
+
For more information on working with errors in CumulusCI visit:
|
|
40
|
+
https://cumulusci.readthedocs.io/en/latest/features.html#working-with-errors
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_logfile_path():
|
|
45
|
+
return Path.home() / ".cumulusci" / "logs" / "cci.log"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@error.command(
|
|
49
|
+
name="info",
|
|
50
|
+
help="Outputs the most recent traceback (if one exists in the most recent log)",
|
|
51
|
+
)
|
|
52
|
+
def error_info():
|
|
53
|
+
warn_if_no_long_paths()
|
|
54
|
+
logfile_path = get_logfile_path()
|
|
55
|
+
if not logfile_path.is_file():
|
|
56
|
+
click.echo(f"No logfile found at: {logfile_path}")
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
traceback = get_traceback(logfile_path.read_text(encoding="utf-8"))
|
|
60
|
+
click.echo(traceback)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_traceback(log_content: str) -> str:
|
|
64
|
+
"""Returns the the traceback in a logfile if it exists."""
|
|
65
|
+
stacktrace_start = "Traceback (most recent call last):"
|
|
66
|
+
if stacktrace_start not in log_content:
|
|
67
|
+
return f"\nNo stacktrace found in: {get_logfile_path()}\n"
|
|
68
|
+
|
|
69
|
+
stacktrace = ""
|
|
70
|
+
for i, line in enumerate(reversed(log_content.split("\n")), 1):
|
|
71
|
+
stacktrace = "\n" + line + stacktrace
|
|
72
|
+
if stacktrace_start in line:
|
|
73
|
+
break
|
|
74
|
+
|
|
75
|
+
return stacktrace
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@error.command(name="gist", help="Creates a GitHub gist from the latest logfile")
|
|
79
|
+
@pass_runtime(require_project=False, require_keychain=True)
|
|
80
|
+
def error_gist(runtime):
|
|
81
|
+
logfile_path = get_logfile_path()
|
|
82
|
+
if logfile_path.is_file():
|
|
83
|
+
log_content = logfile_path.read_text(encoding="utf-8")
|
|
84
|
+
else:
|
|
85
|
+
log_not_found_msg = """No logfile to open at path: {}
|
|
86
|
+
Please ensure you're running this command from the same directory you were experiencing an issue."""
|
|
87
|
+
error_msg = log_not_found_msg.format(logfile_path)
|
|
88
|
+
click.echo(error_msg)
|
|
89
|
+
raise CumulusCIException(error_msg)
|
|
90
|
+
|
|
91
|
+
last_cmd_header = "\n\n\nLast Command Run\n================================\n"
|
|
92
|
+
filename = f"cci_output_{datetime.utcnow()}.txt"
|
|
93
|
+
files = {
|
|
94
|
+
filename: {"content": f"{get_context_info()}{last_cmd_header}{log_content}"}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
gh = runtime.keychain.get_service("github")
|
|
99
|
+
gist = create_gist(
|
|
100
|
+
get_github_api(gh.username, gh.password or gh.token),
|
|
101
|
+
"CumulusCI Error Output",
|
|
102
|
+
files,
|
|
103
|
+
)
|
|
104
|
+
except github3.exceptions.NotFoundError as exc:
|
|
105
|
+
scope_warning = check_github_scopes(exc)
|
|
106
|
+
raise CumulusCIException(GIST_404_ERR_MSG + f"\n\n{scope_warning}")
|
|
107
|
+
except Exception as e:
|
|
108
|
+
raise CumulusCIException(
|
|
109
|
+
f"An error occurred attempting to create your gist:\n{e}"
|
|
110
|
+
)
|
|
111
|
+
else:
|
|
112
|
+
click.echo(f"Gist created: {gist.html_url}")
|
|
113
|
+
webbrowser.open(gist.html_url)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def get_context_info():
|
|
117
|
+
host_info = platform.uname()
|
|
118
|
+
|
|
119
|
+
info = []
|
|
120
|
+
info.append(f"CumulusCI version: {cumulusci.__version__}")
|
|
121
|
+
info.append(f"Python version: {sys.version.split()[0]} ({sys.executable})")
|
|
122
|
+
info.append(f"Environment Info: {host_info.system} / {host_info.machine}")
|
|
123
|
+
if host_info.system == "Windows":
|
|
124
|
+
info.append(f"Windows long path support enabled: {win32_long_paths_enabled()}")
|
|
125
|
+
return "\n".join(info)
|
cumulusci/cli/flow.py
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from cumulusci.core.exceptions import FlowNotFoundError
|
|
9
|
+
from cumulusci.core.utils import format_duration
|
|
10
|
+
from cumulusci.utils import document_flow, flow_ref_title_and_intro
|
|
11
|
+
from cumulusci.utils.yaml.safer_loader import load_yaml_data
|
|
12
|
+
|
|
13
|
+
from .runtime import pass_runtime
|
|
14
|
+
from .ui import CliTable
|
|
15
|
+
from .utils import group_items
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.group("flow", help="Commands for finding and running flows for a project")
|
|
19
|
+
def flow():
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@flow.command(name="doc", help="Exports RST format documentation for all flows")
|
|
24
|
+
@click.option(
|
|
25
|
+
"--project", "project", is_flag=True, help="Include project-specific flows only"
|
|
26
|
+
)
|
|
27
|
+
@pass_runtime(require_project=False, require_keychain=True)
|
|
28
|
+
def flow_doc(runtime, project=False):
|
|
29
|
+
flow_info_path = Path(__file__, "..", "..", "..", "docs", "flows.yml").resolve()
|
|
30
|
+
with open(flow_info_path, "r", encoding="utf-8") as f:
|
|
31
|
+
flow_info = load_yaml_data(f)
|
|
32
|
+
click.echo(flow_ref_title_and_intro(flow_info["intro_blurb"]))
|
|
33
|
+
flow_info_groups = list(flow_info["groups"].keys())
|
|
34
|
+
|
|
35
|
+
universal_flows = runtime.universal_config.list_flows()
|
|
36
|
+
if project:
|
|
37
|
+
flows = [
|
|
38
|
+
flow
|
|
39
|
+
for flow in runtime.project_config.list_flows()
|
|
40
|
+
if flow not in universal_flows
|
|
41
|
+
]
|
|
42
|
+
else:
|
|
43
|
+
flows = universal_flows
|
|
44
|
+
flows_by_group = group_items(flows)
|
|
45
|
+
flow_groups = sorted(
|
|
46
|
+
flows_by_group.keys(),
|
|
47
|
+
key=lambda group: flow_info_groups.index(group)
|
|
48
|
+
if group in flow_info_groups
|
|
49
|
+
else 100,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
for group in flow_groups:
|
|
53
|
+
click.echo(f"{group}\n{'-' * len(group)}")
|
|
54
|
+
if group in flow_info["groups"]:
|
|
55
|
+
click.echo(flow_info["groups"][group]["description"])
|
|
56
|
+
|
|
57
|
+
for flow in sorted(flows_by_group[group]):
|
|
58
|
+
flow_name, flow_description = flow
|
|
59
|
+
try:
|
|
60
|
+
flow_coordinator = runtime.get_flow(flow_name)
|
|
61
|
+
except FlowNotFoundError as e:
|
|
62
|
+
raise click.UsageError(str(e))
|
|
63
|
+
|
|
64
|
+
additional_info = None
|
|
65
|
+
if flow_name in flow_info.get("flows", {}):
|
|
66
|
+
additional_info = flow_info["flows"][flow_name]["rst_text"]
|
|
67
|
+
|
|
68
|
+
click.echo(
|
|
69
|
+
document_flow(
|
|
70
|
+
flow_name,
|
|
71
|
+
flow_description,
|
|
72
|
+
flow_coordinator,
|
|
73
|
+
additional_info=additional_info,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
click.echo("")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@flow.command(name="list", help="List available flows for the current context")
|
|
80
|
+
@click.option("--plain", is_flag=True, help="Print the table using plain ascii.")
|
|
81
|
+
@click.option("--json", "print_json", is_flag=True, help="Print a json string")
|
|
82
|
+
@pass_runtime(require_project=False)
|
|
83
|
+
def flow_list(runtime, plain, print_json):
|
|
84
|
+
plain = plain or runtime.universal_config.cli__plain_output
|
|
85
|
+
flows = runtime.get_available_flows()
|
|
86
|
+
if print_json:
|
|
87
|
+
click.echo(json.dumps(flows))
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
flow_groups = group_items(flows)
|
|
91
|
+
for group, flows in flow_groups.items():
|
|
92
|
+
data = [["Flow", "Description"]]
|
|
93
|
+
data.extend(sorted(flows))
|
|
94
|
+
table = CliTable(
|
|
95
|
+
data,
|
|
96
|
+
group,
|
|
97
|
+
)
|
|
98
|
+
table.echo(plain)
|
|
99
|
+
|
|
100
|
+
click.echo(
|
|
101
|
+
"Use "
|
|
102
|
+
+ click.style("cci flow info <flow_name>", bold=True)
|
|
103
|
+
+ " to get more information about a flow."
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@flow.command(name="info", help="Displays information for a flow")
|
|
108
|
+
@click.argument("flow_name")
|
|
109
|
+
@pass_runtime(require_keychain=True)
|
|
110
|
+
def flow_info(runtime, flow_name):
|
|
111
|
+
try:
|
|
112
|
+
coordinator = runtime.get_flow(flow_name)
|
|
113
|
+
output = coordinator.get_summary(verbose=True)
|
|
114
|
+
click.echo(output)
|
|
115
|
+
except FlowNotFoundError as e:
|
|
116
|
+
raise click.UsageError(str(e))
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@flow.command(name="run", help="Runs a flow")
|
|
120
|
+
@click.argument("flow_name")
|
|
121
|
+
@click.option(
|
|
122
|
+
"--org",
|
|
123
|
+
help="Specify the target org. By default, runs against the current default org",
|
|
124
|
+
)
|
|
125
|
+
@click.option(
|
|
126
|
+
"--delete-org",
|
|
127
|
+
is_flag=True,
|
|
128
|
+
help="If set, deletes the scratch org after the flow completes",
|
|
129
|
+
)
|
|
130
|
+
@click.option(
|
|
131
|
+
"--debug", is_flag=True, help="Drops into pdb, the Python debugger, on an exception"
|
|
132
|
+
)
|
|
133
|
+
@click.option(
|
|
134
|
+
"-o",
|
|
135
|
+
nargs=2,
|
|
136
|
+
multiple=True,
|
|
137
|
+
help="Pass task specific options for the task as '-o taskname__option value'. You can specify more than one option by using -o more than once.",
|
|
138
|
+
)
|
|
139
|
+
@click.option(
|
|
140
|
+
"--no-prompt",
|
|
141
|
+
is_flag=True,
|
|
142
|
+
help="Disables all prompts. Set for non-interactive mode use such as calling from scripts or CI systems",
|
|
143
|
+
)
|
|
144
|
+
@pass_runtime(require_keychain=True)
|
|
145
|
+
def flow_run(runtime, flow_name, org, delete_org, debug, o, no_prompt):
|
|
146
|
+
|
|
147
|
+
# Get necessary configs
|
|
148
|
+
org, org_config = runtime.get_org(org)
|
|
149
|
+
if delete_org and not org_config.scratch:
|
|
150
|
+
raise click.UsageError("--delete-org can only be used with a scratch org")
|
|
151
|
+
|
|
152
|
+
# Parse command line options
|
|
153
|
+
options = defaultdict(dict)
|
|
154
|
+
if o:
|
|
155
|
+
for key, value in o:
|
|
156
|
+
if "__" in key:
|
|
157
|
+
task_name, option_name = key.split("__")
|
|
158
|
+
options[task_name][option_name] = value
|
|
159
|
+
else:
|
|
160
|
+
raise click.UsageError(
|
|
161
|
+
"-o option for flows should contain __ to split task name from option name."
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Create the flow and handle initialization exceptions
|
|
165
|
+
try:
|
|
166
|
+
coordinator = runtime.get_flow(flow_name, options=options)
|
|
167
|
+
start_time = datetime.now()
|
|
168
|
+
coordinator.run(org_config)
|
|
169
|
+
duration = datetime.now() - start_time
|
|
170
|
+
click.echo(f"Ran {flow_name} in {format_duration(duration)}")
|
|
171
|
+
except Exception:
|
|
172
|
+
runtime.alert(f"Flow error: {flow_name}")
|
|
173
|
+
raise
|
|
174
|
+
finally:
|
|
175
|
+
# Delete the scratch org if --delete-org was set
|
|
176
|
+
if delete_org:
|
|
177
|
+
try:
|
|
178
|
+
org_config.delete_org()
|
|
179
|
+
except Exception as e:
|
|
180
|
+
click.echo(
|
|
181
|
+
"Scratch org deletion failed. Ignoring the error below to complete the flow:"
|
|
182
|
+
)
|
|
183
|
+
click.echo(str(e))
|
|
184
|
+
|
|
185
|
+
runtime.alert(f"Flow Complete: {flow_name}")
|
cumulusci/cli/logger.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
""" CLI logger """
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import tempfile
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
from rich.logging import RichHandler
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import colorama
|
|
12
|
+
except ImportError:
|
|
13
|
+
# coloredlogs only installs colorama on Windows
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def init_logger(debug=False):
|
|
18
|
+
"""Initialize the logger"""
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__.split(".")[0])
|
|
21
|
+
for handler in logger.handlers: # pragma: no cover
|
|
22
|
+
logger.removeHandler(handler)
|
|
23
|
+
|
|
24
|
+
if os.name == "nt" and "colorama" in sys.modules: # pragma: no cover
|
|
25
|
+
colorama.init()
|
|
26
|
+
|
|
27
|
+
logger.addHandler(
|
|
28
|
+
RichHandler(
|
|
29
|
+
rich_tracebacks=True,
|
|
30
|
+
show_level=debug,
|
|
31
|
+
show_path=debug,
|
|
32
|
+
tracebacks_show_locals=debug,
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
logger.setLevel(logging.DEBUG)
|
|
36
|
+
logger.propagate = False
|
|
37
|
+
|
|
38
|
+
if debug: # pragma: no cover
|
|
39
|
+
# Referenced from:
|
|
40
|
+
# https://github.com/urllib3/urllib3/blob/cd55f2fe98df4d499ab5c826433ee4995d3f6a60/src/urllib3/__init__.py#L48
|
|
41
|
+
def add_rich_logger(
|
|
42
|
+
module: str, level: int = logging.DEBUG
|
|
43
|
+
) -> logging.StreamHandler:
|
|
44
|
+
"""Retrieve the logger for the given module.
|
|
45
|
+
Remove all handlers from it, and add a single RichHandler."""
|
|
46
|
+
logger = logging.getLogger(module)
|
|
47
|
+
for handler in logger.handlers:
|
|
48
|
+
logger.removeHandler(handler)
|
|
49
|
+
|
|
50
|
+
handler = RichHandler()
|
|
51
|
+
logger.addHandler(handler)
|
|
52
|
+
logger.setLevel(level)
|
|
53
|
+
logger.debug(f"Added rich.logging.RichHandler to logger: {module}")
|
|
54
|
+
return handler
|
|
55
|
+
|
|
56
|
+
# monkey patch urllib3 logger
|
|
57
|
+
requests.packages.urllib3.add_stderr_logger = add_rich_logger
|
|
58
|
+
requests.packages.urllib3.add_stderr_logger("urllib3")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_tempfile_logger():
|
|
62
|
+
"""Creates a logger that writes to a temporary
|
|
63
|
+
logfile. Returns the logger and path to tempfile"""
|
|
64
|
+
logger = logging.getLogger("tempfile_logger")
|
|
65
|
+
file_handle, filepath = tempfile.mkstemp()
|
|
66
|
+
# close the file as it will be opened again by FileHandler
|
|
67
|
+
os.close(file_handle)
|
|
68
|
+
handler = logging.FileHandler(filepath, encoding="utf-8")
|
|
69
|
+
handler.terminator = ""
|
|
70
|
+
logger.addHandler(handler)
|
|
71
|
+
logger.setLevel(logging.DEBUG)
|
|
72
|
+
return logger, filepath
|