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,727 @@
1
+ from io import StringIO
2
+ from unittest.mock import MagicMock, Mock, patch
3
+
4
+ import pytest
5
+
6
+ from cumulusci.core.config import BaseProjectConfig
7
+ from cumulusci.core.exceptions import VcsException, VcsNotFoundError
8
+ from cumulusci.core.keychain import EncryptedFileProjectKeychain
9
+ from cumulusci.vcs import bootstrap
10
+ from cumulusci.vcs.base import VCSService
11
+ from cumulusci.vcs.models import (
12
+ AbstractBranch,
13
+ AbstractGitTag,
14
+ AbstractPullRequest,
15
+ AbstractRelease,
16
+ AbstractRepo,
17
+ AbstractRepoCommit,
18
+ )
19
+ from cumulusci.vcs.tests.dummy_service import DummyRef, DummyRepo, DummyTag
20
+
21
+
22
+ class TestBootstrapFunctions:
23
+ """Test class for VCS bootstrap functions"""
24
+
25
+ @pytest.fixture()
26
+ def keychain(self, project_config, key) -> EncryptedFileProjectKeychain:
27
+ keychain = EncryptedFileProjectKeychain(project_config, key)
28
+ assert keychain.project_config == project_config
29
+ assert keychain.key == key
30
+ return keychain
31
+
32
+ @pytest.fixture()
33
+ def mock_repo(self):
34
+ """Create a mock repository for testing"""
35
+ repo = Mock(spec=AbstractRepo)
36
+ repo.default_branch = "main"
37
+ repo.repo_url = "https://github.com/test/repo"
38
+ repo.owner_login = "test"
39
+ return repo
40
+
41
+ @pytest.fixture()
42
+ def mock_commit(self):
43
+ """Create a mock commit for testing"""
44
+ commit = Mock(spec=AbstractRepoCommit)
45
+ commit.sha = "1234567890abcdef"
46
+ commit.parents = []
47
+ return commit
48
+
49
+ @pytest.fixture()
50
+ def mock_release(self):
51
+ """Create a mock release for testing"""
52
+ release = Mock(spec=AbstractRelease)
53
+ release.tag_name = "release/1.0.0"
54
+ release.prerelease = False
55
+ return release
56
+
57
+ @pytest.fixture()
58
+ def mock_pull_request(self):
59
+ """Create a mock pull request for testing"""
60
+ pr = Mock(spec=AbstractPullRequest)
61
+ pr.merged_at = None
62
+ pr.number = 123
63
+ return pr
64
+
65
+ @pytest.fixture()
66
+ def mock_project_config(self):
67
+ """Create a mock project config for testing"""
68
+ config = Mock(spec=BaseProjectConfig)
69
+ config.repo_url = "https://github.com/test/repo"
70
+ config.config = {}
71
+ config.config["services"] = {
72
+ "test_service": {
73
+ "attributes": {"name": {"required": True}, "password": {}},
74
+ },
75
+ }
76
+ config.logger = Mock()
77
+ config.project__git__prefix_feature = "feature/"
78
+ config.project__git__prefix_release = "release/"
79
+ config.project__git__prefix_beta = "beta/"
80
+ return config
81
+
82
+ def test_get_service_with_class_path(self, keychain, service_config):
83
+ """Test getting service with valid class path"""
84
+ project_config = keychain.project_config
85
+ project_config.keychain = keychain
86
+ keychain.set_service("github", "alias", service_config)
87
+
88
+ encrypted = keychain._get_config_bytes(service_config)
89
+ keychain.config["services"]["github"] = {"alias": encrypted}
90
+
91
+ keychain._save_default_service("github", "alias", project=False)
92
+ keychain._load_default_services()
93
+
94
+ result = bootstrap.get_service(project_config)
95
+ assert isinstance(result, VCSService)
96
+
97
+ @patch("cumulusci.vcs.base.VCSService.registered_services")
98
+ def test_get_service_missing_class_path(self, mock_registered_services):
99
+ """Test error handling when class path is missing"""
100
+ config = MagicMock()
101
+ config.get_project_service.return_value = ("github", None)
102
+ config.lookup.return_value = "github"
103
+ config.services = {"github": {}}
104
+ config.repo_url = "https://github.com/invalid/repo"
105
+
106
+ # Mock no registered services to force the exception
107
+ mock_registered_services.return_value = []
108
+
109
+ with pytest.raises(VcsException) as e:
110
+ bootstrap.get_service(config)
111
+ assert "Could not find a VCS service for URL" in str(e.value)
112
+
113
+ def test_get_ref_for_tag(self):
114
+ """Test getting reference for a tag"""
115
+ repo = DummyRepo()
116
+ result = bootstrap.get_ref_for_tag(repo, "v1.0")
117
+ assert isinstance(result, DummyRef)
118
+
119
+ def test_get_tag_by_name(self):
120
+ """Test getting tag by name"""
121
+ repo = DummyRepo()
122
+ result = bootstrap.get_tag_by_name(repo, "v1.0")
123
+ assert isinstance(result, DummyTag)
124
+
125
+ def test_get_version_id_from_commit_success(self, mock_repo):
126
+ """Test successfully getting version ID from commit"""
127
+ mock_commit = Mock(spec=AbstractRepoCommit)
128
+ mock_commit.get_statuses.return_value = "04t123456789"
129
+ mock_repo.get_commit.return_value = mock_commit
130
+
131
+ result = bootstrap.get_version_id_from_commit(mock_repo, "abc123", "context")
132
+ assert result == "04t123456789"
133
+
134
+ def test_get_version_id_from_commit_no_commit(self, mock_repo):
135
+ """Test getting version ID when commit doesn't exist"""
136
+ mock_repo.get_commit.return_value = None
137
+
138
+ result = bootstrap.get_version_id_from_commit(mock_repo, "abc123", "context")
139
+ assert result is None
140
+
141
+ def test_get_commit(self, mock_repo, mock_commit):
142
+ """Test getting commit by SHA"""
143
+ mock_repo.get_commit.return_value = mock_commit
144
+
145
+ result = bootstrap.get_commit(mock_repo, "abc123")
146
+ assert result == mock_commit
147
+ mock_repo.get_commit.assert_called_once_with("abc123")
148
+
149
+ def test_get_pull_requests_with_base_branch_simple(self, mock_repo):
150
+ """Test getting pull requests with base branch"""
151
+ mock_prs = [Mock(), Mock()]
152
+ mock_repo.pull_requests.return_value = mock_prs
153
+
154
+ result = bootstrap.get_pull_requests_with_base_branch(mock_repo, "main")
155
+ assert result == mock_prs
156
+ mock_repo.pull_requests.assert_called_once_with(
157
+ base="main", head=None, state=None
158
+ )
159
+
160
+ def test_get_pull_requests_with_base_branch_with_head(self, mock_repo):
161
+ """Test getting pull requests with base branch and head"""
162
+ mock_prs = [Mock(), Mock()]
163
+ mock_repo.pull_requests.return_value = mock_prs
164
+ mock_repo.owner_login = "test_owner"
165
+
166
+ result = bootstrap.get_pull_requests_with_base_branch(
167
+ mock_repo, "main", head="feature-branch", state="open"
168
+ )
169
+ assert result == mock_prs
170
+ mock_repo.pull_requests.assert_called_once_with(
171
+ base="main", head="test_owner:feature-branch", state="open"
172
+ )
173
+
174
+ def test_is_pull_request_merged_true(self):
175
+ """Test pull request is merged"""
176
+ pr = Mock(spec=AbstractPullRequest)
177
+ pr.merged_at = "2023-01-01T00:00:00Z"
178
+
179
+ result = bootstrap.is_pull_request_merged(pr)
180
+ assert result is True
181
+
182
+ def test_is_pull_request_merged_false(self):
183
+ """Test pull request is not merged"""
184
+ pr = Mock(spec=AbstractPullRequest)
185
+ pr.merged_at = None
186
+
187
+ result = bootstrap.is_pull_request_merged(pr)
188
+ assert result is False
189
+
190
+ def test_is_label_on_pull_request_true(self, mock_repo, mock_pull_request):
191
+ """Test label exists on pull request"""
192
+ mock_repo.get_pr_issue_labels.return_value = [
193
+ "bug",
194
+ "enhancement",
195
+ "documentation",
196
+ ]
197
+
198
+ result = bootstrap.is_label_on_pull_request(mock_repo, mock_pull_request, "bug")
199
+ assert result is True
200
+
201
+ def test_is_label_on_pull_request_false(self, mock_repo, mock_pull_request):
202
+ """Test label does not exist on pull request"""
203
+ mock_repo.get_pr_issue_labels.return_value = ["bug", "enhancement"]
204
+
205
+ result = bootstrap.is_label_on_pull_request(
206
+ mock_repo, mock_pull_request, "documentation"
207
+ )
208
+ assert result is False
209
+
210
+ @patch("cumulusci.vcs.bootstrap.get_service_for_repo_url")
211
+ def test_get_repo_from_url_success(self, mock_get_service, mock_project_config):
212
+ """Test successfully getting repository from URL"""
213
+ mock_service = Mock(spec=VCSService)
214
+ mock_repo = Mock(spec=AbstractRepo)
215
+ mock_service.get_repository.return_value = mock_repo
216
+ mock_get_service.return_value = mock_service
217
+
218
+ result = bootstrap.get_repo_from_url(
219
+ mock_project_config, "https://github.com/test/repo"
220
+ )
221
+
222
+ assert result == mock_repo
223
+ mock_get_service.assert_called_once_with(
224
+ mock_project_config, "https://github.com/test/repo", service_alias=None
225
+ )
226
+
227
+ @patch("cumulusci.vcs.bootstrap.get_service_for_repo_url")
228
+ def test_get_repo_from_url_not_found(self, mock_get_service, mock_project_config):
229
+ """Test error when repository is not found"""
230
+ mock_service = Mock(spec=VCSService)
231
+ mock_service.get_repository.return_value = None
232
+ mock_get_service.return_value = mock_service
233
+
234
+ with pytest.raises(VcsNotFoundError) as e:
235
+ bootstrap.get_repo_from_url(
236
+ mock_project_config, "https://github.com/test/repo"
237
+ )
238
+
239
+ assert "Could not find a repository at https://github.com/test/repo" in str(
240
+ e.value
241
+ )
242
+
243
+ @patch("cumulusci.vcs.base.VCSService.registered_services")
244
+ def test_get_service_for_repo_url_success(
245
+ self, mock_registered_services, mock_project_config
246
+ ):
247
+ """Test successfully getting service for repo URL"""
248
+ mock_service_class = Mock()
249
+ mock_service_instance = Mock(spec=VCSService)
250
+ mock_service_class.get_service_for_url.return_value = mock_service_instance
251
+ mock_registered_services.return_value = [mock_service_class]
252
+
253
+ result = bootstrap.get_service_for_repo_url(
254
+ mock_project_config, "https://github.com/test/repo"
255
+ )
256
+
257
+ assert result == mock_service_instance
258
+ mock_service_class.get_service_for_url.assert_called_once_with(
259
+ mock_project_config, "https://github.com/test/repo", service_alias=None
260
+ )
261
+
262
+ @patch("cumulusci.vcs.base.VCSService.registered_services")
263
+ def test_get_service_for_repo_url_not_found(
264
+ self, mock_registered_services, mock_project_config
265
+ ):
266
+ """Test error when no service found for URL"""
267
+ mock_service_class = Mock()
268
+ mock_service_class.get_service_for_url.return_value = None
269
+ mock_registered_services.return_value = [mock_service_class]
270
+
271
+ with pytest.raises(VcsException) as e:
272
+ bootstrap.get_service_for_repo_url(
273
+ mock_project_config, "https://github.com/test/repo"
274
+ )
275
+
276
+ assert (
277
+ "Could not find a VCS service for URL: https://github.com/test/repo"
278
+ in str(e.value)
279
+ )
280
+
281
+ @patch("cumulusci.vcs.bootstrap.cci_safe_load")
282
+ def test_get_remote_project_config(self, mock_cci_load, mock_repo):
283
+ """Test getting remote project configuration"""
284
+ mock_file_contents = StringIO("project:\n name: test")
285
+ mock_repo.file_contents.return_value = mock_file_contents
286
+ mock_cci_load.return_value = {"project": {"name": "test"}}
287
+
288
+ result = bootstrap.get_remote_project_config(mock_repo, "main")
289
+
290
+ assert isinstance(result, BaseProjectConfig)
291
+ mock_repo.file_contents.assert_called_once_with("cumulusci.yml", ref="main")
292
+ mock_cci_load.assert_called_once_with(mock_file_contents)
293
+
294
+ @patch("cumulusci.vcs.bootstrap.get_remote_project_config")
295
+ def test_find_repo_feature_prefix_with_custom_prefix(
296
+ self, mock_get_config, mock_repo
297
+ ):
298
+ """Test finding repository feature prefix with custom prefix"""
299
+ mock_branch = Mock()
300
+ mock_commit = Mock()
301
+ mock_commit.sha = "abc123"
302
+ mock_branch.commit = mock_commit
303
+ mock_repo.branch.return_value = mock_branch
304
+
305
+ mock_config = Mock()
306
+ mock_config.project__git__prefix_feature = "custom-feature/"
307
+ mock_get_config.return_value = mock_config
308
+
309
+ result = bootstrap.find_repo_feature_prefix(mock_repo)
310
+
311
+ assert result == "custom-feature/"
312
+ mock_repo.branch.assert_called_once_with(mock_repo.default_branch)
313
+
314
+ @patch("cumulusci.vcs.bootstrap.get_remote_project_config")
315
+ def test_find_repo_feature_prefix_default(self, mock_get_config, mock_repo):
316
+ """Test finding repository feature prefix with default"""
317
+ mock_branch = Mock()
318
+ mock_commit = Mock()
319
+ mock_commit.sha = "abc123"
320
+ mock_branch.commit = mock_commit
321
+ mock_repo.branch.return_value = mock_branch
322
+
323
+ mock_config = Mock()
324
+ mock_config.project__git__prefix_feature = None
325
+ mock_get_config.return_value = mock_config
326
+
327
+ result = bootstrap.find_repo_feature_prefix(mock_repo)
328
+
329
+ assert result == "feature/"
330
+
331
+ @patch("cumulusci.vcs.bootstrap.get_remote_project_config")
332
+ def test_get_remote_context(self, mock_get_config, mock_repo):
333
+ """Test getting remote context"""
334
+ mock_config = Mock()
335
+ mock_config.lookup.return_value = "custom_context"
336
+ mock_get_config.return_value = mock_config
337
+
338
+ result = bootstrap.get_remote_context(
339
+ mock_repo, "test_context", "default_context"
340
+ )
341
+
342
+ assert result == "custom_context"
343
+ mock_config.lookup.assert_called_once_with("project__git__test_context")
344
+
345
+ @patch("cumulusci.vcs.bootstrap.get_remote_project_config")
346
+ def test_get_remote_context_default(self, mock_get_config, mock_repo):
347
+ """Test getting remote context with default"""
348
+ mock_config = Mock()
349
+ mock_config.lookup.return_value = None
350
+ mock_get_config.return_value = mock_config
351
+
352
+ result = bootstrap.get_remote_context(
353
+ mock_repo, "test_context", "default_context"
354
+ )
355
+
356
+ assert result == "default_context"
357
+
358
+ @patch("cumulusci.vcs.bootstrap.get_latest_prerelease")
359
+ def test_find_latest_release_beta(self, mock_get_prerelease, mock_repo):
360
+ """Test finding latest release including beta"""
361
+ mock_release = Mock(spec=AbstractRelease)
362
+ mock_get_prerelease.return_value = mock_release
363
+
364
+ result = bootstrap.find_latest_release(mock_repo, include_beta=True)
365
+
366
+ assert result == mock_release
367
+ mock_get_prerelease.assert_called_once_with(mock_repo)
368
+
369
+ def test_find_latest_release_production(self, mock_repo):
370
+ """Test finding latest production release"""
371
+ mock_release = Mock(spec=AbstractRelease)
372
+ mock_repo.latest_release.return_value = mock_release
373
+
374
+ result = bootstrap.find_latest_release(mock_repo, include_beta=False)
375
+
376
+ assert result == mock_release
377
+ mock_repo.latest_release.assert_called_once()
378
+
379
+ def test_find_latest_release_not_found(self, mock_repo):
380
+ """Test finding latest release when none exists"""
381
+ mock_repo.latest_release.side_effect = VcsNotFoundError("No releases found")
382
+
383
+ result = bootstrap.find_latest_release(mock_repo, include_beta=False)
384
+
385
+ assert result is None
386
+
387
+ def test_get_latest_prerelease(self, mock_repo):
388
+ """Test getting latest prerelease"""
389
+ mock_release = Mock(spec=AbstractRelease)
390
+ mock_repo.get_latest_prerelease.return_value = mock_release
391
+
392
+ result = bootstrap.get_latest_prerelease(mock_repo)
393
+
394
+ assert result == mock_release
395
+ mock_repo.get_latest_prerelease.assert_called_once()
396
+
397
+ def test_find_previous_release_with_prefix(self, mock_repo):
398
+ """Test finding previous release with prefix filter"""
399
+ mock_release1 = Mock(spec=AbstractRelease)
400
+ mock_release1.tag_name = "release/2.0.0"
401
+ mock_release1.prerelease = False
402
+
403
+ mock_release2 = Mock(spec=AbstractRelease)
404
+ mock_release2.tag_name = "release/1.0.0"
405
+ mock_release2.prerelease = False
406
+
407
+ mock_release3 = Mock(spec=AbstractRelease)
408
+ mock_release3.tag_name = "beta/1.0.0"
409
+ mock_release3.prerelease = True
410
+
411
+ mock_repo.releases.return_value = [mock_release1, mock_release2, mock_release3]
412
+
413
+ result = bootstrap.find_previous_release(mock_repo, prefix="release/")
414
+
415
+ assert result == mock_release2
416
+
417
+ def test_find_previous_release_without_prefix(self, mock_repo):
418
+ """Test finding previous release without prefix filter"""
419
+ mock_release1 = Mock(spec=AbstractRelease)
420
+ mock_release1.tag_name = "release/2.0.0"
421
+ mock_release1.prerelease = False
422
+
423
+ mock_release2 = Mock(spec=AbstractRelease)
424
+ mock_release2.tag_name = "release/1.0.0"
425
+ mock_release2.prerelease = False
426
+
427
+ mock_prerelease = Mock(spec=AbstractRelease)
428
+ mock_prerelease.tag_name = "beta/1.5.0"
429
+ mock_prerelease.prerelease = True
430
+
431
+ mock_repo.releases.return_value = [
432
+ mock_release1,
433
+ mock_prerelease,
434
+ mock_release2,
435
+ ]
436
+
437
+ result = bootstrap.find_previous_release(mock_repo)
438
+
439
+ assert result == mock_release2
440
+
441
+ @patch("cumulusci.vcs.bootstrap.get_version_id_from_commit")
442
+ def test_locate_commit_status_package_id_found(
443
+ self, mock_get_version_id, mock_repo
444
+ ):
445
+ """Test locating commit status package ID successfully"""
446
+ mock_branch = Mock(spec=AbstractBranch)
447
+ mock_commit = Mock(spec=AbstractRepoCommit)
448
+ mock_commit.sha = "abc123"
449
+ mock_commit.parents = []
450
+ mock_branch.commit = mock_commit
451
+ mock_get_version_id.return_value = "04t123456789"
452
+
453
+ version_id, commit = bootstrap.locate_commit_status_package_id(
454
+ mock_repo, mock_branch, "context_2gp"
455
+ )
456
+
457
+ assert version_id == "04t123456789"
458
+ assert commit == mock_commit
459
+
460
+ @patch("cumulusci.vcs.bootstrap.get_version_id_from_commit")
461
+ def test_locate_commit_status_package_id_not_found(
462
+ self, mock_get_version_id, mock_repo
463
+ ):
464
+ """Test locating commit status package ID when not found"""
465
+ mock_branch = Mock(spec=AbstractBranch)
466
+ mock_commit = Mock(spec=AbstractRepoCommit)
467
+ mock_commit.sha = "abc123"
468
+ mock_commit.parents = []
469
+ mock_branch.commit = mock_commit
470
+ mock_get_version_id.return_value = None
471
+
472
+ version_id, commit = bootstrap.locate_commit_status_package_id(
473
+ mock_repo, mock_branch, "context_2gp"
474
+ )
475
+
476
+ assert version_id is None
477
+ assert commit is None # When no parents, commit becomes None
478
+
479
+ @patch("cumulusci.vcs.bootstrap.get_service")
480
+ def test_get_repo_from_config(self, mock_get_service, mock_project_config):
481
+ """Test getting repository from config"""
482
+ mock_service = Mock(spec=VCSService)
483
+ mock_repo = Mock(spec=AbstractRepo)
484
+ mock_service.get_repository.return_value = mock_repo
485
+ mock_get_service.return_value = mock_service
486
+
487
+ result = bootstrap.get_repo_from_config(
488
+ mock_project_config, {"option": "value"}
489
+ )
490
+
491
+ assert result == mock_repo
492
+ mock_get_service.assert_called_once_with(
493
+ mock_project_config, logger=mock_project_config.logger
494
+ )
495
+ mock_service.get_repository.assert_called_once_with(options={"option": "value"})
496
+
497
+ def test_get_latest_tag_production(self, mock_repo):
498
+ """Test getting latest production tag"""
499
+ mock_release = Mock(spec=AbstractRelease)
500
+ mock_release.tag_name = "release/1.0.0"
501
+ mock_repo.latest_release.return_value = mock_release
502
+ mock_repo.project_config = Mock()
503
+ mock_repo.project_config.project__git__prefix_release = "release/"
504
+
505
+ result = bootstrap.get_latest_tag(mock_repo, beta=False)
506
+
507
+ assert result == "release/1.0.0"
508
+
509
+ @patch("cumulusci.vcs.bootstrap._get_latest_tag_for_prefix")
510
+ def test_get_latest_tag_beta(self, mock_get_latest_prefix, mock_repo):
511
+ """Test getting latest beta tag"""
512
+ mock_get_latest_prefix.return_value = "beta/1.0.0"
513
+ mock_repo.project_config = Mock()
514
+ mock_repo.project_config.project__git__prefix_beta = "beta/"
515
+
516
+ result = bootstrap.get_latest_tag(mock_repo, beta=True)
517
+
518
+ assert result == "beta/1.0.0"
519
+ mock_get_latest_prefix.assert_called_once_with(mock_repo, "beta/")
520
+
521
+ def test_get_latest_tag_exception(self, mock_repo):
522
+ """Test getting latest tag when exception occurs"""
523
+ mock_repo.latest_release.side_effect = Exception("Error")
524
+ mock_repo.project_config = Mock()
525
+ mock_repo.project_config.project__git__prefix_release = "release/"
526
+ mock_repo.repo_url = "https://github.com/test/repo"
527
+
528
+ with pytest.raises(VcsException) as e:
529
+ bootstrap.get_latest_tag(mock_repo, beta=False)
530
+
531
+ assert (
532
+ "No release found for https://github.com/test/repo with tag prefix release/"
533
+ in str(e.value)
534
+ )
535
+
536
+ def test_get_latest_tag_for_prefix_success(self, mock_repo):
537
+ """Test getting latest tag for prefix successfully"""
538
+ mock_release1 = Mock(spec=AbstractRelease)
539
+ mock_release1.tag_name = "beta/2.0.0"
540
+
541
+ mock_release2 = Mock(spec=AbstractRelease)
542
+ mock_release2.tag_name = "release/1.0.0"
543
+
544
+ mock_repo.releases.return_value = [mock_release1, mock_release2]
545
+
546
+ result = bootstrap._get_latest_tag_for_prefix(mock_repo, "beta/")
547
+
548
+ assert result == "beta/2.0.0"
549
+
550
+ def test_get_latest_tag_for_prefix_not_found(self, mock_repo):
551
+ """Test getting latest tag for prefix when not found"""
552
+ mock_release = Mock(spec=AbstractRelease)
553
+ mock_release.tag_name = "release/1.0.0"
554
+ mock_repo.releases.return_value = [mock_release]
555
+ mock_repo.repo_url = "https://github.com/test/repo"
556
+
557
+ with pytest.raises(VcsException) as e:
558
+ bootstrap._get_latest_tag_for_prefix(mock_repo, "beta/")
559
+
560
+ assert (
561
+ "No release found for https://github.com/test/repo with tag prefix beta/"
562
+ in str(e.value)
563
+ )
564
+
565
+ @patch("cumulusci.vcs.bootstrap.get_tag_by_name")
566
+ def test_get_version_id_from_tag_success(self, mock_get_tag, mock_repo):
567
+ """Test getting version ID from tag successfully"""
568
+ mock_tag = Mock(spec=AbstractGitTag)
569
+ mock_tag.message = "Release notes\nversion_id: 04t123456789\nMore info"
570
+ mock_get_tag.return_value = mock_tag
571
+
572
+ result = bootstrap.get_version_id_from_tag(mock_repo, "v1.0.0")
573
+
574
+ assert result == "04t123456789"
575
+ mock_get_tag.assert_called_once_with(mock_repo, "v1.0.0")
576
+
577
+ @patch("cumulusci.vcs.bootstrap.get_tag_by_name")
578
+ def test_get_version_id_from_tag_not_found(self, mock_get_tag, mock_repo):
579
+ """Test getting version ID from tag when not found"""
580
+ mock_tag = Mock(spec=AbstractGitTag)
581
+ mock_tag.message = "Release notes\nNo version id here\nMore info"
582
+ mock_get_tag.return_value = mock_tag
583
+
584
+ with pytest.raises(VcsException) as e:
585
+ bootstrap.get_version_id_from_tag(mock_repo, "v1.0.0")
586
+
587
+ assert "Could not find version_id for tag v1.0.0" in str(e.value)
588
+
589
+ @patch("cumulusci.vcs.bootstrap.get_tag_by_name")
590
+ def test_get_version_id_from_tag_invalid_format(self, mock_get_tag, mock_repo):
591
+ """Test getting version ID from tag with invalid format"""
592
+ mock_tag = Mock(spec=AbstractGitTag)
593
+ mock_tag.message = "Release notes\nversion_id: invalid123\nMore info"
594
+ mock_get_tag.return_value = mock_tag
595
+
596
+ with pytest.raises(VcsException) as e:
597
+ bootstrap.get_version_id_from_tag(mock_repo, "v1.0.0")
598
+
599
+ assert "Could not find version_id for tag v1.0.0" in str(e.value)
600
+
601
+
602
+ class TestBootstrapIntegration:
603
+ """Integration tests for bootstrap functions"""
604
+
605
+ @pytest.fixture()
606
+ def dummy_repo_with_config(self):
607
+ """Create a dummy repo with project config"""
608
+ repo = DummyRepo()
609
+ repo.project_config = Mock()
610
+ repo.project_config.project__git__prefix_release = "release/"
611
+ repo.project_config.project__git__prefix_beta = "beta/"
612
+ repo.repo_url = "https://github.com/test/repo"
613
+ return repo
614
+
615
+ def test_get_ref_and_tag_integration(self):
616
+ """Test integration between get_ref_for_tag and get_tag_by_name"""
617
+ repo = DummyRepo()
618
+ tag_name = "v1.0.0"
619
+
620
+ # Test the full flow
621
+ ref = bootstrap.get_ref_for_tag(repo, tag_name)
622
+ tag = bootstrap.get_tag_by_name(repo, tag_name)
623
+
624
+ assert isinstance(ref, DummyRef)
625
+ assert isinstance(tag, DummyTag)
626
+
627
+ @patch("cumulusci.vcs.bootstrap.get_version_id_from_commit")
628
+ def test_locate_commit_status_integration(self, mock_get_version_id):
629
+ """Test integration of commit status location with multiple commits"""
630
+ # Setup commits with parent chain
631
+ commit1 = Mock(spec=AbstractRepoCommit)
632
+ commit1.sha = "abc123"
633
+ commit1.parents = [Mock(sha="def456")]
634
+
635
+ commit2 = Mock(spec=AbstractRepoCommit)
636
+ commit2.sha = "def456"
637
+ commit2.parents = []
638
+
639
+ mock_branch = Mock(spec=AbstractBranch)
640
+ mock_branch.commit = commit1
641
+
642
+ mock_repo = Mock(spec=AbstractRepo)
643
+ mock_repo.get_commit.return_value = commit2
644
+
645
+ # First call returns None, second call returns version_id
646
+ mock_get_version_id.side_effect = [None, "04t123456789"]
647
+
648
+ version_id, commit = bootstrap.locate_commit_status_package_id(
649
+ mock_repo, mock_branch, "context_2gp"
650
+ )
651
+
652
+ assert version_id == "04t123456789"
653
+ assert commit == commit2
654
+ assert mock_get_version_id.call_count == 2
655
+
656
+
657
+ class TestBootstrapRegex:
658
+ """Test regex patterns used in bootstrap"""
659
+
660
+ def test_version_id_regex_match(self):
661
+ """Test VERSION_ID_RE regex matching"""
662
+ test_string = "Build status: success\nversion_id: 04t123456789ABC\nMore info"
663
+ match = bootstrap.VERSION_ID_RE.search(test_string)
664
+
665
+ assert match is not None
666
+ assert match.group(1) == "04t123456789ABC"
667
+
668
+ def test_version_id_regex_no_match(self):
669
+ """Test VERSION_ID_RE regex not matching"""
670
+ test_string = "Build status: success\nNo version id here\nMore info"
671
+ match = bootstrap.VERSION_ID_RE.search(test_string)
672
+
673
+ assert match is None
674
+
675
+
676
+ class TestBootstrapEdgeCases:
677
+ """Test edge cases and error conditions"""
678
+
679
+ def test_get_pull_requests_empty_list(self):
680
+ """Test getting pull requests when none exist"""
681
+ repo = Mock(spec=AbstractRepo)
682
+ repo.pull_requests.return_value = []
683
+
684
+ result = bootstrap.get_pull_requests_with_base_branch(repo, "main")
685
+
686
+ assert result == []
687
+
688
+ def test_is_label_on_pull_request_empty_labels(self):
689
+ """Test checking label when no labels exist"""
690
+ repo = Mock(spec=AbstractRepo)
691
+ pr = Mock(spec=AbstractPullRequest)
692
+ repo.get_pr_issue_labels.return_value = []
693
+
694
+ result = bootstrap.is_label_on_pull_request(repo, pr, "bug")
695
+
696
+ assert result is False
697
+
698
+ def test_find_previous_release_single_release(self):
699
+ """Test finding previous release when only one exists"""
700
+ repo = Mock(spec=AbstractRepo)
701
+ mock_release = Mock(spec=AbstractRelease)
702
+ mock_release.tag_name = "release/1.0.0"
703
+ mock_release.prerelease = False
704
+ repo.releases.return_value = [mock_release]
705
+
706
+ result = bootstrap.find_previous_release(repo)
707
+
708
+ assert result is None
709
+
710
+ def test_locate_commit_status_no_parents(self):
711
+ """Test locating commit status when commit has no parents"""
712
+ repo = Mock(spec=AbstractRepo)
713
+ branch = Mock(spec=AbstractBranch)
714
+ commit = Mock(spec=AbstractRepoCommit)
715
+ commit.sha = "abc123"
716
+ commit.parents = []
717
+ branch.commit = commit
718
+
719
+ with patch(
720
+ "cumulusci.vcs.bootstrap.get_version_id_from_commit", return_value=None
721
+ ):
722
+ version_id, returned_commit = bootstrap.locate_commit_status_package_id(
723
+ repo, branch, "context"
724
+ )
725
+
726
+ assert version_id is None
727
+ assert returned_commit is None # When no parents, commit becomes None