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.

Files changed (744) hide show
  1. cumulusci/__about__.py +1 -0
  2. cumulusci/__init__.py +22 -0
  3. cumulusci/__main__.py +3 -0
  4. cumulusci/cli/__init__.py +0 -0
  5. cumulusci/cli/cci.py +244 -0
  6. cumulusci/cli/error.py +125 -0
  7. cumulusci/cli/flow.py +185 -0
  8. cumulusci/cli/logger.py +72 -0
  9. cumulusci/cli/org.py +692 -0
  10. cumulusci/cli/plan.py +181 -0
  11. cumulusci/cli/project.py +391 -0
  12. cumulusci/cli/robot.py +116 -0
  13. cumulusci/cli/runtime.py +190 -0
  14. cumulusci/cli/service.py +521 -0
  15. cumulusci/cli/task.py +295 -0
  16. cumulusci/cli/tests/__init__.py +0 -0
  17. cumulusci/cli/tests/test_cci.py +545 -0
  18. cumulusci/cli/tests/test_error.py +170 -0
  19. cumulusci/cli/tests/test_flow.py +276 -0
  20. cumulusci/cli/tests/test_logger.py +25 -0
  21. cumulusci/cli/tests/test_org.py +1438 -0
  22. cumulusci/cli/tests/test_plan.py +245 -0
  23. cumulusci/cli/tests/test_project.py +235 -0
  24. cumulusci/cli/tests/test_robot.py +177 -0
  25. cumulusci/cli/tests/test_runtime.py +197 -0
  26. cumulusci/cli/tests/test_service.py +853 -0
  27. cumulusci/cli/tests/test_task.py +266 -0
  28. cumulusci/cli/tests/test_ui.py +310 -0
  29. cumulusci/cli/tests/test_utils.py +122 -0
  30. cumulusci/cli/tests/utils.py +52 -0
  31. cumulusci/cli/ui.py +234 -0
  32. cumulusci/cli/utils.py +150 -0
  33. cumulusci/conftest.py +181 -0
  34. cumulusci/core/__init__.py +0 -0
  35. cumulusci/core/config/BaseConfig.py +5 -0
  36. cumulusci/core/config/BaseTaskFlowConfig.py +5 -0
  37. cumulusci/core/config/OrgConfig.py +5 -0
  38. cumulusci/core/config/ScratchOrgConfig.py +5 -0
  39. cumulusci/core/config/__init__.py +125 -0
  40. cumulusci/core/config/base_config.py +111 -0
  41. cumulusci/core/config/base_task_flow_config.py +82 -0
  42. cumulusci/core/config/marketing_cloud_service_config.py +83 -0
  43. cumulusci/core/config/oauth2_service_config.py +17 -0
  44. cumulusci/core/config/org_config.py +604 -0
  45. cumulusci/core/config/project_config.py +782 -0
  46. cumulusci/core/config/scratch_org_config.py +251 -0
  47. cumulusci/core/config/sfdx_org_config.py +220 -0
  48. cumulusci/core/config/tests/_test_config_backwards_compatibility.py +33 -0
  49. cumulusci/core/config/tests/test_config.py +1895 -0
  50. cumulusci/core/config/tests/test_config_expensive.py +839 -0
  51. cumulusci/core/config/tests/test_config_util.py +91 -0
  52. cumulusci/core/config/universal_config.py +88 -0
  53. cumulusci/core/config/util.py +18 -0
  54. cumulusci/core/datasets.py +303 -0
  55. cumulusci/core/debug.py +33 -0
  56. cumulusci/core/dependencies/__init__.py +55 -0
  57. cumulusci/core/dependencies/base.py +561 -0
  58. cumulusci/core/dependencies/dependencies.py +273 -0
  59. cumulusci/core/dependencies/github.py +177 -0
  60. cumulusci/core/dependencies/github_resolvers.py +244 -0
  61. cumulusci/core/dependencies/resolvers.py +580 -0
  62. cumulusci/core/dependencies/tests/__init__.py +0 -0
  63. cumulusci/core/dependencies/tests/conftest.py +385 -0
  64. cumulusci/core/dependencies/tests/test_dependencies.py +950 -0
  65. cumulusci/core/dependencies/tests/test_github.py +83 -0
  66. cumulusci/core/dependencies/tests/test_resolvers.py +1027 -0
  67. cumulusci/core/dependencies/utils.py +13 -0
  68. cumulusci/core/enums.py +11 -0
  69. cumulusci/core/exceptions.py +311 -0
  70. cumulusci/core/flowrunner.py +888 -0
  71. cumulusci/core/github.py +665 -0
  72. cumulusci/core/keychain/__init__.py +24 -0
  73. cumulusci/core/keychain/base_project_keychain.py +441 -0
  74. cumulusci/core/keychain/encrypted_file_project_keychain.py +945 -0
  75. cumulusci/core/keychain/environment_project_keychain.py +7 -0
  76. cumulusci/core/keychain/serialization.py +152 -0
  77. cumulusci/core/keychain/subprocess_keychain.py +24 -0
  78. cumulusci/core/keychain/tests/conftest.py +50 -0
  79. cumulusci/core/keychain/tests/test_base_project_keychain.py +299 -0
  80. cumulusci/core/keychain/tests/test_encrypted_file_project_keychain.py +1228 -0
  81. cumulusci/core/metadeploy/__init__.py +0 -0
  82. cumulusci/core/metadeploy/api.py +88 -0
  83. cumulusci/core/metadeploy/plans.py +25 -0
  84. cumulusci/core/metadeploy/tests/test_api.py +276 -0
  85. cumulusci/core/runtime.py +115 -0
  86. cumulusci/core/sfdx.py +162 -0
  87. cumulusci/core/source/__init__.py +16 -0
  88. cumulusci/core/source/github.py +50 -0
  89. cumulusci/core/source/local_folder.py +35 -0
  90. cumulusci/core/source_transforms/__init__.py +0 -0
  91. cumulusci/core/source_transforms/tests/test_transforms.py +1091 -0
  92. cumulusci/core/source_transforms/transforms.py +532 -0
  93. cumulusci/core/tasks.py +404 -0
  94. cumulusci/core/template_utils.py +59 -0
  95. cumulusci/core/tests/__init__.py +0 -0
  96. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_e2e.yaml +215 -0
  97. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_extract_standard_objects.yaml +199 -0
  98. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml +3 -0
  99. cumulusci/core/tests/fake_remote_repo/cumulusci.yml +32 -0
  100. cumulusci/core/tests/fake_remote_repo/tasks/directory/example_2.py +6 -0
  101. cumulusci/core/tests/fake_remote_repo/tasks/example.py +43 -0
  102. cumulusci/core/tests/fake_remote_repo_2/cumulusci.yml +11 -0
  103. cumulusci/core/tests/fake_remote_repo_2/tasks/example_3.py +6 -0
  104. cumulusci/core/tests/test_datasets_e2e.py +386 -0
  105. cumulusci/core/tests/test_exceptions.py +11 -0
  106. cumulusci/core/tests/test_flowrunner.py +836 -0
  107. cumulusci/core/tests/test_github.py +942 -0
  108. cumulusci/core/tests/test_sfdx.py +138 -0
  109. cumulusci/core/tests/test_source.py +678 -0
  110. cumulusci/core/tests/test_tasks.py +262 -0
  111. cumulusci/core/tests/test_utils.py +141 -0
  112. cumulusci/core/tests/test_utils_merge_config.py +276 -0
  113. cumulusci/core/tests/test_versions.py +76 -0
  114. cumulusci/core/tests/untrusted_repo_child/cumulusci.yml +7 -0
  115. cumulusci/core/tests/untrusted_repo_child/tasks/untrusted_child.py +6 -0
  116. cumulusci/core/tests/untrusted_repo_parent/cumulusci.yml +26 -0
  117. cumulusci/core/tests/untrusted_repo_parent/tasks/untrusted_parent.py +6 -0
  118. cumulusci/core/tests/utils.py +116 -0
  119. cumulusci/core/tests/yaml/global.yaml +0 -0
  120. cumulusci/core/utils.py +402 -0
  121. cumulusci/core/versions.py +149 -0
  122. cumulusci/cumulusci.yml +1621 -0
  123. cumulusci/files/admin_profile.xml +20 -0
  124. cumulusci/files/delete_excludes.txt +424 -0
  125. cumulusci/files/templates/project/README.md +12 -0
  126. cumulusci/files/templates/project/cumulusci.yml +63 -0
  127. cumulusci/files/templates/project/dot-gitignore +60 -0
  128. cumulusci/files/templates/project/mapping.yml +45 -0
  129. cumulusci/files/templates/project/scratch_def.json +25 -0
  130. cumulusci/oauth/__init__.py +0 -0
  131. cumulusci/oauth/client.py +400 -0
  132. cumulusci/oauth/exceptions.py +9 -0
  133. cumulusci/oauth/salesforce.py +95 -0
  134. cumulusci/oauth/tests/__init__.py +0 -0
  135. cumulusci/oauth/tests/cassettes/test_get_device_code.yaml +22 -0
  136. cumulusci/oauth/tests/cassettes/test_get_device_oauth_token.yaml +74 -0
  137. cumulusci/oauth/tests/test_client.py +308 -0
  138. cumulusci/oauth/tests/test_salesforce.py +46 -0
  139. cumulusci/plugins/__init__.py +3 -0
  140. cumulusci/plugins/plugin_base.py +93 -0
  141. cumulusci/plugins/plugin_loader.py +59 -0
  142. cumulusci/robotframework/CumulusCI.py +340 -0
  143. cumulusci/robotframework/CumulusCI.robot +7 -0
  144. cumulusci/robotframework/Performance.py +165 -0
  145. cumulusci/robotframework/Salesforce.py +936 -0
  146. cumulusci/robotframework/Salesforce.robot +192 -0
  147. cumulusci/robotframework/SalesforceAPI.py +416 -0
  148. cumulusci/robotframework/SalesforcePlaywright.py +220 -0
  149. cumulusci/robotframework/SalesforcePlaywright.robot +40 -0
  150. cumulusci/robotframework/__init__.py +2 -0
  151. cumulusci/robotframework/base_library.py +39 -0
  152. cumulusci/robotframework/faker_mixin.py +89 -0
  153. cumulusci/robotframework/form_handlers.py +222 -0
  154. cumulusci/robotframework/javascript/cci_init.js +34 -0
  155. cumulusci/robotframework/javascript/cumulusci.js +4 -0
  156. cumulusci/robotframework/locator_manager.py +197 -0
  157. cumulusci/robotframework/locators_56.py +88 -0
  158. cumulusci/robotframework/locators_57.py +5 -0
  159. cumulusci/robotframework/pageobjects/BasePageObjects.py +433 -0
  160. cumulusci/robotframework/pageobjects/ObjectManagerPageObject.py +246 -0
  161. cumulusci/robotframework/pageobjects/PageObjectLibrary.py +45 -0
  162. cumulusci/robotframework/pageobjects/PageObjects.py +351 -0
  163. cumulusci/robotframework/pageobjects/__init__.py +12 -0
  164. cumulusci/robotframework/pageobjects/baseobjects.py +120 -0
  165. cumulusci/robotframework/perftests/short/collection_perf.robot +105 -0
  166. cumulusci/robotframework/tests/CustomObjectTestPage.py +10 -0
  167. cumulusci/robotframework/tests/FooTestPage.py +8 -0
  168. cumulusci/robotframework/tests/cumulusci/base.robot +40 -0
  169. cumulusci/robotframework/tests/cumulusci/bulkdata.robot +38 -0
  170. cumulusci/robotframework/tests/cumulusci/communities.robot +57 -0
  171. cumulusci/robotframework/tests/cumulusci/datagen.robot +84 -0
  172. cumulusci/robotframework/tests/salesforce/TestLibraryA.py +24 -0
  173. cumulusci/robotframework/tests/salesforce/TestLibraryB.py +20 -0
  174. cumulusci/robotframework/tests/salesforce/TestListener.py +93 -0
  175. cumulusci/robotframework/tests/salesforce/api.robot +178 -0
  176. cumulusci/robotframework/tests/salesforce/browsers.robot +143 -0
  177. cumulusci/robotframework/tests/salesforce/classic.robot +51 -0
  178. cumulusci/robotframework/tests/salesforce/create_contact.robot +59 -0
  179. cumulusci/robotframework/tests/salesforce/faker.robot +68 -0
  180. cumulusci/robotframework/tests/salesforce/forms.robot +172 -0
  181. cumulusci/robotframework/tests/salesforce/label_locator.robot +244 -0
  182. cumulusci/robotframework/tests/salesforce/labels.html +33 -0
  183. cumulusci/robotframework/tests/salesforce/locators.robot +149 -0
  184. cumulusci/robotframework/tests/salesforce/pageobjects/base_pageobjects.robot +100 -0
  185. cumulusci/robotframework/tests/salesforce/pageobjects/example_page_object.py +25 -0
  186. cumulusci/robotframework/tests/salesforce/pageobjects/listing_page.robot +115 -0
  187. cumulusci/robotframework/tests/salesforce/pageobjects/objectmanager.robot +74 -0
  188. cumulusci/robotframework/tests/salesforce/pageobjects/pageobjects.robot +171 -0
  189. cumulusci/robotframework/tests/salesforce/performance.robot +109 -0
  190. cumulusci/robotframework/tests/salesforce/playwright/javascript_keywords.robot +33 -0
  191. cumulusci/robotframework/tests/salesforce/playwright/open_test_browser.robot +48 -0
  192. cumulusci/robotframework/tests/salesforce/playwright/playwright.robot +24 -0
  193. cumulusci/robotframework/tests/salesforce/playwright/ui.robot +32 -0
  194. cumulusci/robotframework/tests/salesforce/populate.robot +89 -0
  195. cumulusci/robotframework/tests/salesforce/test_testlistener.py +37 -0
  196. cumulusci/robotframework/tests/salesforce/ui.robot +361 -0
  197. cumulusci/robotframework/tests/test_cumulusci_library.py +304 -0
  198. cumulusci/robotframework/tests/test_locator_manager.py +158 -0
  199. cumulusci/robotframework/tests/test_pageobjects.py +291 -0
  200. cumulusci/robotframework/tests/test_performance.py +38 -0
  201. cumulusci/robotframework/tests/test_salesforce.py +79 -0
  202. cumulusci/robotframework/tests/test_salesforce_locators.py +73 -0
  203. cumulusci/robotframework/tests/test_template_util.py +53 -0
  204. cumulusci/robotframework/tests/test_utils.py +106 -0
  205. cumulusci/robotframework/utils.py +283 -0
  206. cumulusci/salesforce_api/__init__.py +0 -0
  207. cumulusci/salesforce_api/exceptions.py +23 -0
  208. cumulusci/salesforce_api/filterable_objects.py +96 -0
  209. cumulusci/salesforce_api/mc_soap_envelopes.py +89 -0
  210. cumulusci/salesforce_api/metadata.py +721 -0
  211. cumulusci/salesforce_api/org_schema.py +571 -0
  212. cumulusci/salesforce_api/org_schema_models.py +226 -0
  213. cumulusci/salesforce_api/package_install.py +265 -0
  214. cumulusci/salesforce_api/package_zip.py +301 -0
  215. cumulusci/salesforce_api/rest_deploy.py +148 -0
  216. cumulusci/salesforce_api/retrieve_profile_api.py +301 -0
  217. cumulusci/salesforce_api/soap_envelopes.py +177 -0
  218. cumulusci/salesforce_api/tests/__init__.py +0 -0
  219. cumulusci/salesforce_api/tests/metadata_test_strings.py +24 -0
  220. cumulusci/salesforce_api/tests/test_metadata.py +1015 -0
  221. cumulusci/salesforce_api/tests/test_package_install.py +219 -0
  222. cumulusci/salesforce_api/tests/test_package_zip.py +380 -0
  223. cumulusci/salesforce_api/tests/test_rest_deploy.py +264 -0
  224. cumulusci/salesforce_api/tests/test_retrieve_profile_api.py +337 -0
  225. cumulusci/salesforce_api/tests/test_utils.py +124 -0
  226. cumulusci/salesforce_api/utils.py +51 -0
  227. cumulusci/schema/cumulusci.jsonschema.json +782 -0
  228. cumulusci/tasks/__init__.py +0 -0
  229. cumulusci/tasks/apex/__init__.py +0 -0
  230. cumulusci/tasks/apex/anon.py +157 -0
  231. cumulusci/tasks/apex/batch.py +180 -0
  232. cumulusci/tasks/apex/testrunner.py +835 -0
  233. cumulusci/tasks/apex/tests/cassettes/ManualEditTestApexIntegrationTests.test_run_tests__integration_test.yaml +703 -0
  234. cumulusci/tasks/apex/tests/test_apex_tasks.py +1558 -0
  235. cumulusci/tasks/base_source_control_task.py +17 -0
  236. cumulusci/tasks/bulkdata/__init__.py +15 -0
  237. cumulusci/tasks/bulkdata/base_generate_data_task.py +96 -0
  238. cumulusci/tasks/bulkdata/dates.py +97 -0
  239. cumulusci/tasks/bulkdata/delete.py +156 -0
  240. cumulusci/tasks/bulkdata/extract.py +441 -0
  241. cumulusci/tasks/bulkdata/extract_dataset_utils/calculate_dependencies.py +117 -0
  242. cumulusci/tasks/bulkdata/extract_dataset_utils/extract_yml.py +123 -0
  243. cumulusci/tasks/bulkdata/extract_dataset_utils/hardcoded_default_declarations.py +49 -0
  244. cumulusci/tasks/bulkdata/extract_dataset_utils/synthesize_extract_declarations.py +283 -0
  245. cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_extract_yml.py +142 -0
  246. cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_synthesize_extract_declarations.py +575 -0
  247. cumulusci/tasks/bulkdata/factory_utils.py +134 -0
  248. cumulusci/tasks/bulkdata/generate.py +4 -0
  249. cumulusci/tasks/bulkdata/generate_and_load_data.py +232 -0
  250. cumulusci/tasks/bulkdata/generate_and_load_data_from_yaml.py +19 -0
  251. cumulusci/tasks/bulkdata/generate_from_yaml.py +183 -0
  252. cumulusci/tasks/bulkdata/generate_mapping.py +434 -0
  253. cumulusci/tasks/bulkdata/generate_mapping_utils/dependency_map.py +169 -0
  254. cumulusci/tasks/bulkdata/generate_mapping_utils/extract_mapping_file_generator.py +45 -0
  255. cumulusci/tasks/bulkdata/generate_mapping_utils/generate_mapping_from_declarations.py +121 -0
  256. cumulusci/tasks/bulkdata/generate_mapping_utils/load_mapping_file_generator.py +127 -0
  257. cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_generator_post_processes.py +53 -0
  258. cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_transforms.py +139 -0
  259. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_extract_mapping_from_declarations.py +135 -0
  260. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_load_mapping_from_declarations.py +330 -0
  261. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_generator_post_processes.py +60 -0
  262. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_transforms.py +188 -0
  263. cumulusci/tasks/bulkdata/load.py +1196 -0
  264. cumulusci/tasks/bulkdata/mapping_parser.py +811 -0
  265. cumulusci/tasks/bulkdata/query_transformers.py +264 -0
  266. cumulusci/tasks/bulkdata/select_utils.py +792 -0
  267. cumulusci/tasks/bulkdata/snowfakery.py +753 -0
  268. cumulusci/tasks/bulkdata/snowfakery_utils/queue_manager.py +478 -0
  269. cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_run_until.py +141 -0
  270. cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_working_directory.py +53 -0
  271. cumulusci/tasks/bulkdata/snowfakery_utils/subtask_configurator.py +64 -0
  272. cumulusci/tasks/bulkdata/step.py +1242 -0
  273. cumulusci/tasks/bulkdata/tests/__init__.py +0 -0
  274. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_random_strategy.yaml +147 -0
  275. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_annoy_strategy.yaml +123 -0
  276. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy.yaml +313 -0
  277. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy_bulk.yaml +550 -0
  278. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_strategy.yaml +175 -0
  279. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_standard_strategy.yaml +147 -0
  280. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__multiple_needed.yaml +69 -0
  281. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__none_needed.yaml +22 -0
  282. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__one_needed.yaml +24 -0
  283. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_snowfakery_query_salesforce.yaml +25 -0
  284. cumulusci/tasks/bulkdata/tests/cassettes/TestUpdatesIntegrationTests.test_updates_task.yaml +80 -0
  285. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_simple_upsert__rest.yaml +270 -0
  286. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert__rest.yaml +267 -0
  287. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field__rest.yaml +369 -0
  288. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field_rest__duplicate_error.yaml +204 -0
  289. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_fields__bulk.yaml +675 -0
  290. cumulusci/tasks/bulkdata/tests/dummy_data_factory.py +36 -0
  291. cumulusci/tasks/bulkdata/tests/integration_test_utils.py +49 -0
  292. cumulusci/tasks/bulkdata/tests/mapping-oid.yml +87 -0
  293. cumulusci/tasks/bulkdata/tests/mapping_after.yml +38 -0
  294. cumulusci/tasks/bulkdata/tests/mapping_poly.yml +34 -0
  295. cumulusci/tasks/bulkdata/tests/mapping_poly_incomplete.yml +20 -0
  296. cumulusci/tasks/bulkdata/tests/mapping_poly_wrong.yml +21 -0
  297. cumulusci/tasks/bulkdata/tests/mapping_select.yml +20 -0
  298. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_strategy.yml +20 -0
  299. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_number.yml +21 -0
  300. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_strategy.yml +21 -0
  301. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__non_float.yml +21 -0
  302. cumulusci/tasks/bulkdata/tests/mapping_select_missing_priority_fields.yml +22 -0
  303. cumulusci/tasks/bulkdata/tests/mapping_select_no_priority_fields.yml +18 -0
  304. cumulusci/tasks/bulkdata/tests/mapping_simple.yml +27 -0
  305. cumulusci/tasks/bulkdata/tests/mapping_v1.yml +28 -0
  306. cumulusci/tasks/bulkdata/tests/mapping_v2.yml +21 -0
  307. cumulusci/tasks/bulkdata/tests/mapping_v3.yml +32 -0
  308. cumulusci/tasks/bulkdata/tests/mapping_vanilla_sf.yml +69 -0
  309. cumulusci/tasks/bulkdata/tests/mock_data_factory_without_mapping.py +12 -0
  310. cumulusci/tasks/bulkdata/tests/person_accounts.yml +23 -0
  311. cumulusci/tasks/bulkdata/tests/person_accounts_minimal.yml +15 -0
  312. cumulusci/tasks/bulkdata/tests/recordtypes.yml +8 -0
  313. cumulusci/tasks/bulkdata/tests/recordtypes_2.yml +6 -0
  314. cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml +8 -0
  315. cumulusci/tasks/bulkdata/tests/snowfakery/child/child2.yml +3 -0
  316. cumulusci/tasks/bulkdata/tests/snowfakery/child.yml +4 -0
  317. cumulusci/tasks/bulkdata/tests/snowfakery/gen_npsp_standard_objects.recipe.yml +89 -0
  318. cumulusci/tasks/bulkdata/tests/snowfakery/include_parent.yml +3 -0
  319. cumulusci/tasks/bulkdata/tests/snowfakery/npsp_standard_objects_macros.yml +34 -0
  320. cumulusci/tasks/bulkdata/tests/snowfakery/options.recipe.yml +6 -0
  321. cumulusci/tasks/bulkdata/tests/snowfakery/query_snowfakery.recipe.yml +16 -0
  322. cumulusci/tasks/bulkdata/tests/snowfakery/sf_standard_object_macros.yml +83 -0
  323. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.load.yml +2 -0
  324. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.recipe.yml +13 -0
  325. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_2.load.yml +5 -0
  326. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.load.yml +13 -0
  327. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.recipe.yml +12 -0
  328. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels_2.load.yml +13 -0
  329. cumulusci/tasks/bulkdata/tests/snowfakery/unique_values.recipe.yml +4 -0
  330. cumulusci/tasks/bulkdata/tests/snowfakery/upsert.recipe.yml +23 -0
  331. cumulusci/tasks/bulkdata/tests/snowfakery/upsert_2.recipe.yml +29 -0
  332. cumulusci/tasks/bulkdata/tests/snowfakery/upsert_before.yml +10 -0
  333. cumulusci/tasks/bulkdata/tests/test_base_generate_data_tasks.py +61 -0
  334. cumulusci/tasks/bulkdata/tests/test_dates.py +99 -0
  335. cumulusci/tasks/bulkdata/tests/test_delete.py +404 -0
  336. cumulusci/tasks/bulkdata/tests/test_extract.py +1311 -0
  337. cumulusci/tasks/bulkdata/tests/test_factory_utils.py +55 -0
  338. cumulusci/tasks/bulkdata/tests/test_generate_and_load.py +252 -0
  339. cumulusci/tasks/bulkdata/tests/test_generate_from_snowfakery_task.py +343 -0
  340. cumulusci/tasks/bulkdata/tests/test_generatemapping.py +1039 -0
  341. cumulusci/tasks/bulkdata/tests/test_load.py +3175 -0
  342. cumulusci/tasks/bulkdata/tests/test_mapping_parser.py +1658 -0
  343. cumulusci/tasks/bulkdata/tests/test_query_db__joins_self_lookups.yml +12 -0
  344. cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups.yml +26 -0
  345. cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups_select.yml +48 -0
  346. cumulusci/tasks/bulkdata/tests/test_select.py +171 -0
  347. cumulusci/tasks/bulkdata/tests/test_select_utils.py +1057 -0
  348. cumulusci/tasks/bulkdata/tests/test_snowfakery.py +1153 -0
  349. cumulusci/tasks/bulkdata/tests/test_step.py +3957 -0
  350. cumulusci/tasks/bulkdata/tests/test_updates.py +513 -0
  351. cumulusci/tasks/bulkdata/tests/test_upsert.py +1015 -0
  352. cumulusci/tasks/bulkdata/tests/test_utils.py +158 -0
  353. cumulusci/tasks/bulkdata/tests/testdata.db +0 -0
  354. cumulusci/tasks/bulkdata/tests/update_describe.py +50 -0
  355. cumulusci/tasks/bulkdata/tests/update_person_accounts.yml +23 -0
  356. cumulusci/tasks/bulkdata/tests/utils.py +114 -0
  357. cumulusci/tasks/bulkdata/update_data.py +260 -0
  358. cumulusci/tasks/bulkdata/upsert_utils.py +130 -0
  359. cumulusci/tasks/bulkdata/utils.py +249 -0
  360. cumulusci/tasks/command.py +178 -0
  361. cumulusci/tasks/connectedapp.py +186 -0
  362. cumulusci/tasks/create_package_version.py +778 -0
  363. cumulusci/tasks/datadictionary.py +745 -0
  364. cumulusci/tasks/dx_convert_from.py +26 -0
  365. cumulusci/tasks/github/__init__.py +17 -0
  366. cumulusci/tasks/github/base.py +16 -0
  367. cumulusci/tasks/github/commit_status.py +13 -0
  368. cumulusci/tasks/github/merge.py +11 -0
  369. cumulusci/tasks/github/publish.py +11 -0
  370. cumulusci/tasks/github/pull_request.py +11 -0
  371. cumulusci/tasks/github/release.py +11 -0
  372. cumulusci/tasks/github/release_report.py +11 -0
  373. cumulusci/tasks/github/tag.py +11 -0
  374. cumulusci/tasks/github/tests/__init__.py +0 -0
  375. cumulusci/tasks/github/tests/test_util.py +202 -0
  376. cumulusci/tasks/github/tests/test_vcs_migration.py +44 -0
  377. cumulusci/tasks/github/tests/util_github_api.py +666 -0
  378. cumulusci/tasks/github/util.py +252 -0
  379. cumulusci/tasks/marketing_cloud/__init__.py +0 -0
  380. cumulusci/tasks/marketing_cloud/api.py +188 -0
  381. cumulusci/tasks/marketing_cloud/base.py +38 -0
  382. cumulusci/tasks/marketing_cloud/deploy.py +345 -0
  383. cumulusci/tasks/marketing_cloud/get_user_info.py +40 -0
  384. cumulusci/tasks/marketing_cloud/mc_constants.py +1 -0
  385. cumulusci/tasks/marketing_cloud/tests/__init__.py +0 -0
  386. cumulusci/tasks/marketing_cloud/tests/conftest.py +46 -0
  387. cumulusci/tasks/marketing_cloud/tests/expected-payload.json +110 -0
  388. cumulusci/tasks/marketing_cloud/tests/test_api.py +97 -0
  389. cumulusci/tasks/marketing_cloud/tests/test_api_soap_envelopes.py +145 -0
  390. cumulusci/tasks/marketing_cloud/tests/test_base.py +14 -0
  391. cumulusci/tasks/marketing_cloud/tests/test_deploy.py +400 -0
  392. cumulusci/tasks/marketing_cloud/tests/test_get_user_info.py +141 -0
  393. cumulusci/tasks/marketing_cloud/tests/validation-response.json +39 -0
  394. cumulusci/tasks/metadata/__init__.py +0 -0
  395. cumulusci/tasks/metadata/ee_src.py +94 -0
  396. cumulusci/tasks/metadata/managed_src.py +100 -0
  397. cumulusci/tasks/metadata/metadata_map.yml +868 -0
  398. cumulusci/tasks/metadata/modify.py +99 -0
  399. cumulusci/tasks/metadata/package.py +684 -0
  400. cumulusci/tasks/metadata/tests/__init__.py +0 -0
  401. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/.hidden/.keep +0 -0
  402. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/destructiveChanges.xml +9 -0
  403. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package.xml +9 -0
  404. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package_install_uninstall.xml +11 -0
  405. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/reports/namespace__TestFolder/TestReport.report +3 -0
  406. cumulusci/tasks/metadata/tests/sample_package.xml +9 -0
  407. cumulusci/tasks/metadata/tests/test_ee_src.py +112 -0
  408. cumulusci/tasks/metadata/tests/test_managed_src.py +111 -0
  409. cumulusci/tasks/metadata/tests/test_modify.py +123 -0
  410. cumulusci/tasks/metadata/tests/test_package.py +476 -0
  411. cumulusci/tasks/metadata_etl/__init__.py +29 -0
  412. cumulusci/tasks/metadata_etl/base.py +436 -0
  413. cumulusci/tasks/metadata_etl/duplicate_rules.py +24 -0
  414. cumulusci/tasks/metadata_etl/field_sets.py +70 -0
  415. cumulusci/tasks/metadata_etl/help_text.py +92 -0
  416. cumulusci/tasks/metadata_etl/layouts.py +550 -0
  417. cumulusci/tasks/metadata_etl/objects.py +68 -0
  418. cumulusci/tasks/metadata_etl/permissions.py +167 -0
  419. cumulusci/tasks/metadata_etl/picklists.py +221 -0
  420. cumulusci/tasks/metadata_etl/remote_site_settings.py +99 -0
  421. cumulusci/tasks/metadata_etl/sharing.py +138 -0
  422. cumulusci/tasks/metadata_etl/tests/test_base.py +512 -0
  423. cumulusci/tasks/metadata_etl/tests/test_duplicate_rules.py +22 -0
  424. cumulusci/tasks/metadata_etl/tests/test_field_sets.py +156 -0
  425. cumulusci/tasks/metadata_etl/tests/test_help_text.py +387 -0
  426. cumulusci/tasks/metadata_etl/tests/test_ip_ranges.py +85 -0
  427. cumulusci/tasks/metadata_etl/tests/test_layouts.py +858 -0
  428. cumulusci/tasks/metadata_etl/tests/test_objects.py +236 -0
  429. cumulusci/tasks/metadata_etl/tests/test_permissions.py +223 -0
  430. cumulusci/tasks/metadata_etl/tests/test_picklists.py +547 -0
  431. cumulusci/tasks/metadata_etl/tests/test_remote_site_settings.py +46 -0
  432. cumulusci/tasks/metadata_etl/tests/test_sharing.py +333 -0
  433. cumulusci/tasks/metadata_etl/tests/test_value_sets.py +298 -0
  434. cumulusci/tasks/metadata_etl/value_sets.py +106 -0
  435. cumulusci/tasks/metadeploy.py +393 -0
  436. cumulusci/tasks/metaxml.py +88 -0
  437. cumulusci/tasks/preflight/__init__.py +0 -0
  438. cumulusci/tasks/preflight/dataset_load.py +49 -0
  439. cumulusci/tasks/preflight/licenses.py +86 -0
  440. cumulusci/tasks/preflight/packages.py +14 -0
  441. cumulusci/tasks/preflight/permsets.py +23 -0
  442. cumulusci/tasks/preflight/recordtypes.py +16 -0
  443. cumulusci/tasks/preflight/retrieve_tasks.py +30 -0
  444. cumulusci/tasks/preflight/settings.py +77 -0
  445. cumulusci/tasks/preflight/sobjects.py +202 -0
  446. cumulusci/tasks/preflight/tests/test_dataset_load.py +85 -0
  447. cumulusci/tasks/preflight/tests/test_licenses.py +174 -0
  448. cumulusci/tasks/preflight/tests/test_packages.py +14 -0
  449. cumulusci/tasks/preflight/tests/test_permset_preflights.py +51 -0
  450. cumulusci/tasks/preflight/tests/test_recordtypes.py +30 -0
  451. cumulusci/tasks/preflight/tests/test_retrieve_tasks.py +62 -0
  452. cumulusci/tasks/preflight/tests/test_settings.py +130 -0
  453. cumulusci/tasks/preflight/tests/test_sobjects.py +231 -0
  454. cumulusci/tasks/push/README.md +59 -0
  455. cumulusci/tasks/push/__init__.py +0 -0
  456. cumulusci/tasks/push/push_api.py +659 -0
  457. cumulusci/tasks/push/pushfails.py +136 -0
  458. cumulusci/tasks/push/tasks.py +476 -0
  459. cumulusci/tasks/push/tests/conftest.py +263 -0
  460. cumulusci/tasks/push/tests/test_push_api.py +951 -0
  461. cumulusci/tasks/push/tests/test_push_tasks.py +659 -0
  462. cumulusci/tasks/release_notes/README.md +63 -0
  463. cumulusci/tasks/release_notes/__init__.py +0 -0
  464. cumulusci/tasks/release_notes/exceptions.py +5 -0
  465. cumulusci/tasks/release_notes/generator.py +137 -0
  466. cumulusci/tasks/release_notes/parser.py +232 -0
  467. cumulusci/tasks/release_notes/provider.py +44 -0
  468. cumulusci/tasks/release_notes/task.py +300 -0
  469. cumulusci/tasks/release_notes/tests/__init__.py +0 -0
  470. cumulusci/tasks/release_notes/tests/change_notes/full/example1.md +17 -0
  471. cumulusci/tasks/release_notes/tests/change_notes/multi/1.txt +1 -0
  472. cumulusci/tasks/release_notes/tests/change_notes/multi/2.txt +1 -0
  473. cumulusci/tasks/release_notes/tests/change_notes/multi/3.txt +1 -0
  474. cumulusci/tasks/release_notes/tests/change_notes/single/1.txt +1 -0
  475. cumulusci/tasks/release_notes/tests/test_generator.py +582 -0
  476. cumulusci/tasks/release_notes/tests/test_parser.py +867 -0
  477. cumulusci/tasks/release_notes/tests/test_provider.py +512 -0
  478. cumulusci/tasks/release_notes/tests/test_task.py +461 -0
  479. cumulusci/tasks/release_notes/tests/utils.py +153 -0
  480. cumulusci/tasks/robotframework/__init__.py +3 -0
  481. cumulusci/tasks/robotframework/debugger/DebugListener.py +100 -0
  482. cumulusci/tasks/robotframework/debugger/__init__.py +10 -0
  483. cumulusci/tasks/robotframework/debugger/model.py +87 -0
  484. cumulusci/tasks/robotframework/debugger/ui.py +259 -0
  485. cumulusci/tasks/robotframework/libdoc.py +269 -0
  486. cumulusci/tasks/robotframework/robotframework.py +392 -0
  487. cumulusci/tasks/robotframework/stylesheet.css +130 -0
  488. cumulusci/tasks/robotframework/template.html +109 -0
  489. cumulusci/tasks/robotframework/tests/TestLibrary.py +18 -0
  490. cumulusci/tasks/robotframework/tests/TestPageObjects.py +31 -0
  491. cumulusci/tasks/robotframework/tests/TestResource.robot +8 -0
  492. cumulusci/tasks/robotframework/tests/failing_tests.robot +16 -0
  493. cumulusci/tasks/robotframework/tests/performance.robot +23 -0
  494. cumulusci/tasks/robotframework/tests/test_browser_proxies.py +137 -0
  495. cumulusci/tasks/robotframework/tests/test_debugger.py +360 -0
  496. cumulusci/tasks/robotframework/tests/test_robot_parallel.py +141 -0
  497. cumulusci/tasks/robotframework/tests/test_robotframework.py +860 -0
  498. cumulusci/tasks/salesforce/BaseRetrieveMetadata.py +58 -0
  499. cumulusci/tasks/salesforce/BaseSalesforceApiTask.py +45 -0
  500. cumulusci/tasks/salesforce/BaseSalesforceMetadataApiTask.py +18 -0
  501. cumulusci/tasks/salesforce/BaseSalesforceTask.py +4 -0
  502. cumulusci/tasks/salesforce/BaseUninstallMetadata.py +41 -0
  503. cumulusci/tasks/salesforce/CreateCommunity.py +124 -0
  504. cumulusci/tasks/salesforce/CreatePackage.py +29 -0
  505. cumulusci/tasks/salesforce/Deploy.py +240 -0
  506. cumulusci/tasks/salesforce/DeployBundles.py +88 -0
  507. cumulusci/tasks/salesforce/DescribeMetadataTypes.py +26 -0
  508. cumulusci/tasks/salesforce/EnsureRecordTypes.py +202 -0
  509. cumulusci/tasks/salesforce/GetInstalledPackages.py +8 -0
  510. cumulusci/tasks/salesforce/ListCommunities.py +40 -0
  511. cumulusci/tasks/salesforce/ListCommunityTemplates.py +19 -0
  512. cumulusci/tasks/salesforce/PublishCommunity.py +62 -0
  513. cumulusci/tasks/salesforce/RetrievePackaged.py +41 -0
  514. cumulusci/tasks/salesforce/RetrieveReportsAndDashboards.py +82 -0
  515. cumulusci/tasks/salesforce/RetrieveUnpackaged.py +36 -0
  516. cumulusci/tasks/salesforce/SOQLQuery.py +39 -0
  517. cumulusci/tasks/salesforce/UninstallLocal.py +15 -0
  518. cumulusci/tasks/salesforce/UninstallLocalBundles.py +28 -0
  519. cumulusci/tasks/salesforce/UninstallLocalNamespacedBundles.py +58 -0
  520. cumulusci/tasks/salesforce/UninstallPackage.py +32 -0
  521. cumulusci/tasks/salesforce/UninstallPackaged.py +56 -0
  522. cumulusci/tasks/salesforce/UpdateAdminProfile.py +8 -0
  523. cumulusci/tasks/salesforce/__init__.py +79 -0
  524. cumulusci/tasks/salesforce/activate_flow.py +74 -0
  525. cumulusci/tasks/salesforce/check_components.py +324 -0
  526. cumulusci/tasks/salesforce/composite.py +142 -0
  527. cumulusci/tasks/salesforce/create_permission_sets.py +35 -0
  528. cumulusci/tasks/salesforce/custom_settings.py +134 -0
  529. cumulusci/tasks/salesforce/custom_settings_wait.py +132 -0
  530. cumulusci/tasks/salesforce/enable_prediction.py +107 -0
  531. cumulusci/tasks/salesforce/insert_record.py +40 -0
  532. cumulusci/tasks/salesforce/install_package_version.py +242 -0
  533. cumulusci/tasks/salesforce/license_preflights.py +8 -0
  534. cumulusci/tasks/salesforce/network_member_group.py +178 -0
  535. cumulusci/tasks/salesforce/nonsourcetracking.py +228 -0
  536. cumulusci/tasks/salesforce/org_settings.py +193 -0
  537. cumulusci/tasks/salesforce/package_upload.py +328 -0
  538. cumulusci/tasks/salesforce/profiles.py +74 -0
  539. cumulusci/tasks/salesforce/promote_package_version.py +376 -0
  540. cumulusci/tasks/salesforce/retrieve_profile.py +195 -0
  541. cumulusci/tasks/salesforce/salesforce_files.py +244 -0
  542. cumulusci/tasks/salesforce/sourcetracking.py +507 -0
  543. cumulusci/tasks/salesforce/tests/__init__.py +3 -0
  544. cumulusci/tasks/salesforce/tests/test_CreateCommunity.py +278 -0
  545. cumulusci/tasks/salesforce/tests/test_CreatePackage.py +22 -0
  546. cumulusci/tasks/salesforce/tests/test_Deploy.py +470 -0
  547. cumulusci/tasks/salesforce/tests/test_DeployBundles.py +76 -0
  548. cumulusci/tasks/salesforce/tests/test_EnsureRecordTypes.py +345 -0
  549. cumulusci/tasks/salesforce/tests/test_ListCommunities.py +84 -0
  550. cumulusci/tasks/salesforce/tests/test_ListCommunityTemplates.py +49 -0
  551. cumulusci/tasks/salesforce/tests/test_PackageUpload.py +547 -0
  552. cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py +699 -0
  553. cumulusci/tasks/salesforce/tests/test_PublishCommunity.py +181 -0
  554. cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py +24 -0
  555. cumulusci/tasks/salesforce/tests/test_RetrieveReportsAndDashboards.py +56 -0
  556. cumulusci/tasks/salesforce/tests/test_RetrieveUnpackaged.py +21 -0
  557. cumulusci/tasks/salesforce/tests/test_SOQLQuery.py +30 -0
  558. cumulusci/tasks/salesforce/tests/test_UninstallLocal.py +15 -0
  559. cumulusci/tasks/salesforce/tests/test_UninstallLocalBundles.py +19 -0
  560. cumulusci/tasks/salesforce/tests/test_UninstallLocalNamespacedBundles.py +22 -0
  561. cumulusci/tasks/salesforce/tests/test_UninstallPackage.py +19 -0
  562. cumulusci/tasks/salesforce/tests/test_UninstallPackaged.py +66 -0
  563. cumulusci/tasks/salesforce/tests/test_UninstallPackagedIncremental.py +127 -0
  564. cumulusci/tasks/salesforce/tests/test_activate_flow.py +132 -0
  565. cumulusci/tasks/salesforce/tests/test_base_tasks.py +110 -0
  566. cumulusci/tasks/salesforce/tests/test_check_components.py +445 -0
  567. cumulusci/tasks/salesforce/tests/test_composite.py +250 -0
  568. cumulusci/tasks/salesforce/tests/test_create_permission_sets.py +41 -0
  569. cumulusci/tasks/salesforce/tests/test_custom_settings.py +227 -0
  570. cumulusci/tasks/salesforce/tests/test_custom_settings_wait.py +174 -0
  571. cumulusci/tasks/salesforce/tests/test_describemetadatatypes.py +18 -0
  572. cumulusci/tasks/salesforce/tests/test_enable_prediction.py +240 -0
  573. cumulusci/tasks/salesforce/tests/test_insert_record.py +110 -0
  574. cumulusci/tasks/salesforce/tests/test_install_package_version.py +464 -0
  575. cumulusci/tasks/salesforce/tests/test_network_member_group.py +444 -0
  576. cumulusci/tasks/salesforce/tests/test_nonsourcetracking.py +235 -0
  577. cumulusci/tasks/salesforce/tests/test_org_settings.py +407 -0
  578. cumulusci/tasks/salesforce/tests/test_profiles.py +202 -0
  579. cumulusci/tasks/salesforce/tests/test_retrieve_profile.py +287 -0
  580. cumulusci/tasks/salesforce/tests/test_salesforce_files.py +228 -0
  581. cumulusci/tasks/salesforce/tests/test_sourcetracking.py +350 -0
  582. cumulusci/tasks/salesforce/tests/test_trigger_handlers.py +300 -0
  583. cumulusci/tasks/salesforce/tests/test_update_dependencies.py +509 -0
  584. cumulusci/tasks/salesforce/tests/util.py +79 -0
  585. cumulusci/tasks/salesforce/trigger_handlers.py +119 -0
  586. cumulusci/tasks/salesforce/uninstall_packaged_incremental.py +136 -0
  587. cumulusci/tasks/salesforce/update_dependencies.py +290 -0
  588. cumulusci/tasks/salesforce/update_profile.py +339 -0
  589. cumulusci/tasks/salesforce/users/permsets.py +227 -0
  590. cumulusci/tasks/salesforce/users/photos.py +162 -0
  591. cumulusci/tasks/salesforce/users/tests/photo.mock.txt +1 -0
  592. cumulusci/tasks/salesforce/users/tests/test_permsets.py +950 -0
  593. cumulusci/tasks/salesforce/users/tests/test_photos.py +373 -0
  594. cumulusci/tasks/sample_data/capture_sample_data.py +77 -0
  595. cumulusci/tasks/sample_data/load_sample_data.py +85 -0
  596. cumulusci/tasks/sample_data/test_capture_sample_data.py +117 -0
  597. cumulusci/tasks/sample_data/test_load_sample_data.py +121 -0
  598. cumulusci/tasks/sfdx.py +83 -0
  599. cumulusci/tasks/tests/__init__.py +1 -0
  600. cumulusci/tasks/tests/conftest.py +30 -0
  601. cumulusci/tasks/tests/test_command.py +129 -0
  602. cumulusci/tasks/tests/test_connectedapp.py +236 -0
  603. cumulusci/tasks/tests/test_create_package_version.py +847 -0
  604. cumulusci/tasks/tests/test_datadictionary.py +1575 -0
  605. cumulusci/tasks/tests/test_dx_convert_from.py +60 -0
  606. cumulusci/tasks/tests/test_metadeploy.py +624 -0
  607. cumulusci/tasks/tests/test_metaxml.py +99 -0
  608. cumulusci/tasks/tests/test_promote_package_version.py +488 -0
  609. cumulusci/tasks/tests/test_pushfails.py +96 -0
  610. cumulusci/tasks/tests/test_salesforce.py +72 -0
  611. cumulusci/tasks/tests/test_sfdx.py +105 -0
  612. cumulusci/tasks/tests/test_util.py +207 -0
  613. cumulusci/tasks/util.py +261 -0
  614. cumulusci/tasks/vcs/__init__.py +19 -0
  615. cumulusci/tasks/vcs/commit_status.py +58 -0
  616. cumulusci/tasks/vcs/create_commit_status.py +37 -0
  617. cumulusci/tasks/vcs/download_extract.py +199 -0
  618. cumulusci/tasks/vcs/merge.py +298 -0
  619. cumulusci/tasks/vcs/publish.py +207 -0
  620. cumulusci/tasks/vcs/pull_request.py +9 -0
  621. cumulusci/tasks/vcs/release.py +134 -0
  622. cumulusci/tasks/vcs/release_report.py +105 -0
  623. cumulusci/tasks/vcs/tag.py +31 -0
  624. cumulusci/tasks/vcs/tests/github/test_commit_status.py +196 -0
  625. cumulusci/tasks/vcs/tests/github/test_download_extract.py +896 -0
  626. cumulusci/tasks/vcs/tests/github/test_merge.py +1118 -0
  627. cumulusci/tasks/vcs/tests/github/test_publish.py +823 -0
  628. cumulusci/tasks/vcs/tests/github/test_pull_request.py +29 -0
  629. cumulusci/tasks/vcs/tests/github/test_release.py +390 -0
  630. cumulusci/tasks/vcs/tests/github/test_release_report.py +109 -0
  631. cumulusci/tasks/vcs/tests/github/test_tag.py +90 -0
  632. cumulusci/tasks/vlocity/exceptions.py +2 -0
  633. cumulusci/tasks/vlocity/tests/test_vlocity.py +283 -0
  634. cumulusci/tasks/vlocity/vlocity.py +342 -0
  635. cumulusci/tests/__init__.py +1 -0
  636. cumulusci/tests/cassettes/GET_sobjects_Account_PersonAccount_describe.yaml +18 -0
  637. cumulusci/tests/cassettes/TestIntegrationInfrastructure.test_integration_tests.yaml +19 -0
  638. cumulusci/tests/pytest_plugins/pytest_sf_orgconnect.py +307 -0
  639. cumulusci/tests/pytest_plugins/pytest_sf_vcr.py +275 -0
  640. cumulusci/tests/pytest_plugins/pytest_sf_vcr_serializer.py +160 -0
  641. cumulusci/tests/pytest_plugins/pytest_typeguard.py +5 -0
  642. cumulusci/tests/pytest_plugins/test_vcr_string_compressor.py +49 -0
  643. cumulusci/tests/pytest_plugins/vcr_string_compressor.py +97 -0
  644. cumulusci/tests/shared_cassettes/GET_sobjects_Account_describe.yaml +18 -0
  645. cumulusci/tests/shared_cassettes/GET_sobjects_Case_describe.yaml +18 -0
  646. cumulusci/tests/shared_cassettes/GET_sobjects_Contact_describe.yaml +4838 -0
  647. cumulusci/tests/shared_cassettes/GET_sobjects_Custom__c_describe.yaml +242 -0
  648. cumulusci/tests/shared_cassettes/GET_sobjects_Event_describe.yaml +19 -0
  649. cumulusci/tests/shared_cassettes/GET_sobjects_Global_describe.yaml +1338 -0
  650. cumulusci/tests/shared_cassettes/GET_sobjects_Lead_describe.yaml +18 -0
  651. cumulusci/tests/shared_cassettes/GET_sobjects_OpportunityContactRole_describe.yaml +34 -0
  652. cumulusci/tests/shared_cassettes/GET_sobjects_Opportunity_describe.yaml +1261 -0
  653. cumulusci/tests/shared_cassettes/GET_sobjects_Organization.yaml +49 -0
  654. cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfoList_xml.tpl +15 -0
  655. cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfo_xml.tpl +13 -0
  656. cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_insert_xml.tpl +24 -0
  657. cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_upsert_xml.tpl +25 -0
  658. cumulusci/tests/test_entry_points.py +20 -0
  659. cumulusci/tests/test_integration_infrastructure.py +131 -0
  660. cumulusci/tests/test_main.py +9 -0
  661. cumulusci/tests/test_schema.py +32 -0
  662. cumulusci/tests/test_utils.py +657 -0
  663. cumulusci/tests/test_vcr_serializer.py +134 -0
  664. cumulusci/tests/uncompressed_cassette.yaml +83 -0
  665. cumulusci/tests/util.py +344 -0
  666. cumulusci/utils/__init__.py +731 -0
  667. cumulusci/utils/classutils.py +9 -0
  668. cumulusci/utils/collections.py +32 -0
  669. cumulusci/utils/deprecation.py +11 -0
  670. cumulusci/utils/encryption.py +31 -0
  671. cumulusci/utils/fileutils.py +295 -0
  672. cumulusci/utils/git.py +142 -0
  673. cumulusci/utils/http/multi_request.py +214 -0
  674. cumulusci/utils/http/requests_utils.py +103 -0
  675. cumulusci/utils/http/tests/cassettes/ManualEditTestCompositeParallelSalesforce.test_http_headers.yaml +32 -0
  676. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_composite_parallel_salesforce.yaml +65 -0
  677. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_errors.yaml +24 -0
  678. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_reference_ids.yaml +49 -0
  679. cumulusci/utils/http/tests/test_multi_request.py +255 -0
  680. cumulusci/utils/iterators.py +21 -0
  681. cumulusci/utils/logging.py +128 -0
  682. cumulusci/utils/metaprogramming.py +10 -0
  683. cumulusci/utils/options.py +138 -0
  684. cumulusci/utils/parallel/queries_in_parallel/run_queries_in_parallel.py +29 -0
  685. cumulusci/utils/parallel/queries_in_parallel/tests/test_run_queries_in_parallel.py +50 -0
  686. cumulusci/utils/parallel/task_worker_queues/parallel_worker.py +238 -0
  687. cumulusci/utils/parallel/task_worker_queues/parallel_worker_queue.py +243 -0
  688. cumulusci/utils/parallel/task_worker_queues/tests/test_parallel_worker.py +353 -0
  689. cumulusci/utils/salesforce/count_sobjects.py +46 -0
  690. cumulusci/utils/salesforce/soql.py +17 -0
  691. cumulusci/utils/salesforce/tests/cassettes/ManualEdit_TestCountSObjects.test_count_sobjects__network_errors.yaml +23 -0
  692. cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects__errors.yaml +33 -0
  693. cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects_simple.yaml +29 -0
  694. cumulusci/utils/salesforce/tests/test_count_sobjects.py +29 -0
  695. cumulusci/utils/salesforce/tests/test_soql.py +30 -0
  696. cumulusci/utils/tests/cassettes/ManualEditTestDescribeOrg.test_minimal_schema.yaml +36 -0
  697. cumulusci/utils/tests/cassettes/ManualEdit_test_describe_to_sql.yaml +191 -0
  698. cumulusci/utils/tests/test_fileutils.py +284 -0
  699. cumulusci/utils/tests/test_git.py +85 -0
  700. cumulusci/utils/tests/test_logging.py +70 -0
  701. cumulusci/utils/tests/test_option_parsing.py +188 -0
  702. cumulusci/utils/tests/test_org_schema.py +691 -0
  703. cumulusci/utils/tests/test_org_schema_models.py +79 -0
  704. cumulusci/utils/tests/test_waiting.py +25 -0
  705. cumulusci/utils/version_strings.py +391 -0
  706. cumulusci/utils/waiting.py +42 -0
  707. cumulusci/utils/xml/__init__.py +91 -0
  708. cumulusci/utils/xml/metadata_tree.py +299 -0
  709. cumulusci/utils/xml/robot_xml.py +114 -0
  710. cumulusci/utils/xml/salesforce_encoding.py +100 -0
  711. cumulusci/utils/xml/test/test_metadata_tree.py +251 -0
  712. cumulusci/utils/xml/test/test_salesforce_encoding.py +173 -0
  713. cumulusci/utils/yaml/cumulusci_yml.py +401 -0
  714. cumulusci/utils/yaml/model_parser.py +156 -0
  715. cumulusci/utils/yaml/safer_loader.py +74 -0
  716. cumulusci/utils/yaml/tests/bad_cci.yml +5 -0
  717. cumulusci/utils/yaml/tests/cassettes/TestCumulusciYml.test_validate_url__with_errors.yaml +20 -0
  718. cumulusci/utils/yaml/tests/test_cumulusci_yml.py +286 -0
  719. cumulusci/utils/yaml/tests/test_model_parser.py +175 -0
  720. cumulusci/utils/yaml/tests/test_safer_loader.py +88 -0
  721. cumulusci/utils/ziputils.py +61 -0
  722. cumulusci/vcs/base.py +143 -0
  723. cumulusci/vcs/bootstrap.py +272 -0
  724. cumulusci/vcs/github/__init__.py +24 -0
  725. cumulusci/vcs/github/adapter.py +689 -0
  726. cumulusci/vcs/github/release_notes/generator.py +219 -0
  727. cumulusci/vcs/github/release_notes/parser.py +151 -0
  728. cumulusci/vcs/github/release_notes/provider.py +143 -0
  729. cumulusci/vcs/github/service.py +569 -0
  730. cumulusci/vcs/github/tests/test_adapter.py +138 -0
  731. cumulusci/vcs/github/tests/test_service.py +408 -0
  732. cumulusci/vcs/models.py +586 -0
  733. cumulusci/vcs/tests/conftest.py +41 -0
  734. cumulusci/vcs/tests/dummy_service.py +241 -0
  735. cumulusci/vcs/tests/test_vcs_base.py +687 -0
  736. cumulusci/vcs/tests/test_vcs_bootstrap.py +727 -0
  737. cumulusci/vcs/utils/__init__.py +31 -0
  738. cumulusci/vcs/vcs_source.py +287 -0
  739. cumulusci_plus-5.0.0.dist-info/METADATA +145 -0
  740. cumulusci_plus-5.0.0.dist-info/RECORD +744 -0
  741. cumulusci_plus-5.0.0.dist-info/WHEEL +4 -0
  742. cumulusci_plus-5.0.0.dist-info/entry_points.txt +3 -0
  743. cumulusci_plus-5.0.0.dist-info/licenses/AUTHORS.rst +41 -0
  744. cumulusci_plus-5.0.0.dist-info/licenses/LICENSE +30 -0
