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,376 @@
|
|
|
1
|
+
from typing import Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from simple_salesforce.exceptions import SalesforceMalformedRequest
|
|
4
|
+
|
|
5
|
+
from cumulusci.core.config.util import get_devhub_config
|
|
6
|
+
from cumulusci.core.dependencies.dependencies import PackageVersionIdDependency
|
|
7
|
+
from cumulusci.core.exceptions import CumulusCIException, TaskOptionsError
|
|
8
|
+
from cumulusci.salesforce_api.utils import get_simple_salesforce_connection
|
|
9
|
+
from cumulusci.tasks.create_package_version import PackageVersionNumber
|
|
10
|
+
from cumulusci.tasks.salesforce import BaseSalesforceApiTask
|
|
11
|
+
from cumulusci.utils.salesforce.soql import (
|
|
12
|
+
format_subscriber_package_version_where_clause,
|
|
13
|
+
)
|
|
14
|
+
from cumulusci.vcs.bootstrap import get_version_id_from_tag
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PromotePackageVersion(BaseSalesforceApiTask):
|
|
18
|
+
"""
|
|
19
|
+
Promote a 2GP Package version from a Beta to a Production release.
|
|
20
|
+
|
|
21
|
+
The terms "promoted" and "released" are the same in the context of
|
|
22
|
+
a 2GP package. Once "promoted" a package is considered to be "released".
|
|
23
|
+
Hence, the "promotion" of a package is just an update to the
|
|
24
|
+
Package2Version.IsReleased field.
|
|
25
|
+
|
|
26
|
+
The abbreviation `spv` in variable names is shorthand for "SubscriberPackageVersion".
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
task_docs = """Promote a Second Generation package (managed or unlocked).
|
|
30
|
+
Lists any 1GP dependencies that are detected, as well as
|
|
31
|
+
any dependency packages that have not been promoted.
|
|
32
|
+
Once promoted, the 2GP package can be installed into production orgs."""
|
|
33
|
+
|
|
34
|
+
task_options = {
|
|
35
|
+
"version_id": {
|
|
36
|
+
"description": "The SubscriberPackageVersion (04t) Id for the target package.",
|
|
37
|
+
"required": False,
|
|
38
|
+
},
|
|
39
|
+
"promote_dependencies": {
|
|
40
|
+
"description": (
|
|
41
|
+
"Automatically promote any unpromoted versions of dependency 2GP packages that are detected."
|
|
42
|
+
),
|
|
43
|
+
"required": False,
|
|
44
|
+
},
|
|
45
|
+
"install_key": {
|
|
46
|
+
"description": "Install key for package. Default is no install key."
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# We do use a Salesforce org, but it's the dev hub obtained using get_devhub_config,
|
|
51
|
+
# so the user does not need to specify an org on the CLI
|
|
52
|
+
salesforce_task = False
|
|
53
|
+
|
|
54
|
+
# Since self.org_config is unused, don't try to refresh its token
|
|
55
|
+
def _update_credentials(self):
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def _init_options(self, kwargs) -> None:
|
|
59
|
+
super()._init_options(kwargs)
|
|
60
|
+
|
|
61
|
+
version_id = self.options.get("version_id")
|
|
62
|
+
if version_id and (
|
|
63
|
+
not isinstance(version_id, str) or not version_id.startswith("04t")
|
|
64
|
+
):
|
|
65
|
+
raise TaskOptionsError(
|
|
66
|
+
"Task option `version_id` must be a valid SubscriberPackageVersion (04t) Id"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def _init_task(self) -> None:
|
|
70
|
+
self.tooling = get_simple_salesforce_connection(
|
|
71
|
+
self.project_config,
|
|
72
|
+
get_devhub_config(self.project_config),
|
|
73
|
+
api_version=self.api_version,
|
|
74
|
+
base_url="tooling",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def _run_task(self) -> None:
|
|
78
|
+
"""Orchestrate the task"""
|
|
79
|
+
version_id = self.options.get("version_id")
|
|
80
|
+
if not version_id:
|
|
81
|
+
version_id = self._resolve_version_id()
|
|
82
|
+
|
|
83
|
+
dependencies = self._get_dependency_info(version_id)
|
|
84
|
+
|
|
85
|
+
self._process_one_gp_deps(dependencies)
|
|
86
|
+
should_exit = self._process_two_gp_deps(dependencies)
|
|
87
|
+
|
|
88
|
+
if should_exit:
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
target_package_info = self._get_target_package_info(version_id)
|
|
92
|
+
self._promote_package_version(target_package_info)
|
|
93
|
+
self.return_values = {
|
|
94
|
+
"dependencies": [
|
|
95
|
+
PackageVersionIdDependency(version_id=d["version_id"])
|
|
96
|
+
for d in dependencies
|
|
97
|
+
],
|
|
98
|
+
"version_id": version_id,
|
|
99
|
+
"version_number": target_package_info["package_version_number"],
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
def _resolve_version_id(self) -> str:
|
|
103
|
+
"""
|
|
104
|
+
If a SubscriberPackageVersionId has not been specified we need to
|
|
105
|
+
auto-resolve a version_id from the tag on our current commit
|
|
106
|
+
|
|
107
|
+
@returns: (str) the SubscriberPackageVersionId from the current repo commit
|
|
108
|
+
"""
|
|
109
|
+
self.logger.info(
|
|
110
|
+
"No version_id specified. Automatically resolving to latest available Beta version."
|
|
111
|
+
)
|
|
112
|
+
tag_name = self.project_config.get_latest_tag(beta=True)
|
|
113
|
+
repo = self.project_config.get_repo()
|
|
114
|
+
version_id = get_version_id_from_tag(repo, tag_name)
|
|
115
|
+
self.logger.info(f"Resolved to version: {version_id}")
|
|
116
|
+
self.logger.info("")
|
|
117
|
+
return version_id
|
|
118
|
+
|
|
119
|
+
def _get_dependency_info(self, spv_id: str) -> Optional[List[Dict]]:
|
|
120
|
+
"""
|
|
121
|
+
Given a SubscriberPackageVersionId (04t) return a list of
|
|
122
|
+
dictionaries with info on all dependency packages present.
|
|
123
|
+
|
|
124
|
+
@param spv_id: a SubscriberPackageVersionId
|
|
125
|
+
@returns: a dict with the following shape:
|
|
126
|
+
{
|
|
127
|
+
"is_2gp": (bool) whether or not this dependency is a 2GP package
|
|
128
|
+
"is_promoted": whether or not this package is already promoted (only present if is_2gp is True)
|
|
129
|
+
"Package2VersionId": The Id from the corresponding Package2Version record
|
|
130
|
+
"name": (str) The name of the package
|
|
131
|
+
"release_state": (str) the package's release state
|
|
132
|
+
"version_id": (str) the SubscriberPackageVersionId (04t) of the dependency
|
|
133
|
+
}
|
|
134
|
+
"""
|
|
135
|
+
dependency_spv_ids = self._get_dependency_spv_ids(spv_id)
|
|
136
|
+
|
|
137
|
+
dependencies = []
|
|
138
|
+
for spv_id in dependency_spv_ids:
|
|
139
|
+
subscriber_package_version = self._query_SubscriberPackageVersion(spv_id)
|
|
140
|
+
subscriber_package = self._query_SubscriberPackage(
|
|
141
|
+
subscriber_package_version["SubscriberPackageId"]
|
|
142
|
+
)
|
|
143
|
+
package_2_version = self._query_Package2Version(spv_id)
|
|
144
|
+
|
|
145
|
+
info = {
|
|
146
|
+
"name": subscriber_package["Name"],
|
|
147
|
+
"release_state": subscriber_package_version["ReleaseState"],
|
|
148
|
+
"version_id": spv_id,
|
|
149
|
+
}
|
|
150
|
+
if package_2_version:
|
|
151
|
+
info["is_2gp"] = True
|
|
152
|
+
info["is_promoted"] = package_2_version["IsReleased"]
|
|
153
|
+
info["Package2VersionId"] = package_2_version["Id"]
|
|
154
|
+
else:
|
|
155
|
+
# It's a 1GP dependency if no Package2Version record is present
|
|
156
|
+
info["is_2gp"] = False
|
|
157
|
+
info["is_promoted"] = None
|
|
158
|
+
info["Package2VersionId"] = None
|
|
159
|
+
|
|
160
|
+
dependencies.append(info)
|
|
161
|
+
|
|
162
|
+
self.logger.info(f"Total dependencies found: {len(dependencies)}")
|
|
163
|
+
return dependencies
|
|
164
|
+
|
|
165
|
+
def _get_dependency_spv_ids(self, spv_id: str) -> List[str]:
|
|
166
|
+
"""
|
|
167
|
+
@param spv_id: SubscriberPackageVersionId to fetch dependencies for
|
|
168
|
+
@return: list of SubscriberPackageVersionIds (04t) of dependency packages
|
|
169
|
+
"""
|
|
170
|
+
subscriber_package_version = self._query_SubscriberPackageVersion(spv_id)
|
|
171
|
+
dependencies = subscriber_package_version["Dependencies"] or {"ids": []}
|
|
172
|
+
dependencies = [d["subscriberPackageVersionId"] for d in dependencies["ids"]]
|
|
173
|
+
return dependencies
|
|
174
|
+
|
|
175
|
+
def _process_one_gp_deps(self, dependencies: List[Dict]) -> None:
|
|
176
|
+
"""
|
|
177
|
+
Log any 1GP dependecies that are present.
|
|
178
|
+
|
|
179
|
+
@param dependencies: list of dependencies to process
|
|
180
|
+
"""
|
|
181
|
+
one_gp_deps = self._filter_one_gp_deps(dependencies)
|
|
182
|
+
if one_gp_deps:
|
|
183
|
+
self.logger.warning("")
|
|
184
|
+
self.logger.warning("This package has the following 1GP dependencies:")
|
|
185
|
+
for dep in one_gp_deps:
|
|
186
|
+
self.logger.warning("")
|
|
187
|
+
self.logger.warning(f" Package Name: {dep['name']}")
|
|
188
|
+
self.logger.warning(f" Release State: {dep['release_state']}")
|
|
189
|
+
|
|
190
|
+
def _process_two_gp_deps(self, dependencies: List[Dict]) -> bool:
|
|
191
|
+
"""
|
|
192
|
+
If we're auto-promoting then auto-promote!
|
|
193
|
+
Otherwise, log which dependencies need promoting.
|
|
194
|
+
|
|
195
|
+
@param dependencies: list of dependencies to process
|
|
196
|
+
@return: a should_exit indicator to tell _run_task() whether or not to exit
|
|
197
|
+
"""
|
|
198
|
+
two_gp_deps = self._filter_two_gp_deps(dependencies)
|
|
199
|
+
unpromoted_two_gp_deps = self._filter_unpromoted_two_gp_deps(dependencies)
|
|
200
|
+
|
|
201
|
+
self.logger.info("")
|
|
202
|
+
self.logger.info(f"Total 2GP dependencies: {len(two_gp_deps)}")
|
|
203
|
+
self.logger.info(f"Unpromoted 2GP dependencies: {len(unpromoted_two_gp_deps)}")
|
|
204
|
+
|
|
205
|
+
should_exit = False
|
|
206
|
+
if unpromoted_two_gp_deps and self.options.get("promote_dependencies", False):
|
|
207
|
+
for d in unpromoted_two_gp_deps:
|
|
208
|
+
self._promote_package_version(d)
|
|
209
|
+
elif unpromoted_two_gp_deps:
|
|
210
|
+
# we only want _run_task() to exit if unpromoted
|
|
211
|
+
# 2GP deps are present and we aren't auto-promoting
|
|
212
|
+
should_exit = True
|
|
213
|
+
self.logger.error("")
|
|
214
|
+
self.logger.error(
|
|
215
|
+
"This package depends on other packages that have not yet been promoted."
|
|
216
|
+
)
|
|
217
|
+
self.logger.error(
|
|
218
|
+
"The following packages must be promoted before this one."
|
|
219
|
+
)
|
|
220
|
+
self.logger.error(
|
|
221
|
+
"(Use `--promote_dependencies True` to automatically promote these dependencies):"
|
|
222
|
+
)
|
|
223
|
+
self.logger.error("")
|
|
224
|
+
for dep in unpromoted_two_gp_deps:
|
|
225
|
+
self.logger.error(f" Package Name: {dep['name']}")
|
|
226
|
+
self.logger.error(f" SubscriberPackageVersionId: {dep['version_id']}")
|
|
227
|
+
self.logger.error("")
|
|
228
|
+
|
|
229
|
+
return should_exit
|
|
230
|
+
|
|
231
|
+
def _get_target_package_info(self, spv_id: str) -> Dict:
|
|
232
|
+
"""
|
|
233
|
+
@param spv_id: SubscriberPackageVersionId of the target package
|
|
234
|
+
@returns: dict of info on the target package with the following:
|
|
235
|
+
{
|
|
236
|
+
"name": name of the package,
|
|
237
|
+
"Package2VersionId": Id of the corresponding Package2Verison record
|
|
238
|
+
}
|
|
239
|
+
"""
|
|
240
|
+
package_2_version = self._query_Package2Version(spv_id)
|
|
241
|
+
version_number = PackageVersionNumber(**package_2_version)
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
"name": self.project_config.project__name,
|
|
245
|
+
"Package2VersionId": package_2_version["Id"],
|
|
246
|
+
"version_id": spv_id,
|
|
247
|
+
"package_version_number": version_number.format(),
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
def _promote_package_version(self, package_info: Dict) -> None:
|
|
251
|
+
"""
|
|
252
|
+
Promote the 2GP package associated with the given SubscriberPackageVersionId
|
|
253
|
+
|
|
254
|
+
@param spv_id: the SubscriberPackageVersionId to promote
|
|
255
|
+
"""
|
|
256
|
+
self.logger.info("")
|
|
257
|
+
self.logger.info(
|
|
258
|
+
f"Promoting package: {package_info['name']} ({package_info['version_id']})"
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
Package2Version = self._get_tooling_object("Package2Version")
|
|
262
|
+
Package2Version.update(package_info["Package2VersionId"], {"IsReleased": True})
|
|
263
|
+
|
|
264
|
+
self.logger.info("Package promoted!")
|
|
265
|
+
|
|
266
|
+
def _query_Package2Version(
|
|
267
|
+
self, spv_id: str, raise_error: bool = False
|
|
268
|
+
) -> Optional[Dict]:
|
|
269
|
+
"""Queries for a Package2Version record with the given SubscriberPackageVersionId"""
|
|
270
|
+
try:
|
|
271
|
+
return self._query_one_tooling(
|
|
272
|
+
[
|
|
273
|
+
"Id",
|
|
274
|
+
"BuildNumber",
|
|
275
|
+
"MajorVersion",
|
|
276
|
+
"MinorVersion",
|
|
277
|
+
"PatchVersion",
|
|
278
|
+
"IsReleased",
|
|
279
|
+
],
|
|
280
|
+
"Package2Version",
|
|
281
|
+
where_clause=f"SubscriberPackageVersionId='{spv_id}'",
|
|
282
|
+
raise_error=raise_error,
|
|
283
|
+
)
|
|
284
|
+
except SalesforceMalformedRequest as e:
|
|
285
|
+
if "Object type 'Package2' is not supported" in e.content[0]["message"]:
|
|
286
|
+
raise TaskOptionsError(
|
|
287
|
+
"This org does not have a Dev Hub with 2nd-generation packaging enabled. "
|
|
288
|
+
"Make sure you are using the correct org and/or check the Dev Hub settings in Setup."
|
|
289
|
+
)
|
|
290
|
+
raise # pragma: no cover
|
|
291
|
+
|
|
292
|
+
def _query_SubscriberPackage(self, sp_id: str) -> Optional[Dict]:
|
|
293
|
+
"""Queries for a SubscriberPackage with the given SubscriberPackageId"""
|
|
294
|
+
return self._query_one_tooling(
|
|
295
|
+
["Id", "Name"],
|
|
296
|
+
"SubscriberPackage",
|
|
297
|
+
where_clause=f"Id='{sp_id}'",
|
|
298
|
+
raise_error=True,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
def _query_SubscriberPackageVersion(self, spv_id: str) -> Optional[Dict]:
|
|
302
|
+
"""Queries for a SubscriberPackageVersion record with the given SubscriberPackageVersionId"""
|
|
303
|
+
|
|
304
|
+
return self._query_one_tooling(
|
|
305
|
+
[
|
|
306
|
+
"Id",
|
|
307
|
+
"Dependencies",
|
|
308
|
+
"ReleaseState",
|
|
309
|
+
"SubscriberPackageId",
|
|
310
|
+
],
|
|
311
|
+
"SubscriberPackageVersion",
|
|
312
|
+
where_clause=format_subscriber_package_version_where_clause(
|
|
313
|
+
spv_id, self.options.get("install_key")
|
|
314
|
+
),
|
|
315
|
+
raise_error=True,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
def _query_one_tooling(
|
|
319
|
+
self,
|
|
320
|
+
fields: List[str],
|
|
321
|
+
obj_name: str,
|
|
322
|
+
where_clause: str = None,
|
|
323
|
+
raise_error=False,
|
|
324
|
+
) -> Optional[Dict]:
|
|
325
|
+
"""
|
|
326
|
+
Queries the Tooling API and returns a _single_ sObject (or None).
|
|
327
|
+
See docstring of _query_tooling() for param info.
|
|
328
|
+
"""
|
|
329
|
+
records = self._query_tooling(
|
|
330
|
+
fields, obj_name, where_clause=where_clause, raise_error=raise_error
|
|
331
|
+
)
|
|
332
|
+
return records[0] if records else None
|
|
333
|
+
|
|
334
|
+
def _query_tooling(
|
|
335
|
+
self,
|
|
336
|
+
fields: List[str],
|
|
337
|
+
obj_name: str,
|
|
338
|
+
where_clause: str = None,
|
|
339
|
+
raise_error: bool = False,
|
|
340
|
+
) -> Optional[List[Dict]]:
|
|
341
|
+
"""
|
|
342
|
+
Queires the Tooling API
|
|
343
|
+
|
|
344
|
+
@param fields: list of fields to query for
|
|
345
|
+
@param obj_name: name of the tooling API sObject you want to query
|
|
346
|
+
@param where_clause: the where clause for the query (everything _after_ 'WHERE')
|
|
347
|
+
@param return_one: If true, returns a single sObject record
|
|
348
|
+
@param raise_error: If True, raises an error if no records are found
|
|
349
|
+
|
|
350
|
+
@return: None if no records are found, single sObject if `return_one` is True,
|
|
351
|
+
or a list of sObject records if `return_one` is False.
|
|
352
|
+
"""
|
|
353
|
+
query = f"SELECT {', '.join(fields)} FROM {obj_name}"
|
|
354
|
+
if where_clause:
|
|
355
|
+
query += f" WHERE {where_clause}"
|
|
356
|
+
|
|
357
|
+
res = self.tooling.query_all(query)
|
|
358
|
+
|
|
359
|
+
if not res["records"] or res["totalSize"] == 0:
|
|
360
|
+
if raise_error:
|
|
361
|
+
raise CumulusCIException(f"No records returned for query: {query}")
|
|
362
|
+
return None
|
|
363
|
+
|
|
364
|
+
return res["records"]
|
|
365
|
+
|
|
366
|
+
def _filter_one_gp_deps(self, dependencies: List[Dict]) -> List[Dict]:
|
|
367
|
+
"""Return only 1GP dependencies"""
|
|
368
|
+
return [d for d in dependencies if not d["is_2gp"]]
|
|
369
|
+
|
|
370
|
+
def _filter_two_gp_deps(self, dependencies: List[Dict]) -> List[Dict]:
|
|
371
|
+
"""Return only 2GP dependencies"""
|
|
372
|
+
return [d for d in dependencies if d["is_2gp"]]
|
|
373
|
+
|
|
374
|
+
def _filter_unpromoted_two_gp_deps(self, dependencies: List[Dict]) -> List[Dict]:
|
|
375
|
+
"""Return only 2GP dependencies that are not yet promoted"""
|
|
376
|
+
return [d for d in dependencies if d["is_2gp"] and not d["is_promoted"]]
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from cumulusci.core.utils import process_bool_arg, process_list_arg
|
|
4
|
+
from cumulusci.salesforce_api.metadata import ApiRetrieveUnpackaged
|
|
5
|
+
from cumulusci.salesforce_api.retrieve_profile_api import RetrieveProfileApi
|
|
6
|
+
from cumulusci.tasks.salesforce.BaseSalesforceMetadataApiTask import (
|
|
7
|
+
BaseSalesforceMetadataApiTask,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RetrieveProfile(BaseSalesforceMetadataApiTask):
|
|
12
|
+
api_class = ApiRetrieveUnpackaged
|
|
13
|
+
task_options = {
|
|
14
|
+
"profiles": {
|
|
15
|
+
"description": "List of profile API names that you want to retrieve",
|
|
16
|
+
"required": True,
|
|
17
|
+
},
|
|
18
|
+
"path": {
|
|
19
|
+
"description": "Target folder path. By default, it uses force-app/main/default",
|
|
20
|
+
},
|
|
21
|
+
"strict_mode": {
|
|
22
|
+
"description": "When set to False, enables leniency by ignoring missing profiles when provided with a list of profiles."
|
|
23
|
+
" When set to True, enforces strict validation, causing a failure if any profile is not present in the list."
|
|
24
|
+
" Default is True",
|
|
25
|
+
"required": False,
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def _init_options(self, kwargs):
|
|
30
|
+
super(RetrieveProfile, self)._init_options(kwargs)
|
|
31
|
+
self.api_version = self.project_config.config["project"]["package"][
|
|
32
|
+
"api_version"
|
|
33
|
+
]
|
|
34
|
+
self.profiles = process_list_arg(self.options["profiles"])
|
|
35
|
+
if not self.profiles:
|
|
36
|
+
raise ValueError("At least one profile must be specified.")
|
|
37
|
+
|
|
38
|
+
self.extract_dir = self.options.get("path", "force-app")
|
|
39
|
+
extract_path = Path(self.extract_dir)
|
|
40
|
+
|
|
41
|
+
if not extract_path.exists():
|
|
42
|
+
raise FileNotFoundError(
|
|
43
|
+
f"The extract directory '{self.extract_dir}' does not exist."
|
|
44
|
+
)
|
|
45
|
+
if not extract_path.is_dir():
|
|
46
|
+
raise NotADirectoryError(f"'{self.extract_dir}' is not a directory.")
|
|
47
|
+
|
|
48
|
+
# If extract_dir is force-app and main/default is not present
|
|
49
|
+
if self.extract_dir == "force-app":
|
|
50
|
+
if not (extract_path / "main" / "default").exists():
|
|
51
|
+
(extract_path / "main" / "default").mkdir(parents=True, exist_ok=True)
|
|
52
|
+
self.extract_dir = "force-app/main/default"
|
|
53
|
+
|
|
54
|
+
self.strictMode = process_bool_arg(self.options.get("strict_mode", True))
|
|
55
|
+
|
|
56
|
+
def _check_existing_profiles(self, retrieve_profile_api_task):
|
|
57
|
+
# Check for existing profiles
|
|
58
|
+
self.existing_profiles = retrieve_profile_api_task._retrieve_existing_profiles(
|
|
59
|
+
self.profiles
|
|
60
|
+
)
|
|
61
|
+
self.missing_profiles = set(self.profiles) - set(self.existing_profiles)
|
|
62
|
+
|
|
63
|
+
# Handle for strictMode
|
|
64
|
+
if self.missing_profiles:
|
|
65
|
+
self.logger.warning(
|
|
66
|
+
f"The following profiles were not found or could not be retrieved: '{', '.join(self.missing_profiles)}'\n"
|
|
67
|
+
)
|
|
68
|
+
if self.strictMode:
|
|
69
|
+
raise RuntimeError(
|
|
70
|
+
"Operation failed due to missing profiles. Set strictMode to False if you want to ignore missing profiles."
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Handle for no existing profiles
|
|
74
|
+
if not self.existing_profiles:
|
|
75
|
+
raise RuntimeError("None of the profiles given were found.")
|
|
76
|
+
|
|
77
|
+
def add_flow_accesses(self, profile_content, flows):
|
|
78
|
+
# Find the position of the closing </Profile> tag
|
|
79
|
+
profile_end_position = profile_content.find("</Profile>")
|
|
80
|
+
|
|
81
|
+
if profile_end_position != -1:
|
|
82
|
+
flow_accesses_xml = "".join(
|
|
83
|
+
[
|
|
84
|
+
f" <flowAccesses>\n"
|
|
85
|
+
f" <enabled>true</enabled>\n"
|
|
86
|
+
f" <flow>{flow}</flow>\n"
|
|
87
|
+
f" </flowAccesses>\n"
|
|
88
|
+
for flow in flows
|
|
89
|
+
]
|
|
90
|
+
)
|
|
91
|
+
modified_content = (
|
|
92
|
+
profile_content[:profile_end_position]
|
|
93
|
+
+ flow_accesses_xml
|
|
94
|
+
+ profile_content[profile_end_position:]
|
|
95
|
+
)
|
|
96
|
+
return modified_content
|
|
97
|
+
|
|
98
|
+
return profile_content
|
|
99
|
+
|
|
100
|
+
def save_profile_file(self, extract_dir, filename, content):
|
|
101
|
+
profile_path = Path(extract_dir) / filename
|
|
102
|
+
profile_meta_xml_path = Path(extract_dir) / f"{filename}-meta.xml"
|
|
103
|
+
|
|
104
|
+
# Check if either the profile file or metadata file exists
|
|
105
|
+
if profile_path.exists():
|
|
106
|
+
self.update_file_content(profile_path, content)
|
|
107
|
+
elif profile_meta_xml_path.exists():
|
|
108
|
+
self.update_file_content(profile_meta_xml_path, content)
|
|
109
|
+
else:
|
|
110
|
+
# Neither file exists, create the profile file
|
|
111
|
+
profile_meta_xml_path.parent.mkdir(parents=True, exist_ok=True)
|
|
112
|
+
with profile_meta_xml_path.open(
|
|
113
|
+
mode="w", encoding="utf-8"
|
|
114
|
+
) as updated_profile_file:
|
|
115
|
+
updated_profile_file.write(content)
|
|
116
|
+
|
|
117
|
+
def update_file_content(self, file_path, content):
|
|
118
|
+
with open(file_path, "w", encoding="utf-8") as updated_file:
|
|
119
|
+
updated_file.write(content)
|
|
120
|
+
|
|
121
|
+
def _run_task(self):
|
|
122
|
+
self.retrieve_profile_api_task = RetrieveProfileApi(
|
|
123
|
+
project_config=self.project_config,
|
|
124
|
+
task_config=self.task_config,
|
|
125
|
+
org_config=self.org_config,
|
|
126
|
+
)
|
|
127
|
+
self.retrieve_profile_api_task._init_task()
|
|
128
|
+
self._check_existing_profiles(self.retrieve_profile_api_task)
|
|
129
|
+
(
|
|
130
|
+
permissionable_entities,
|
|
131
|
+
profile_flows,
|
|
132
|
+
) = self.retrieve_profile_api_task._retrieve_permissionable_entities(
|
|
133
|
+
self.existing_profiles
|
|
134
|
+
)
|
|
135
|
+
entities_to_be_retrieved = {
|
|
136
|
+
**permissionable_entities,
|
|
137
|
+
**{"Profile": self.existing_profiles},
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
self.package_xml = self._create_package_xml(
|
|
141
|
+
entities_to_be_retrieved, self.api_version
|
|
142
|
+
)
|
|
143
|
+
api = self._get_api()
|
|
144
|
+
zip_result = api()
|
|
145
|
+
|
|
146
|
+
for file_info in zip_result.infolist():
|
|
147
|
+
if file_info.filename.startswith(
|
|
148
|
+
"profiles/"
|
|
149
|
+
) and file_info.filename.endswith(".profile"):
|
|
150
|
+
with zip_result.open(file_info) as profile_file:
|
|
151
|
+
profile_content = profile_file.read().decode("utf-8")
|
|
152
|
+
profile_name = profile_name = Path(file_info.filename).stem
|
|
153
|
+
|
|
154
|
+
if profile_name in profile_flows:
|
|
155
|
+
profile_content = self.add_flow_accesses(
|
|
156
|
+
profile_content, profile_flows[profile_name]
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
self.save_profile_file(
|
|
160
|
+
self.extract_dir, file_info.filename, profile_content
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# zip_result.extractall('./unpackaged')
|
|
164
|
+
self.existing_profiles.remove(
|
|
165
|
+
"Admin"
|
|
166
|
+
) if "Admin" in self.existing_profiles else None
|
|
167
|
+
self.logger.info(
|
|
168
|
+
f"Profiles {', '.join(self.existing_profiles)} unzipped into folder '{self.extract_dir}'"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def _get_api(self):
|
|
172
|
+
# Logs
|
|
173
|
+
self.logger.info("Retrieving all entities from org:")
|
|
174
|
+
|
|
175
|
+
return self.api_class(
|
|
176
|
+
self,
|
|
177
|
+
api_version=self.api_version,
|
|
178
|
+
package_xml=self.package_xml,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def _create_package_xml(self, input_dict: dict, api_version: str):
|
|
182
|
+
package_xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
|
|
183
|
+
package_xml += '<Package xmlns="http://soap.sforce.com/2006/04/metadata">\n'
|
|
184
|
+
|
|
185
|
+
for name, members in input_dict.items():
|
|
186
|
+
package_xml += " <types>\n"
|
|
187
|
+
for member in members:
|
|
188
|
+
package_xml += f" <members>{member}</members>\n"
|
|
189
|
+
package_xml += f" <name>{name}</name>\n"
|
|
190
|
+
package_xml += " </types>\n"
|
|
191
|
+
|
|
192
|
+
package_xml += f" <version>{api_version}</version>\n"
|
|
193
|
+
package_xml += "</Package>\n"
|
|
194
|
+
|
|
195
|
+
return package_xml
|