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
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
from zipfile import ZipFile
|
|
3
|
+
|
|
4
|
+
from cumulusci.tasks.salesforce.BaseSalesforceMetadataApiTask import (
|
|
5
|
+
BaseSalesforceMetadataApiTask,
|
|
6
|
+
)
|
|
7
|
+
from cumulusci.utils import process_text_in_zipfile, strip_namespace, tokenize_namespace
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BaseRetrieveMetadata(BaseSalesforceMetadataApiTask):
|
|
11
|
+
task_options = {
|
|
12
|
+
"path": {
|
|
13
|
+
"description": "The path to write the retrieved metadata",
|
|
14
|
+
"required": True,
|
|
15
|
+
},
|
|
16
|
+
"namespace_strip": {
|
|
17
|
+
"description": "If set, all namespace prefixes for the namespace specified are stripped from files and filenames"
|
|
18
|
+
},
|
|
19
|
+
"namespace_tokenize": {
|
|
20
|
+
"description": "If set, all namespace prefixes for the namespace specified are replaced with tokens for use with namespace_inject"
|
|
21
|
+
},
|
|
22
|
+
"namespaced_org": {
|
|
23
|
+
"description": "If True, the tokens %%%NAMESPACED_ORG%%% and ___NAMESPACED_ORG___ will get replaced with the namespace. The default is false causing those tokens to get stripped and replaced with an empty string. Set this if deploying to a namespaced scratch org or packaging org."
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
def _run_task(self):
|
|
28
|
+
api = self._get_api()
|
|
29
|
+
src_zip = api()
|
|
30
|
+
self._extract_zip(src_zip)
|
|
31
|
+
self.logger.info(
|
|
32
|
+
"Extracted retrieved metadata into {}".format(self.options["path"])
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def _process_namespace(self, src_zip):
|
|
36
|
+
if self.options.get("namespace_tokenize"):
|
|
37
|
+
src_zip = process_text_in_zipfile(
|
|
38
|
+
src_zip,
|
|
39
|
+
functools.partial(
|
|
40
|
+
tokenize_namespace,
|
|
41
|
+
namespace=self.options["namespace_tokenize"],
|
|
42
|
+
logger=self.logger,
|
|
43
|
+
),
|
|
44
|
+
)
|
|
45
|
+
if self.options.get("namespace_strip"):
|
|
46
|
+
src_zip = process_text_in_zipfile(
|
|
47
|
+
src_zip,
|
|
48
|
+
functools.partial(
|
|
49
|
+
strip_namespace,
|
|
50
|
+
namespace=self.options["namespace_strip"],
|
|
51
|
+
logger=self.logger,
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
return src_zip
|
|
55
|
+
|
|
56
|
+
def _extract_zip(self, src_zip: ZipFile):
|
|
57
|
+
src_zip = self._process_namespace(src_zip)
|
|
58
|
+
src_zip.extractall(self.options["path"])
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from salesforce_bulk import SalesforceBulk
|
|
2
|
+
|
|
3
|
+
from cumulusci.core.exceptions import ConfigError
|
|
4
|
+
from cumulusci.core.tasks import BaseSalesforceTask
|
|
5
|
+
from cumulusci.salesforce_api.utils import get_simple_salesforce_connection
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BaseSalesforceApiTask(BaseSalesforceTask):
|
|
9
|
+
name = "BaseSalesforceApiTask"
|
|
10
|
+
api_version = None
|
|
11
|
+
|
|
12
|
+
def _init_task(self):
|
|
13
|
+
super()._init_task()
|
|
14
|
+
self.sf = self._init_api()
|
|
15
|
+
self.bulk = self._init_bulk()
|
|
16
|
+
self.tooling = self._init_api("tooling")
|
|
17
|
+
self._init_class()
|
|
18
|
+
|
|
19
|
+
def _init_api(self, base_url=None):
|
|
20
|
+
rv = get_simple_salesforce_connection(
|
|
21
|
+
self.project_config,
|
|
22
|
+
self.org_config,
|
|
23
|
+
api_version=self.api_version,
|
|
24
|
+
base_url=base_url,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
return rv
|
|
28
|
+
|
|
29
|
+
def _init_bulk(self):
|
|
30
|
+
version = self.api_version or self.project_config.project__package__api_version
|
|
31
|
+
if not version:
|
|
32
|
+
raise ConfigError("Cannot find Salesforce version")
|
|
33
|
+
return SalesforceBulk(
|
|
34
|
+
host=self.org_config.instance_url.replace("https://", "").rstrip("/"),
|
|
35
|
+
sessionId=self.org_config.access_token,
|
|
36
|
+
API_version=version,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def _init_class(self):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
def _get_tooling_object(self, obj_name):
|
|
43
|
+
obj = getattr(self.tooling, obj_name)
|
|
44
|
+
obj.base_url = obj.base_url.replace("/sobjects/", "/tooling/sobjects/")
|
|
45
|
+
return obj
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from cumulusci.tasks.salesforce import BaseSalesforceTask
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BaseSalesforceMetadataApiTask(BaseSalesforceTask):
|
|
5
|
+
api_class = None
|
|
6
|
+
name = "BaseSalesforceMetadataApiTask"
|
|
7
|
+
|
|
8
|
+
def _get_api(self):
|
|
9
|
+
return self.api_class(self)
|
|
10
|
+
|
|
11
|
+
def _run_task(self):
|
|
12
|
+
api = self._get_api()
|
|
13
|
+
result = None
|
|
14
|
+
if api:
|
|
15
|
+
result = api()
|
|
16
|
+
self.org_config.reset_installed_packages()
|
|
17
|
+
self.return_values = result
|
|
18
|
+
return result
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from cumulusci.core.utils import process_bool_arg
|
|
2
|
+
from cumulusci.salesforce_api.package_zip import DestructiveChangesZipBuilder
|
|
3
|
+
from cumulusci.tasks.salesforce import Deploy
|
|
4
|
+
|
|
5
|
+
uninstall_task_options = Deploy.task_options.copy()
|
|
6
|
+
uninstall_task_options["purge_on_delete"] = {
|
|
7
|
+
"description": "Sets the purgeOnDelete option for the deployment. Defaults to True"
|
|
8
|
+
}
|
|
9
|
+
uninstall_task_options["dry_run"] = {
|
|
10
|
+
"description": "Perform a dry run of the operation without actually deleting any components, and display the components that would be deleted."
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BaseUninstallMetadata(Deploy):
|
|
15
|
+
task_options = uninstall_task_options
|
|
16
|
+
|
|
17
|
+
def _init_options(self, kwargs):
|
|
18
|
+
super(BaseUninstallMetadata, self)._init_options(kwargs)
|
|
19
|
+
self.options["purge_on_delete"] = process_bool_arg(
|
|
20
|
+
self.options.get("purge_on_delete", True)
|
|
21
|
+
)
|
|
22
|
+
self.options["dry_run"] = process_bool_arg(self.options.get("dry_run", False))
|
|
23
|
+
|
|
24
|
+
def _get_api(self, path=None):
|
|
25
|
+
destructive_changes = self._get_destructive_changes(path=path)
|
|
26
|
+
if not destructive_changes:
|
|
27
|
+
return
|
|
28
|
+
if self.options["dry_run"]:
|
|
29
|
+
self.logger.info(
|
|
30
|
+
"Performing uninstall dry run. This destructive deployment was created:"
|
|
31
|
+
)
|
|
32
|
+
self.logger.info(destructive_changes)
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
package_zip = DestructiveChangesZipBuilder(
|
|
36
|
+
destructive_changes, self.project_config.project__package__api_version
|
|
37
|
+
)
|
|
38
|
+
api = self.api_class(
|
|
39
|
+
self, package_zip(), purge_on_delete=self.options["purge_on_delete"]
|
|
40
|
+
)
|
|
41
|
+
return api
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
from simple_salesforce.exceptions import SalesforceMalformedRequest
|
|
5
|
+
|
|
6
|
+
from cumulusci.core.exceptions import CumulusCIException, SalesforceException
|
|
7
|
+
from cumulusci.core.utils import process_bool_arg
|
|
8
|
+
from cumulusci.tasks.salesforce import BaseSalesforceApiTask
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CreateCommunity(BaseSalesforceApiTask):
|
|
12
|
+
COMMUNITY_EXISTS_ERROR_MSG = "Enter a different name. That one already exists."
|
|
13
|
+
api_version = "48.0"
|
|
14
|
+
task_docs = """
|
|
15
|
+
Create a Salesforce Community via the Connect API.
|
|
16
|
+
|
|
17
|
+
Specify the `template` "VF Template" for Visualforce Tabs community,
|
|
18
|
+
or the name for a specific desired template
|
|
19
|
+
"""
|
|
20
|
+
task_options = {
|
|
21
|
+
"template": {
|
|
22
|
+
"description": "Name of the template for the community.",
|
|
23
|
+
"required": True,
|
|
24
|
+
},
|
|
25
|
+
"name": {"description": "Name of the community.", "required": True},
|
|
26
|
+
"description": {
|
|
27
|
+
"description": "Description of the community.",
|
|
28
|
+
"required": False,
|
|
29
|
+
},
|
|
30
|
+
"url_path_prefix": {
|
|
31
|
+
"description": "URL prefix for the community.",
|
|
32
|
+
"required": False,
|
|
33
|
+
},
|
|
34
|
+
"retries": {
|
|
35
|
+
"description": "Number of times to retry community creation request"
|
|
36
|
+
},
|
|
37
|
+
"timeout": {
|
|
38
|
+
"description": "Time to wait, in seconds, for the community to be created"
|
|
39
|
+
},
|
|
40
|
+
"skip_existing": {
|
|
41
|
+
"description": "If True, an existing community with the "
|
|
42
|
+
"same name will not raise an exception."
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
def _init_options(self, kwargs):
|
|
47
|
+
super(CreateCommunity, self)._init_options(kwargs)
|
|
48
|
+
self.options["retries"] = int(self.options.get("retries", 6))
|
|
49
|
+
self.options["timeout"] = int(self.options.get("timeout", 300))
|
|
50
|
+
self.options["skip_existing"] = process_bool_arg(
|
|
51
|
+
self.options.get("skip_existing", False)
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def _run_task(self):
|
|
55
|
+
community = self._get_community()
|
|
56
|
+
if community is not None:
|
|
57
|
+
error_msg = f'A community named "{self.options["name"]}" already exists.'
|
|
58
|
+
if self.options["skip_existing"]:
|
|
59
|
+
self.logger.info(error_msg)
|
|
60
|
+
return
|
|
61
|
+
raise CumulusCIException(error_msg)
|
|
62
|
+
|
|
63
|
+
self.logger.info('Creating community "{}"'.format(self.options["name"]))
|
|
64
|
+
tries = 0
|
|
65
|
+
while True:
|
|
66
|
+
tries += 1
|
|
67
|
+
try:
|
|
68
|
+
self._create_community()
|
|
69
|
+
except Exception as e:
|
|
70
|
+
if tries > self.options["retries"]:
|
|
71
|
+
raise
|
|
72
|
+
else:
|
|
73
|
+
self.logger.warning(str(e))
|
|
74
|
+
self.logger.info("Retrying community creation request")
|
|
75
|
+
self.poll_interval_s = 1
|
|
76
|
+
else:
|
|
77
|
+
break # pragma: no cover
|
|
78
|
+
|
|
79
|
+
def _create_community(self):
|
|
80
|
+
payload = {
|
|
81
|
+
"name": self.options["name"],
|
|
82
|
+
"description": self.options.get("description") or "",
|
|
83
|
+
"templateName": self.options["template"],
|
|
84
|
+
"urlPathPrefix": self.options.get("url_path_prefix") or "",
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
self.logger.info("Sending request to create Community")
|
|
88
|
+
try:
|
|
89
|
+
self.sf.restful(
|
|
90
|
+
"connect/communities", method="POST", data=json.dumps(payload)
|
|
91
|
+
)
|
|
92
|
+
except SalesforceMalformedRequest as e:
|
|
93
|
+
if CreateCommunity.COMMUNITY_EXISTS_ERROR_MSG in str(e):
|
|
94
|
+
# We can end up here if the previous try timed out
|
|
95
|
+
# but the community finished creating before we tried again.
|
|
96
|
+
community = self._get_community()
|
|
97
|
+
self.poll_complete = True
|
|
98
|
+
self.logger.info("Community {} created".format(community["id"]))
|
|
99
|
+
return
|
|
100
|
+
else:
|
|
101
|
+
raise
|
|
102
|
+
|
|
103
|
+
# Wait for the community to be created
|
|
104
|
+
self.time_start = datetime.now()
|
|
105
|
+
self._poll()
|
|
106
|
+
|
|
107
|
+
def _poll_action(self):
|
|
108
|
+
elapsed = datetime.now() - self.time_start
|
|
109
|
+
if elapsed.total_seconds() > self.options["timeout"]:
|
|
110
|
+
raise SalesforceException(
|
|
111
|
+
"Community creation not finished after {timeout} seconds".format(
|
|
112
|
+
**self.options
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
community = self._get_community()
|
|
117
|
+
if community is not None:
|
|
118
|
+
self.poll_complete = True
|
|
119
|
+
self.logger.info("Community {} created".format(community["id"]))
|
|
120
|
+
|
|
121
|
+
def _get_community(self):
|
|
122
|
+
community_list = self.sf.restful("connect/communities")["communities"]
|
|
123
|
+
communities = {c["name"].lower().upper(): c for c in community_list}
|
|
124
|
+
return communities.get(self.options["name"].lower().upper())
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from cumulusci.salesforce_api.package_zip import CreatePackageZipBuilder
|
|
2
|
+
from cumulusci.tasks.salesforce import Deploy
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CreatePackage(Deploy):
|
|
6
|
+
task_options = {
|
|
7
|
+
"package": {
|
|
8
|
+
"description": "The name of the package to create. Defaults to project__package__name",
|
|
9
|
+
"required": True,
|
|
10
|
+
},
|
|
11
|
+
"api_version": {
|
|
12
|
+
"description": "The api version to use when creating the package. Defaults to project__package__api_version",
|
|
13
|
+
"required": True,
|
|
14
|
+
},
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def _init_options(self, kwargs):
|
|
18
|
+
super(CreatePackage, self)._init_options(kwargs)
|
|
19
|
+
if "package" not in self.options:
|
|
20
|
+
self.options["package"] = self.project_config.project__package__name
|
|
21
|
+
if "api_version" not in self.options:
|
|
22
|
+
self.options[
|
|
23
|
+
"api_version"
|
|
24
|
+
] = self.project_config.project__package__api_version
|
|
25
|
+
|
|
26
|
+
def _get_package_zip(self, path=None):
|
|
27
|
+
return CreatePackageZipBuilder(
|
|
28
|
+
self.options["package"], self.options["api_version"]
|
|
29
|
+
).as_base64()
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
from typing import List, Optional, Union
|
|
3
|
+
|
|
4
|
+
from defusedxml.minidom import parseString
|
|
5
|
+
from pydantic import ValidationError
|
|
6
|
+
|
|
7
|
+
from cumulusci.cli.ui import CliTable
|
|
8
|
+
from cumulusci.core.dependencies.utils import TaskContext
|
|
9
|
+
from cumulusci.core.exceptions import TaskOptionsError
|
|
10
|
+
from cumulusci.core.sfdx import convert_sfdx_source
|
|
11
|
+
from cumulusci.core.source_transforms.transforms import (
|
|
12
|
+
SourceTransform,
|
|
13
|
+
SourceTransformList,
|
|
14
|
+
)
|
|
15
|
+
from cumulusci.core.utils import process_bool_arg, process_list_arg, determine_managed_mode
|
|
16
|
+
from cumulusci.salesforce_api.metadata import ApiDeploy, ApiRetrieveUnpackaged
|
|
17
|
+
from cumulusci.salesforce_api.package_zip import MetadataPackageZipBuilder
|
|
18
|
+
from cumulusci.salesforce_api.rest_deploy import RestDeploy
|
|
19
|
+
from cumulusci.tasks.metadata.package import process_common_components
|
|
20
|
+
from cumulusci.tasks.salesforce.BaseSalesforceMetadataApiTask import (
|
|
21
|
+
BaseSalesforceMetadataApiTask,
|
|
22
|
+
)
|
|
23
|
+
from cumulusci.utils.xml import metadata_tree
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Deploy(BaseSalesforceMetadataApiTask):
|
|
27
|
+
api_class = ApiDeploy
|
|
28
|
+
api_retrieve_unpackaged = ApiRetrieveUnpackaged
|
|
29
|
+
task_options = {
|
|
30
|
+
"path": {
|
|
31
|
+
"description": "The path to the metadata source to be deployed",
|
|
32
|
+
"required": True,
|
|
33
|
+
},
|
|
34
|
+
"unmanaged": {
|
|
35
|
+
"description": "If True, changes namespace_inject to replace tokens with a blank string"
|
|
36
|
+
},
|
|
37
|
+
"namespace_inject": {
|
|
38
|
+
"description": "If set, the namespace tokens in files and filenames are replaced with the namespace's prefix"
|
|
39
|
+
},
|
|
40
|
+
"namespace_strip": {
|
|
41
|
+
"description": "If set, all namespace prefixes for the namespace specified are stripped from files and filenames"
|
|
42
|
+
},
|
|
43
|
+
"check_only": {
|
|
44
|
+
"description": "If True, performs a test deployment (validation) of components without saving the components in the target org"
|
|
45
|
+
},
|
|
46
|
+
"collision_check": {
|
|
47
|
+
"description": "If True, performs a collision check with metadata already present in the target org"
|
|
48
|
+
},
|
|
49
|
+
"test_level": {
|
|
50
|
+
"description": "Specifies which tests are run as part of a deployment. Valid values: NoTestRun, RunLocalTests, RunAllTestsInOrg, RunSpecifiedTests."
|
|
51
|
+
},
|
|
52
|
+
"specified_tests": {
|
|
53
|
+
"description": "Comma-separated list of test classes to run upon deployment. Applies only with test_level set to RunSpecifiedTests."
|
|
54
|
+
},
|
|
55
|
+
"static_resource_path": {
|
|
56
|
+
"description": "The path where decompressed static resources are stored. Any subdirectories found will be zipped and added to the staticresources directory of the build."
|
|
57
|
+
},
|
|
58
|
+
"namespaced_org": {
|
|
59
|
+
"description": "If True, the tokens %%%NAMESPACED_ORG%%% and ___NAMESPACED_ORG___ will get replaced with the namespace. The default is false causing those tokens to get stripped and replaced with an empty string. Set this if deploying to a namespaced scratch org or packaging org."
|
|
60
|
+
},
|
|
61
|
+
"clean_meta_xml": {
|
|
62
|
+
"description": "Defaults to True which strips the <packageVersions/> element from all meta.xml files. The packageVersion element gets added automatically by the target org and is set to whatever version is installed in the org. To disable this, set this option to False"
|
|
63
|
+
},
|
|
64
|
+
"transforms": {
|
|
65
|
+
"description": "Apply source transforms before deploying. See the CumulusCI documentation for details on how to specify transforms."
|
|
66
|
+
},
|
|
67
|
+
"rest_deploy": {"description": "If True, deploy metadata using REST API"},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
namespaces = {"sf": "http://soap.sforce.com/2006/04/metadata"}
|
|
71
|
+
|
|
72
|
+
transforms: List[SourceTransform] = []
|
|
73
|
+
|
|
74
|
+
def _init_options(self, kwargs):
|
|
75
|
+
super(Deploy, self)._init_options(kwargs)
|
|
76
|
+
|
|
77
|
+
self.check_only = process_bool_arg(self.options.get("check_only", False))
|
|
78
|
+
self.test_level = self.options.get("test_level")
|
|
79
|
+
if self.test_level and self.test_level not in [
|
|
80
|
+
"NoTestRun",
|
|
81
|
+
"RunLocalTests",
|
|
82
|
+
"RunAllTestsInOrg",
|
|
83
|
+
"RunSpecifiedTests",
|
|
84
|
+
]:
|
|
85
|
+
raise TaskOptionsError(
|
|
86
|
+
f"Specified test run level {self.test_level} is not valid."
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
self.specified_tests = process_list_arg(self.options.get("specified_tests", []))
|
|
90
|
+
|
|
91
|
+
if bool(self.specified_tests) != (self.test_level == "RunSpecifiedTests"):
|
|
92
|
+
raise TaskOptionsError(
|
|
93
|
+
"The specified_tests option and test_level RunSpecifiedTests must be used together."
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
self.options["namespace_inject"] = (
|
|
97
|
+
self.options.get("namespace_inject")
|
|
98
|
+
or self.project_config.project__package__namespace
|
|
99
|
+
)
|
|
100
|
+
if "collision_check" not in self.options:
|
|
101
|
+
self.options["collision_check"] = False
|
|
102
|
+
|
|
103
|
+
if "transforms" in self.options:
|
|
104
|
+
try:
|
|
105
|
+
self.transforms = SourceTransformList.parse_obj(
|
|
106
|
+
self.options["transforms"]
|
|
107
|
+
).as_transforms()
|
|
108
|
+
except ValidationError as e:
|
|
109
|
+
raise TaskOptionsError(
|
|
110
|
+
"The transform spec is not valid. See CumulusCI documentation for details of how to specify transforms. "
|
|
111
|
+
f"The validation error was {str(e)}"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Set class variable to true if rest_deploy is set to True
|
|
115
|
+
self.rest_deploy = process_bool_arg(self.options.get("rest_deploy", False))
|
|
116
|
+
|
|
117
|
+
def _get_api(self, path=None):
|
|
118
|
+
if not path:
|
|
119
|
+
path = self.options.get("path")
|
|
120
|
+
|
|
121
|
+
package_zip = self._get_package_zip(path)
|
|
122
|
+
|
|
123
|
+
if isinstance(package_zip, dict):
|
|
124
|
+
self.logger.warning(
|
|
125
|
+
"Deploy getting aborted due to collision of following components"
|
|
126
|
+
)
|
|
127
|
+
table_header_row = ["Type", "Component API Name"]
|
|
128
|
+
table_data = [table_header_row]
|
|
129
|
+
for type in package_zip.keys():
|
|
130
|
+
for component_name in package_zip[type]:
|
|
131
|
+
table_data.append([type, component_name])
|
|
132
|
+
table = CliTable(
|
|
133
|
+
table_data,
|
|
134
|
+
)
|
|
135
|
+
table.echo()
|
|
136
|
+
return None
|
|
137
|
+
elif package_zip is not None:
|
|
138
|
+
self.logger.info("Payload size: {} bytes".format(len(package_zip)))
|
|
139
|
+
else:
|
|
140
|
+
self.logger.warning("Deployment package is empty; skipping deployment.")
|
|
141
|
+
return
|
|
142
|
+
|
|
143
|
+
# If rest_deploy param is set, update api_class to be RestDeploy
|
|
144
|
+
if self.rest_deploy:
|
|
145
|
+
self.api_class = RestDeploy
|
|
146
|
+
|
|
147
|
+
return self.api_class(
|
|
148
|
+
self,
|
|
149
|
+
package_zip,
|
|
150
|
+
purge_on_delete=False,
|
|
151
|
+
check_only=self.check_only,
|
|
152
|
+
test_level=self.test_level,
|
|
153
|
+
run_tests=self.specified_tests,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def _has_namespaced_package(self, ns: Optional[str]) -> bool:
|
|
157
|
+
return determine_managed_mode(
|
|
158
|
+
self.options, self.project_config, self.org_config
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def _is_namespaced_org(self, ns: Optional[str]) -> bool:
|
|
162
|
+
if "namespaced_org" in self.options:
|
|
163
|
+
return process_bool_arg(self.options.get("namespaced_org", False))
|
|
164
|
+
return bool(ns) and ns == self.org_config.namespace
|
|
165
|
+
|
|
166
|
+
def _create_api_object(self, package_xml, api_version):
|
|
167
|
+
api_retrieve_unpackaged_object = self.api_retrieve_unpackaged(
|
|
168
|
+
self, package_xml, api_version
|
|
169
|
+
)
|
|
170
|
+
return api_retrieve_unpackaged_object
|
|
171
|
+
|
|
172
|
+
def _collision_check(self, src_path):
|
|
173
|
+
is_collision = False
|
|
174
|
+
package_xml = open(f"{src_path}/package.xml", "r")
|
|
175
|
+
source_xml_tree = metadata_tree.parse(f"{src_path}/package.xml")
|
|
176
|
+
|
|
177
|
+
api_retrieve_unpackaged_response = self._create_api_object(
|
|
178
|
+
package_xml.read(), source_xml_tree.version.text
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
xml_map = metadata_tree.parse_package_xml_types("name", source_xml_tree)
|
|
182
|
+
|
|
183
|
+
messages = parseString(
|
|
184
|
+
api_retrieve_unpackaged_response._get_response().content
|
|
185
|
+
).getElementsByTagName("messages")
|
|
186
|
+
|
|
187
|
+
process_common_components(messages, xml_map)
|
|
188
|
+
|
|
189
|
+
for type, api_names in xml_map.items():
|
|
190
|
+
if len(api_names) != 0:
|
|
191
|
+
is_collision = True
|
|
192
|
+
break
|
|
193
|
+
|
|
194
|
+
return is_collision, xml_map
|
|
195
|
+
|
|
196
|
+
def _get_package_zip(self, path) -> Union[str, dict, None]:
|
|
197
|
+
assert path, f"Path should be specified for {self.__class__.name}"
|
|
198
|
+
if not pathlib.Path(path).exists():
|
|
199
|
+
self.logger.warning(f"{path} not found.")
|
|
200
|
+
return
|
|
201
|
+
namespace = self.options["namespace_inject"]
|
|
202
|
+
options = {
|
|
203
|
+
**self.options,
|
|
204
|
+
"clean_meta_xml": process_bool_arg(
|
|
205
|
+
self.options.get("clean_meta_xml", True)
|
|
206
|
+
),
|
|
207
|
+
"namespace_inject": namespace,
|
|
208
|
+
"unmanaged": not self._has_namespaced_package(namespace),
|
|
209
|
+
"namespaced_org": self._is_namespaced_org(namespace),
|
|
210
|
+
}
|
|
211
|
+
package_zip = None
|
|
212
|
+
|
|
213
|
+
with convert_sfdx_source(path, None, self.logger) as src_path:
|
|
214
|
+
##############
|
|
215
|
+
is_collision = False
|
|
216
|
+
if "collision_check" in options and options["collision_check"]:
|
|
217
|
+
is_collision, xml_map = self._collision_check(src_path)
|
|
218
|
+
#############
|
|
219
|
+
if not is_collision:
|
|
220
|
+
context = TaskContext(self.org_config, self.project_config, self.logger)
|
|
221
|
+
package_zip = MetadataPackageZipBuilder(
|
|
222
|
+
path=src_path,
|
|
223
|
+
context=context,
|
|
224
|
+
options=options,
|
|
225
|
+
transforms=self.transforms,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
# If the package is empty, do nothing.
|
|
229
|
+
if not package_zip.zf.namelist():
|
|
230
|
+
return
|
|
231
|
+
return package_zip.as_base64()
|
|
232
|
+
else:
|
|
233
|
+
return xml_map
|
|
234
|
+
|
|
235
|
+
def freeze(self, step):
|
|
236
|
+
steps = super().freeze(step)
|
|
237
|
+
for step in steps:
|
|
238
|
+
if step["kind"] == "other":
|
|
239
|
+
step["kind"] = "metadata"
|
|
240
|
+
return steps
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from cumulusci.tasks.salesforce import Deploy
|
|
5
|
+
|
|
6
|
+
deploy_options = copy.deepcopy(Deploy.task_options)
|
|
7
|
+
deploy_options["path"][
|
|
8
|
+
"description"
|
|
9
|
+
] = "The path to the parent directory containing the metadata bundles directories"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DeployBundles(Deploy):
|
|
13
|
+
task_options = deploy_options
|
|
14
|
+
|
|
15
|
+
def _run_task(self):
|
|
16
|
+
path = self.options["path"]
|
|
17
|
+
pwd = os.getcwd()
|
|
18
|
+
|
|
19
|
+
path = os.path.join(pwd, path)
|
|
20
|
+
|
|
21
|
+
self.logger.info("Deploying all metadata bundles in path {}".format(path))
|
|
22
|
+
|
|
23
|
+
if not os.path.isdir(path):
|
|
24
|
+
self.logger.warning("Path {} not found, skipping".format(path))
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
for item in sorted(os.listdir(path)):
|
|
28
|
+
item_path = os.path.join(path, item)
|
|
29
|
+
if not os.path.isdir(item_path):
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
self.logger.info(
|
|
33
|
+
"Deploying bundle: {}/{}".format(self.options["path"], item)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
self._deploy_bundle(item_path)
|
|
37
|
+
|
|
38
|
+
def _deploy_bundle(self, path):
|
|
39
|
+
api = self._get_api(path)
|
|
40
|
+
return api()
|
|
41
|
+
|
|
42
|
+
def freeze(self, step):
|
|
43
|
+
ui_options = self.task_config.config.get("ui_options", {})
|
|
44
|
+
path = self.options["path"]
|
|
45
|
+
if not os.path.isdir(path):
|
|
46
|
+
return []
|
|
47
|
+
steps = []
|
|
48
|
+
for i, item in enumerate(sorted(os.listdir(path)), 1):
|
|
49
|
+
if not os.path.isdir(os.path.join(path, item)):
|
|
50
|
+
continue
|
|
51
|
+
name = os.path.basename(item)
|
|
52
|
+
subpath = os.path.relpath(
|
|
53
|
+
os.path.join(os.path.realpath(path), item),
|
|
54
|
+
os.path.realpath(self.project_config.repo_root),
|
|
55
|
+
).replace(os.sep, "/")
|
|
56
|
+
|
|
57
|
+
# TODO: copying the options for this task
|
|
58
|
+
# to freeze a different task is not ideal.
|
|
59
|
+
dependency = self.options.copy()
|
|
60
|
+
dependency.pop("path")
|
|
61
|
+
dependency.update(
|
|
62
|
+
{
|
|
63
|
+
"github": self.project_config.repo_url,
|
|
64
|
+
"ref": self.project_config.repo_commit,
|
|
65
|
+
"subfolder": subpath,
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
task_config = {
|
|
69
|
+
"options": {"dependencies": [dependency]},
|
|
70
|
+
"checks": self.task_config.checks or [],
|
|
71
|
+
}
|
|
72
|
+
ui_step = {
|
|
73
|
+
"name": "Deploy {}".format(subpath),
|
|
74
|
+
"kind": "metadata",
|
|
75
|
+
"is_required": True,
|
|
76
|
+
}
|
|
77
|
+
ui_step.update(ui_options.get(name, {}))
|
|
78
|
+
ui_step.update(
|
|
79
|
+
{
|
|
80
|
+
"path": "{}.{}".format(step.path, name),
|
|
81
|
+
"step_num": "{}.{}".format(step.step_num, i),
|
|
82
|
+
"task_class": "cumulusci.tasks.salesforce.UpdateDependencies",
|
|
83
|
+
"task_config": task_config,
|
|
84
|
+
"source": step.project_config.source.frozenspec,
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
steps.append(ui_step)
|
|
88
|
+
return steps
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from cumulusci.salesforce_api.metadata import ApiListMetadataTypes
|
|
2
|
+
from cumulusci.tasks.salesforce import BaseRetrieveMetadata
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DescribeMetadataTypes(BaseRetrieveMetadata):
|
|
6
|
+
api_class = ApiListMetadataTypes
|
|
7
|
+
task_options = {
|
|
8
|
+
"api_version": {
|
|
9
|
+
"description": "Override the API version used to list metadatatypes"
|
|
10
|
+
},
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def _init_options(self, kwargs):
|
|
14
|
+
super(DescribeMetadataTypes, self)._init_options(kwargs)
|
|
15
|
+
if "api_version" not in self.options:
|
|
16
|
+
self.options[
|
|
17
|
+
"api_version"
|
|
18
|
+
] = self.project_config.project__package__api_version
|
|
19
|
+
|
|
20
|
+
def _get_api(self):
|
|
21
|
+
return self.api_class(self, self.options.get("api_version"))
|
|
22
|
+
|
|
23
|
+
def _run_task(self):
|
|
24
|
+
api_object = self._get_api()
|
|
25
|
+
self.return_values = api_object()
|
|
26
|
+
return self.return_values
|