@@ -0,0 +1,56 @@
1
+ from cumulusci.salesforce_api.metadata import ApiRetrievePackaged
2
+ from cumulusci.tasks.salesforce import UninstallLocal
3
+ from cumulusci.utils import temporary_dir, zip_subfolder
4
+
5
+
6
+ class UninstallPackaged(UninstallLocal):
7
+
8
+ task_options = {
9
+ "package": {
10
+ "description": "The package name to uninstall. All metadata from the package will be retrieved and a custom destructiveChanges.xml package will be constructed and deployed to delete all deleteable metadata from the package. Defaults to project__package__name",
11
+ "required": True,
12
+ },
13
+ "purge_on_delete": {
14
+ "description": "Sets the purgeOnDelete option for the deployment. Defaults to True",
15
+ "required": True,
16
+ },
17
+ "dry_run": {
18
+ "description": "Perform a dry run of the operation without actually deleting any components, and display the components that would be deleted."
19
+ },
20
+ }
21
+
22
+ def _init_options(self, kwargs):
23
+ super(UninstallPackaged, self)._init_options(kwargs)
24
+ if "package" not in self.options:
25
+ self.options["package"] = self.project_config.project__package__name
26
+
27
+ def _retrieve_packaged(self):
28
+ retrieve_api = ApiRetrievePackaged(
29
+ self,
30
+ self.options["package"],
31
+ self.project_config.project__package__api_version,
32
+ )
33
+ packaged = retrieve_api()
34
+ packaged = zip_subfolder(packaged, self.options["package"])
35
+ return packaged
36
+
37
+ def _get_destructive_changes(self, path=None):
38
+ self.logger.info(
39
+ "Retrieving metadata in package {} from target org".format(
40
+ self.options["package"]
41
+ )
42
+ )
43
+ packaged = self._retrieve_packaged()
44
+
45
+ with temporary_dir() as tempdir:
46
+ packaged.extractall(tempdir)
47
+ destructive_changes = super(
48
+ UninstallPackaged, self
49
+ )._get_destructive_changes(tempdir)
50
+
51
+ self.logger.info(
52
+ "Deleting metadata in package {} from target org".format(
53
+ self.options["package"]
54
+ )
55
+ )
56
+ return destructive_changes
@@ -0,0 +1,8 @@
1
+ # for backwards compatibility
2
+ from cumulusci.tasks.salesforce.update_profile import * # noqa
3
+ from cumulusci.utils.deprecation import warn_moved
4
+
5
+ warn_moved(
6
+ "cumulusci.tasks.salesforce.update_profile",
7
+ __name__,
8
+ )
@@ -0,0 +1,79 @@
1
+ """Salesforce tasks
2
+
3
+ This package uses a lazy import system inspired by werkzeug
4
+ (for startup speed and to avoid problems with import cycles).
5
+ We should be able to replace LazyModule with a module-level __getattr__
6
+ one we drop support for Python 3.6.
7
+ """
8
+
9
+ from types import ModuleType
10
+ import sys
11
+
12
+ ORIGINS = {
13
+ "BaseRetrieveMetadata": "cumulusci.tasks.salesforce.BaseRetrieveMetadata",
14
+ "BaseSalesforceTask": "cumulusci.tasks.salesforce.BaseSalesforceTask",
15
+ "BaseSalesforceApiTask": "cumulusci.tasks.salesforce.BaseSalesforceApiTask",
16
+ "BaseSalesforceMetadataApiTask": "cumulusci.tasks.salesforce.BaseSalesforceMetadataApiTask",
17
+ "BaseUninstallMetadata": "cumulusci.tasks.salesforce.BaseUninstallMetadata",
18
+ "CreateCommunity": "cumulusci.tasks.salesforce.CreateCommunity",
19
+ "CreatePackage": "cumulusci.tasks.salesforce.CreatePackage",
20
+ "Deploy": "cumulusci.tasks.salesforce.Deploy",
21
+ "DeployBundles": "cumulusci.tasks.salesforce.DeployBundles",
22
+ "EnsureRecordTypes": "cumulusci.tasks.salesforce.EnsureRecordTypes",
23
+ "GetInstalledPackages": "cumulusci.tasks.preflight.packages",
24
+ "InstallPackageVersion": "cumulusci.tasks.salesforce.install_package_version",
25
+ "ListCommunities": "cumulusci.tasks.salesforce.ListCommunities",
26
+ "ListCommunityTemplates": "cumulusci.tasks.salesforce.ListCommunityTemplates",
27
+ "LoadCustomSettings": "cumulusci.tasks.salesforce.custom_settings",
28
+ "PackageUpload": "cumulusci.tasks.salesforce.package_upload",
29
+ "ProfileGrantAllAccess": "cumulusci.tasks.salesforce.update_profile",
30
+ "PublishCommunity": "cumulusci.tasks.salesforce.PublishCommunity",
31
+ "RetrievePackaged": "cumulusci.tasks.salesforce.RetrievePackaged",
32
+ "RetrieveReportsAndDashboards": "cumulusci.tasks.salesforce.RetrieveReportsAndDashboards",
33
+ "DescribeMetadataTypes": "cumulusci.tasks.salesforce.DescribeMetadataTypes",
34
+ "RetrieveUnpackaged": "cumulusci.tasks.salesforce.RetrieveUnpackaged",
35
+ "SOQLQuery": "cumulusci.tasks.salesforce.SOQLQuery",
36
+ "SetTDTMHandlerStatus": "cumulusci.tasks.salesforce.trigger_handlers",
37
+ "UninstallLocal": "cumulusci.tasks.salesforce.UninstallLocal",
38
+ "UninstallLocalBundles": "cumulusci.tasks.salesforce.UninstallLocalBundles",
39
+ "UninstallLocalNamespacedBundles": "cumulusci.tasks.salesforce.UninstallLocalNamespacedBundles",
40
+ "UninstallPackage": "cumulusci.tasks.salesforce.UninstallPackage",
41
+ "UninstallPackaged": "cumulusci.tasks.salesforce.UninstallPackaged",
42
+ "UninstallPackagedIncremental": "cumulusci.tasks.salesforce.uninstall_packaged_incremental",
43
+ "UpdateDependencies": "cumulusci.tasks.salesforce.update_dependencies",
44
+ "UpdateProfile": "cumulusci.tasks.salesforce.update_profile",
45
+ "UpdateAdminProfile": "cumulusci.tasks.salesforce.update_profile",
46
+ }
47
+
48
+
49
+ class LazyModule(ModuleType):
50
+ def __getattr__(self, name):
51
+ # Import and set attribute on demand
52
+ # (__getattr__ is only called if it hasn't been set already)
53
+ if name in ORIGINS:
54
+ origin = ORIGINS[name]
55
+ module = __import__(origin, None, None, [name])
56
+ setattr(self, name, getattr(module, name))
57
+ return ModuleType.__getattribute__(self, name)
58
+
59
+ def __setattr__(self, name, value):
60
+ # Avoid shadowing our intended classes with submodules of the same name
61
+ # when they are imported.
62
+ if name in ORIGINS and isinstance(value, ModuleType):
63
+ return
64
+ ModuleType.__setattr__(self, name, value)
65
+
66
+
67
+ # create LazyModule and replace the reference to ourself in sys.modules
68
+ new_module = sys.modules[__name__] = LazyModule(__name__)
69
+
70
+ # copy over some special attributes
71
+ new_module.__dict__.update(
72
+ {
73
+ "__doc__": __doc__,
74
+ "__file__": __file__,
75
+ "__path__": __path__,
76
+ "__spec__": __spec__,
77
+ "__all__": tuple(ORIGINS),
78
+ }
79
+ )
@@ -0,0 +1,74 @@
1
+ from cumulusci.core.exceptions import TaskOptionsError
2
+ from cumulusci.core.utils import process_list_arg
3
+ from cumulusci.tasks.salesforce import BaseSalesforceApiTask
4
+
5
+
6
+ class ActivateFlow(BaseSalesforceApiTask):
7
+ """
8
+ Activate the Flows with the supplied Developer Names
9
+ """
10
+
11
+ task_options = {
12
+ "developer_names": {
13
+ "description": "List of DeveloperNames to query in SOQL",
14
+ "required": True,
15
+ },
16
+ "status": {
17
+ "description": "Flag to check whether to activate or deactivate the flow",
18
+ "required": False,
19
+ },
20
+ }
21
+
22
+ def _init_options(self, kwargs):
23
+ super(ActivateFlow, self)._init_options(kwargs)
24
+ self.options["developer_names"] = process_list_arg(
25
+ self.options.get("developer_names")
26
+ )
27
+ self.api_version = self.project_config.project__api_version
28
+ if not self.options["developer_names"]:
29
+ raise TaskOptionsError(
30
+ "Error you are missing developer_names definition in your task cumulusci.yml file. Please pass in developer_names for your task configuration or use -o to developer_names as a commandline argument"
31
+ )
32
+
33
+ def _run_task(self):
34
+ if self.options["status"]:
35
+ self.logger.info(
36
+ f"Activating the following Flows: {self.options['developer_names']}"
37
+ )
38
+ else:
39
+ self.logger.info(
40
+ f"Deactivating the following Flows: {self.options['developer_names']}"
41
+ )
42
+
43
+ self.logger.info("Querying flow definitions...")
44
+ result = self.tooling.query(
45
+ "SELECT Id, ActiveVersion.VersionNumber, LatestVersion.VersionNumber, DeveloperName FROM FlowDefinition WHERE DeveloperName IN ({0})".format(
46
+ ",".join([f"'{n}'" for n in self.options["developer_names"]])
47
+ )
48
+ )
49
+
50
+ results = []
51
+ for listed_flow in result["records"]:
52
+ results.append(listed_flow["DeveloperName"])
53
+ self.logger.info(f'Processing: {listed_flow["DeveloperName"]}')
54
+ path = f"tooling/sobjects/FlowDefinition/{listed_flow['Id']}"
55
+
56
+ urlpath = self.sf.base_url + path
57
+
58
+ if self.options["status"]:
59
+ updated_version_number = listed_flow["LatestVersion"]["VersionNumber"]
60
+ else:
61
+ updated_version_number = 0
62
+ data = {"Metadata": {"activeVersionNumber": updated_version_number}}
63
+ self.logger.info(urlpath)
64
+ response = self.tooling._call_salesforce("PATCH", urlpath, json=data)
65
+ self.logger.info(response)
66
+
67
+ excluded = []
68
+ for i in self.options["developer_names"]:
69
+ if i not in results:
70
+ excluded.append(i)
71
+ if len(excluded) > 0:
72
+ self.logger.warning(
73
+ f"The following developer names were not found: {excluded}"
74
+ )
@@ -0,0 +1,324 @@
1
+ import json
2
+ import os
3
+ import shutil
4
+ import tempfile
5
+ from collections import defaultdict
6
+ from itertools import chain
7
+ from xml.etree.ElementTree import ParseError
8
+
9
+ from defusedxml.minidom import parseString
10
+
11
+ from cumulusci.core.config import FlowConfig, TaskConfig
12
+ from cumulusci.core.exceptions import TaskOptionsError
13
+ from cumulusci.core.flowrunner import FlowCoordinator
14
+ from cumulusci.core.sfdx import convert_sfdx_source
15
+ from cumulusci.core.utils import process_list_arg
16
+ from cumulusci.salesforce_api.metadata import ApiRetrieveUnpackaged
17
+ from cumulusci.tasks.metadata.package import process_common_components
18
+ from cumulusci.tasks.salesforce import BaseSalesforceTask
19
+ from cumulusci.utils import cd
20
+ from cumulusci.utils.xml import metadata_tree
21
+
22
+
23
+ class CheckComponents(BaseSalesforceTask):
24
+ api_retrieve_unpackaged = ApiRetrieveUnpackaged
25
+ task_options = {
26
+ "paths": {
27
+ "description": "List of deploy paths to check",
28
+ "required": False,
29
+ },
30
+ "name": {
31
+ "description": "The name of the current plan or flow to detect deploy paths",
32
+ "required": False,
33
+ },
34
+ }
35
+ deploy_paths = []
36
+
37
+ def _init_options(self, kwargs):
38
+ super(CheckComponents, self)._init_options(kwargs)
39
+ if "paths" in self.options and "name" in self.options:
40
+ raise TaskOptionsError("Please provide either --paths or --name")
41
+ if "paths" not in self.options and "name" not in self.options:
42
+ raise TaskOptionsError(
43
+ "This task requires a plan/flow name or paths options. Pass --paths or --name options"
44
+ )
45
+
46
+ def _run_task(self):
47
+ # Check if paths are provided in options. Assuming to only check for those paths
48
+ paths = self.options.get("paths")
49
+ plan_or_flow_name = self.options.get("name")
50
+
51
+ (
52
+ components,
53
+ api_retrieve_unpackaged_response,
54
+ ) = self.get_repo_existing_components(plan_or_flow_name, paths)
55
+
56
+ if not components:
57
+ self.logger.info("No components found in deploy path")
58
+ raise TaskOptionsError("No plan or paths options provided")
59
+
60
+ self.logger.debug("Components detected at source")
61
+ for component_type, component_names in components.items():
62
+ self.logger.debug(f"{component_type}: {', '.join(component_names)}")
63
+ # check common components
64
+ components.pop("Settings", None)
65
+ existing_components = process_common_components(
66
+ api_retrieve_unpackaged_response, components
67
+ )
68
+
69
+ if existing_components:
70
+ self.logger.info("Components exists in the target org:")
71
+ for component_type, component_names in existing_components.items():
72
+ self.logger.info(f"{component_type}: {', '.join(component_names)}")
73
+ self.return_values["existing_components"] = existing_components
74
+ else:
75
+ self.logger.info(
76
+ "No components from the deploy paths exist in the target org."
77
+ )
78
+
79
+ def get_repo_existing_components(self, plan_or_flow_name, paths=""):
80
+ if paths:
81
+ paths = process_list_arg(paths)
82
+ self.logger.info(f"Using provided paths: {paths}")
83
+ self.deploy_paths = paths
84
+ elif plan_or_flow_name:
85
+ # if path is not provided
86
+ is_plan = self._is_plan(plan_or_flow_name)
87
+ if is_plan is None:
88
+ raise TaskOptionsError(
89
+ f"Plan or flow name '{plan_or_flow_name}' not found"
90
+ )
91
+
92
+ self.logger.info(
93
+ f"Analyzing project {'plan' if is_plan else 'flow'}: {plan_or_flow_name}"
94
+ )
95
+
96
+ # load deploy paths from all the steps in plan or flow
97
+ self._load_deploy_paths(plan_or_flow_name, is_plan)
98
+ if not self.deploy_paths:
99
+ self.logger.warning("No deploy paths found in the plan or flow.")
100
+ return
101
+ self.logger.debug(
102
+ f"deploy paths found in the plan or flow.{self.deploy_paths}"
103
+ )
104
+ # Temp dir to copy all deploy paths from task options
105
+ temp_dir = tempfile.mkdtemp()
106
+ self.logger.info(f"Temporary deploy directory created: {temp_dir}")
107
+ mdapi_components = {}
108
+ mdapi_response_messages = []
109
+ for path in self.deploy_paths:
110
+ full_path = os.path.join(self.project_config.repo_root, path)
111
+ if not os.path.exists(full_path):
112
+ self.logger.info(f"Skipping path: '{path}' - path doesn't exist")
113
+ continue
114
+ elif "package.xml" in os.listdir(full_path):
115
+ package_xml_path = os.path.join(full_path, "package.xml")
116
+ source_xml_tree = metadata_tree.parse(package_xml_path)
117
+ components = metadata_tree.parse_package_xml_types(
118
+ "name", source_xml_tree
119
+ )
120
+ response_messages = self._get_api_object_responce(
121
+ package_xml_path, source_xml_tree.version.text
122
+ )
123
+ merged = {}
124
+ for key in set(components).union(mdapi_components):
125
+ merged[key] = list(
126
+ set(
127
+ chain(
128
+ components.get(key, []), mdapi_components.get(key, [])
129
+ )
130
+ )
131
+ )
132
+ mdapi_components = merged
133
+ mdapi_response_messages.extend(response_messages)
134
+ continue
135
+ self._copy_to_tempdir(path, temp_dir)
136
+
137
+ (
138
+ components,
139
+ api_retrieve_unpackaged_response,
140
+ ) = self._collect_components_from_paths(temp_dir)
141
+
142
+ # remove temp dir
143
+ shutil.rmtree(temp_dir)
144
+ merged = {}
145
+ if components:
146
+ for key in set(components).union(mdapi_components):
147
+ merged[key] = list(
148
+ set(chain(components.get(key, []), mdapi_components.get(key, [])))
149
+ )
150
+ components = merged
151
+ else:
152
+ components = mdapi_components
153
+
154
+ if api_retrieve_unpackaged_response:
155
+ api_retrieve_unpackaged_response.extend(mdapi_response_messages)
156
+ else:
157
+ api_retrieve_unpackaged_response = mdapi_response_messages
158
+
159
+ return [components, api_retrieve_unpackaged_response]
160
+
161
+ def _copy_to_tempdir(self, src_dir, temp_dir):
162
+ for item in os.listdir(src_dir):
163
+ src_item = os.path.join(src_dir, item)
164
+ dst_item = os.path.join(temp_dir, item)
165
+
166
+ if os.path.isdir(src_item):
167
+ if not os.path.exists(dst_item):
168
+ shutil.copytree(src_item, dst_item)
169
+ else:
170
+ self._merge_directories(src_item, dst_item)
171
+ else:
172
+ if not os.path.exists(dst_item):
173
+ shutil.copy2(src_item, dst_item)
174
+ else:
175
+ self.logger.debug(f"File {dst_item} already exists, skipping...")
176
+
177
+ def _merge_directories(self, src_dir, dst_dir):
178
+ for item in os.listdir(src_dir):
179
+ src_item = os.path.join(src_dir, item)
180
+ dst_item = os.path.join(dst_dir, item)
181
+
182
+ if os.path.isdir(src_item):
183
+ if not os.path.exists(dst_item):
184
+ shutil.copytree(src_item, dst_item)
185
+ self._merge_directories(src_item, dst_item)
186
+ else:
187
+ if not os.path.exists(dst_item):
188
+ shutil.copy2(src_item, dst_item) # Copy file if it doesn't exist
189
+ else:
190
+ self.logger.debug(f"File {dst_item} already exists, skipping...")
191
+
192
+ def _is_plan(self, name):
193
+
194
+ if self.project_config.lookup(f"plans__{name}") is not None:
195
+ return True
196
+ elif self.project_config.lookup(f"flows__{name}") is not None:
197
+ return False
198
+ else:
199
+ raise TaskOptionsError(
200
+ "No paths provided and unable to determine the current plan or flow name."
201
+ )
202
+
203
+ def _get_plan_tasks(self, name, is_plan=False):
204
+
205
+ tasks = []
206
+ if is_plan:
207
+ step_config = self.project_config.lookup(f"plans__{name}")
208
+ else:
209
+ step_config = self.project_config.lookup(f"flows__{name}")
210
+
211
+ tasks = self._freeze_steps(self.project_config, step_config)
212
+
213
+ return tasks
214
+
215
+ def _freeze_steps(self, project_config, plan_config) -> list:
216
+ steps = plan_config["steps"]
217
+ flow_config = FlowConfig(plan_config)
218
+ flow_config.project_config = project_config
219
+ flow = FlowCoordinator(project_config, flow_config)
220
+ steps = []
221
+ for step in flow.steps:
222
+ if step.skip:
223
+ continue
224
+ with cd(step.project_config.repo_root):
225
+ task = step.task_class(
226
+ step.project_config,
227
+ TaskConfig(step.task_config),
228
+ name=step.task_name,
229
+ )
230
+ steps.extend(task.freeze(step))
231
+ self.logger.debug("Prepared steps:\n" + json.dumps(steps, indent=4))
232
+ return steps
233
+
234
+ def _load_deploy_paths(self, name, is_plan=False):
235
+ tasks = self._get_plan_tasks(name, is_plan)
236
+ if tasks:
237
+ self.deploy_paths = self._get_deployable_paths(tasks)
238
+
239
+ def _get_deployable_paths(self, tasks):
240
+ found_paths = []
241
+ paths_to_search = ["path", "subfolder"]
242
+ for task in tasks:
243
+ if "task_config" in task and "options" in task["task_config"]:
244
+ options = task["task_config"]["options"]
245
+ found_paths.extend(self._search_for_paths(options, paths_to_search))
246
+ return found_paths
247
+
248
+ def _search_for_paths(self, options, keys_to_search):
249
+ found_values = []
250
+
251
+ if not keys_to_search:
252
+ return found_values
253
+
254
+ def recursive_search(obj):
255
+ if isinstance(obj, dict):
256
+ for key, value in obj.items():
257
+ if key in keys_to_search and isinstance(value, str):
258
+ found_values.append(value)
259
+ elif isinstance(value, (dict, list)):
260
+ recursive_search(value)
261
+
262
+ elif isinstance(obj, list):
263
+ for item in obj:
264
+ recursive_search(item)
265
+
266
+ recursive_search(options)
267
+
268
+ return found_values
269
+
270
+ def _collect_components_from_paths(self, full_path):
271
+
272
+ if not os.path.exists(full_path):
273
+ return None, None
274
+
275
+ components = defaultdict(set)
276
+ self.logger.info(f"Collecting components from path: {full_path}")
277
+ # remove if any exiting package.xml files coppied from deploy_pre/post paths
278
+
279
+ if os.path.exists(os.path.join(full_path, "package.xml")):
280
+ os.remove(os.path.join(full_path, "package.xml"))
281
+
282
+ with convert_sfdx_source(full_path, None, self.logger) as src_path:
283
+ package_xml_path = os.path.join(src_path, "package.xml")
284
+ if os.path.exists(package_xml_path):
285
+ try:
286
+ source_xml_tree = metadata_tree.parse(package_xml_path)
287
+ self.logger.info("parsing package.xml")
288
+
289
+ components = metadata_tree.parse_package_xml_types(
290
+ "name", source_xml_tree
291
+ )
292
+
293
+ response_messages = self._get_api_object_responce(
294
+ package_xml_path, source_xml_tree.version.text
295
+ )
296
+
297
+ return [components, response_messages]
298
+
299
+ except ParseError as e:
300
+ self.logger.error(f"Error parsing package.xml: {e}")
301
+ return None, None
302
+ else:
303
+ self.logger.warning(
304
+ f"No package.xml found in {full_path}, scanning directories"
305
+ )
306
+
307
+ return None, None
308
+
309
+ def _get_api_object_responce(self, pakcage_xml_path, version):
310
+
311
+ if not os.path.exists(pakcage_xml_path):
312
+ return None
313
+
314
+ package_xml = open(pakcage_xml_path, "r")
315
+
316
+ api_retrieve_unpackaged_object = self.api_retrieve_unpackaged(
317
+ self, package_xml.read(), version
318
+ )
319
+
320
+ response_messages = parseString(
321
+ api_retrieve_unpackaged_object._get_response().content
322
+ ).getElementsByTagName("messages")
323
+
324
+ return response_messages
@@ -0,0 +1,142 @@
1
+ import json
2
+ import random
3
+ import re
4
+ import string
5
+ from pathlib import Path
6
+
7
+ from cumulusci.cli.ui import CliTable
8
+ from cumulusci.core.exceptions import SalesforceException
9
+ from cumulusci.core.utils import process_bool_arg, process_list_arg, determine_managed_mode
10
+ from cumulusci.tasks.salesforce import BaseSalesforceApiTask
11
+ from cumulusci.utils import inject_namespace
12
+
13
+ API_ROLLBACK_MESSAGE = "The transaction was rolled back since another operation in the same transaction failed."
14
+ API_INVALID_REF_MESSAGE = "Invalid reference specified."
15
+
16
+
17
+ class CompositeApi(BaseSalesforceApiTask):
18
+ task_docs = """
19
+ This task is a wrapper for Composite REST API calls. Given a list of JSON files
20
+ (one request body per file), POST each and process the returned composite
21
+ result. Files are processed in the order given by the ``data_files`` option.
22
+
23
+ In addition, this task will process the request body and replace namespace
24
+ (``%%%NAMESPACE%%%``) and user ID (``%%%USERID%%%``) tokens. To avoid username
25
+ collisions, use the ``randomize_username`` option to replace the top-level
26
+ domains in any ``Username`` field with a random string.
27
+
28
+ When the top-level ``allOrNone`` property for the request is set to true a
29
+ SalesforceException is raised if an error is returned for any subrequest,
30
+ otherwise partial successes will not raise an exception.
31
+
32
+ Example Task Definition
33
+ -----------------------
34
+
35
+ .. code-block:: yaml
36
+
37
+ tasks:
38
+ example_composite_request:
39
+ class_path: cumulusci.tasks.salesforce.composite.CompositeApi
40
+ options:
41
+ data_files:
42
+ - "datasets/composite/users.json"
43
+ - "datasets/composite/setup_objects.json"
44
+ """
45
+
46
+ task_options = {
47
+ "data_files": {
48
+ "description": "A list of paths, where each path is a JSON file containing a composite request body.",
49
+ "required": True,
50
+ },
51
+ "managed": {
52
+ "description": "If True, replaces namespace tokens with the namespace prefix.",
53
+ "default": False,
54
+ },
55
+ "namespaced": {
56
+ "description": "If True, replaces namespace tokens with the namespace prefix.",
57
+ "default": False,
58
+ },
59
+ "randomize_username": {
60
+ "description": "If True, randomize the TLD for any 'Username' fields.",
61
+ "default": False,
62
+ },
63
+ }
64
+
65
+ def _init_options(self, kwargs):
66
+ super()._init_options(kwargs)
67
+ self.data_files = process_list_arg(self.options.get("data_files") or [])
68
+
69
+ def _run_task(self):
70
+ for data_file_path in self.data_files:
71
+ self.logger.info(f"Processing {data_file_path}")
72
+ self._composite_request(data_file_path)
73
+
74
+ def _composite_request(self, data_file_path):
75
+ request_body = self._process_json(Path(data_file_path).read_text())
76
+ self.is_all_or_none = json.loads(request_body).get("allOrNone", False)
77
+ result = self.sf.restful("composite", method="POST", data=request_body)
78
+ self._process_response(result)
79
+
80
+ def _process_json(self, body):
81
+ """Replace namespace tokens and randomize username domains."""
82
+ user_id = self.org_config.user_id
83
+ body = body.replace("%%%USERID%%%", user_id)
84
+
85
+ namespace = self.project_config.project__package__namespace
86
+ managed = determine_managed_mode(
87
+ self.options, self.project_config, self.org_config
88
+ )
89
+
90
+ _, body = inject_namespace(
91
+ "composite",
92
+ body,
93
+ namespace=namespace,
94
+ managed=managed,
95
+ namespaced_org=self.options.get("namespaced", self.org_config.namespaced),
96
+ )
97
+
98
+ if self.options.get("randomize_username", False):
99
+ random_tld = "".join(random.choices(string.ascii_lowercase, k=4))
100
+ body = re.sub(
101
+ r'("Username": .[\w-]+@[\w-]+\.)+[\w-]+', rf"\1{random_tld}", body
102
+ )
103
+
104
+ return body
105
+
106
+ def _process_response(self, result):
107
+ """Handle the compositeResponse and raise an exception if failed."""
108
+ subrequests = result["compositeResponse"]
109
+ status_codes = {subrequest["httpStatusCode"] for subrequest in subrequests}
110
+
111
+ all_success = all([self._http_ok(code) for code in status_codes])
112
+ if self.is_all_or_none and not all_success:
113
+ self._log_exception_message(subrequests)
114
+ raise SalesforceException(json.dumps(subrequests, indent=2))
115
+ else:
116
+ self._log_success_message(subrequests)
117
+
118
+ def _http_ok(self, status_code):
119
+ return status_code >= 200 and status_code < 300
120
+
121
+ def _log_exception_message(self, subrequests):
122
+ table_data = [["ReferenceId", "Message"]]
123
+ table_data.extend(
124
+ [sub["referenceId"], body["message"]]
125
+ for sub in subrequests
126
+ for body in sub["body"]
127
+ if body.get("message") != API_ROLLBACK_MESSAGE
128
+ )
129
+ table = CliTable(
130
+ table_data,
131
+ )
132
+ self.logger.error("The request failed with the following message(s):\n\n")
133
+ table.echo()
134
+
135
+ def _log_success_message(self, subrequests):
136
+ table_data = [["ReferenceId", "Success"]]
137
+ table_data.extend(
138
+ [sub["referenceId"], self._http_ok(sub["httpStatusCode"])]
139
+ for sub in subrequests
140
+ )
141
+ table = CliTable(table_data, title="Subrequest Results")
142
+ table.echo()