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,1118 @@
1
+ import http.client
2
+
3
+ import github3
4
+ import pytest
5
+ import responses
6
+ from testfixtures import LogCapture
7
+
8
+ from cumulusci.core.config import ServiceConfig, TaskConfig
9
+ from cumulusci.core.exceptions import GithubApiNotFoundError
10
+ from cumulusci.tasks.base_source_control_task import BaseSourceControlTask
11
+ from cumulusci.tasks.release_notes.tests.utils import MockUtilBase
12
+ from cumulusci.tasks.vcs import MergeBranch
13
+ from cumulusci.tests.util import DummyOrgConfig, create_project_config
14
+
15
+
16
+ class TestMergeBranch(MockUtilBase):
17
+ def setup_method(self):
18
+
19
+ # Set up the mock values
20
+ self.repo = "TestRepo"
21
+ self.owner = "TestOwner"
22
+ self.repo_api_url = f"https://api.github.com/repos/{self.owner}/{self.repo}"
23
+ self.branch = "main"
24
+
25
+ # Create the project config
26
+ self.project_config = create_project_config(self.repo, self.owner)
27
+ self.project_config.config["project"]["git"]["default_branch"] = self.branch
28
+ self.project_config.keychain.set_service(
29
+ "github",
30
+ "test_alias",
31
+ ServiceConfig(
32
+ {
33
+ "username": "TestUser",
34
+ "token": "TestPass",
35
+ "email": "testuser@testdomain.com",
36
+ }
37
+ ),
38
+ )
39
+
40
+ def _create_task(self, task_config=None):
41
+ if not task_config:
42
+ task_config = {}
43
+
44
+ return MergeBranch(
45
+ project_config=self.project_config,
46
+ task_config=TaskConfig(task_config),
47
+ org_config=DummyOrgConfig(),
48
+ )
49
+
50
+ def _mock_repo(self):
51
+ api_url = self.repo_api_url
52
+
53
+ expected_response = self._get_expected_repo(owner=self.owner, name=self.repo)
54
+ responses.add(method=responses.GET, url=api_url, json=expected_response)
55
+ return expected_response
56
+
57
+ def _mock_branch(self, branch, expected_response=None):
58
+ api_url = f"{self.repo_api_url}/branches/{branch}"
59
+ if not expected_response:
60
+ expected_response = self._get_expected_branch(branch)
61
+ responses.add(method=responses.GET, url=api_url, json=expected_response)
62
+
63
+ def _mock_branches(self, branches=None):
64
+ api_url = f"{self.repo_api_url}/branches"
65
+ if branches:
66
+ expected_response = branches
67
+ else:
68
+ expected_response = []
69
+
70
+ responses.add(method=responses.GET, url=api_url, json=expected_response)
71
+ return expected_response
72
+
73
+ def _mock_branch_does_not_exist(self, branch):
74
+ api_url = f"{self.repo_api_url}/branches/{branch}"
75
+ expected_response = self._get_expected_not_found()
76
+ responses.add(
77
+ method=responses.GET,
78
+ url=api_url,
79
+ status=http.client.NOT_FOUND, # 404
80
+ json=expected_response,
81
+ )
82
+
83
+ def _mock_merge(self, status=http.client.CREATED):
84
+ api_url = f"{self.repo_api_url}/merges"
85
+ expected_response = self._get_expected_merge(status == http.client.CONFLICT)
86
+
87
+ responses.add(
88
+ method=responses.POST, url=api_url, json=expected_response, status=status
89
+ )
90
+ return expected_response
91
+
92
+ def _mock_pull_create(self, pull_id, issue_id, status=None):
93
+ api_url = f"{self.repo_api_url}/pulls"
94
+ expected_response = self._get_expected_pull_request(pull_id, issue_id)
95
+
96
+ responses.add(
97
+ method=responses.POST,
98
+ url=api_url,
99
+ json=expected_response,
100
+ status=status or http.client.CREATED, # 201
101
+ )
102
+
103
+ def _mock_compare(self, base, head, files=None):
104
+ api_url = f"{self.repo_api_url}/compare/{base}...{head}"
105
+ expected_response = self._get_expected_compare(base, head, files)
106
+
107
+ responses.add(method=responses.GET, url=api_url, json=expected_response)
108
+
109
+ def _get_log_lines(self, log):
110
+ log_lines = []
111
+ for event in log.records:
112
+ if event.name != "cumulusci.core.tasks":
113
+ continue
114
+ log_lines.append((event.levelname, event.getMessage()))
115
+ return log_lines
116
+
117
+ def _setup_mocks(self, branch_names, merges=True, compare_diff=True):
118
+ """Setup all mocks needed for an integration test
119
+ of MergeBranch with the given branch_names.
120
+ source_branch should be at index 0
121
+ """
122
+ # Create response for repo endpoint
123
+ self._mock_repo()
124
+ # Create endpoint for repo/pulls...
125
+ self.mock_pulls()
126
+
127
+ # Create response for source branch endpoint
128
+ self._mock_branch(branch_names[0])
129
+
130
+ branch_response_bodies = []
131
+ for name in branch_names:
132
+ branch_response_bodies.append(self._get_expected_branch(name))
133
+
134
+ # Create response for repo/branches endpoint
135
+ branches = self._mock_branches(branch_response_bodies)
136
+
137
+ if merges:
138
+ # Create endpoint for repo/merges endpoint
139
+ merges = [self._mock_merge()]
140
+ # Create endpoints for repo/compare/{base}...{head}
141
+ for branch in branches[1:]:
142
+ files = [{"filename": "text.txt"}] if compare_diff else []
143
+ self._mock_compare(
144
+ base=branch["name"],
145
+ head=self.project_config.repo_commit,
146
+ files=files,
147
+ )
148
+
149
+ @responses.activate
150
+ def test_branch_does_not_exist(self):
151
+ self._mock_repo()
152
+ self._mock_branch_does_not_exist(self.branch)
153
+
154
+ task = self._create_task()
155
+ assert isinstance(task, BaseSourceControlTask)
156
+ with pytest.raises(GithubApiNotFoundError):
157
+ task()
158
+ assert 2 == len(responses.calls)
159
+
160
+ @responses.activate
161
+ def test_no_descendents_of_main(self):
162
+ self._mock_repo()
163
+ self._mock_branch(self.branch)
164
+ other_branch = self._get_expected_branch("not-a-feature-branch")
165
+ self.mock_pulls()
166
+ branches = [self._get_expected_branch("main"), other_branch]
167
+ branches = self._mock_branches(branches)
168
+ with LogCapture() as log:
169
+ task = self._create_task()
170
+ task()
171
+ log_lines = self._get_log_lines(log)
172
+
173
+ expected = log_header() + [
174
+ ("DEBUG", "Skipping branch main: is source branch"),
175
+ (
176
+ "DEBUG",
177
+ "Skipping branch not-a-feature-branch: does not match prefix 'feature/'",
178
+ ),
179
+ ]
180
+ assert expected == log_lines
181
+ assert 3 == len(responses.calls)
182
+
183
+ @responses.activate
184
+ def test_feature_branch_no_diff(self):
185
+ self._setup_mocks(["main", "feature/a-test"], merges=False, compare_diff=False)
186
+ with LogCapture() as log:
187
+ task = self._create_task()
188
+ task()
189
+ log_lines = self._get_log_lines(log)
190
+
191
+ expected = log_header() + [
192
+ ("DEBUG", "Skipping branch main: is source branch"),
193
+ ("DEBUG", "Found descendents of main to update: ['feature/a-test']"),
194
+ ("INFO", "Skipping branch feature/a-test: no file diffs found"),
195
+ ]
196
+ assert expected == log_lines
197
+ assert 4 == len(responses.calls)
198
+
199
+ @responses.activate
200
+ def test_task_output__feature_branch_merge(self):
201
+ self._mock_repo()
202
+ self._mock_branch(self.branch)
203
+ self.mock_pulls()
204
+ branch_name = "feature/a-test"
205
+ branches = []
206
+ branches.append(self._get_expected_branch("main"))
207
+ branches.append(self._get_expected_branch(branch_name))
208
+ branches = self._mock_branches(branches)
209
+ self._mock_compare(
210
+ base=branches[1]["name"],
211
+ head=self.project_config.repo_commit,
212
+ files=[{"filename": "test.txt"}],
213
+ )
214
+ self._mock_merge()
215
+ with LogCapture() as log:
216
+ task = self._create_task()
217
+ task()
218
+ log_lines = self._get_log_lines(log)
219
+
220
+ expected = [
221
+ ("INFO", "Beginning task: MergeBranch"),
222
+ ("INFO", ""),
223
+ ("DEBUG", "Skipping branch main: is source branch"),
224
+ ("DEBUG", "Found descendents of main to update: ['feature/a-test']"),
225
+ ("INFO", "Merged 1 commits into branch: feature/a-test"),
226
+ ]
227
+ assert expected == log_lines
228
+ assert 5 == len(responses.calls)
229
+
230
+ @responses.activate
231
+ def test_feature_branch_merge_github_error(self):
232
+ self._mock_repo()
233
+ self._mock_branch(self.branch)
234
+ self.mock_pulls()
235
+ branch_name = "feature/a-test"
236
+ branches = []
237
+ branches.append(self._get_expected_branch("main"))
238
+ branches.append(self._get_expected_branch(branch_name))
239
+ branches = self._mock_branches(branches)
240
+ self._mock_compare(
241
+ base=branches[1]["name"],
242
+ head=self.project_config.repo_commit,
243
+ files=[{"filename": "test.txt"}],
244
+ )
245
+ self._mock_merge(http.client.INTERNAL_SERVER_ERROR)
246
+ task = self._create_task()
247
+ with pytest.raises(github3.GitHubError):
248
+ task()
249
+
250
+ @responses.activate
251
+ def test_task_output__feature_branch_merge_conflict(self):
252
+ self._mock_repo()
253
+ self._mock_branch(self.branch)
254
+ self.mock_pulls()
255
+ branch_name = "feature/a-test"
256
+ branches = []
257
+ branches.append(self._get_expected_branch("main"))
258
+ branches.append(self._get_expected_branch(branch_name))
259
+ branches = self._mock_branches(branches)
260
+ self._mock_compare(
261
+ base=branches[1]["name"],
262
+ head=self.project_config.repo_commit,
263
+ files=[{"filename": "test.txt"}],
264
+ )
265
+ self._mock_merge(http.client.CONFLICT)
266
+ self._mock_pull_create(1, 2)
267
+ with LogCapture() as log:
268
+ task = self._create_task()
269
+ task()
270
+ actual_log = self._get_log_lines(log)
271
+
272
+ expected_log = log_header() + [
273
+ ("DEBUG", "Skipping branch main: is source branch"),
274
+ ("DEBUG", "Found descendents of main to update: ['feature/a-test']"),
275
+ (
276
+ "INFO",
277
+ "Merge conflict on branch feature/a-test: created pull request #2",
278
+ ),
279
+ ]
280
+ assert expected_log == actual_log
281
+ assert 7 == len(responses.calls)
282
+
283
+ @responses.activate
284
+ def test_task_output__feature_branch_merge_conflict_skip_pull_requests(self):
285
+ self._mock_repo()
286
+ self._mock_branch(self.branch)
287
+ self.mock_pulls()
288
+ branch_name = "feature/a-test"
289
+ branches = []
290
+ branches.append(self._get_expected_branch("main"))
291
+ branches.append(self._get_expected_branch(branch_name))
292
+ branches = self._mock_branches(branches)
293
+ self._mock_compare(
294
+ base=branches[1]["name"],
295
+ head=self.project_config.repo_commit,
296
+ files=[{"filename": "test.txt"}],
297
+ )
298
+ self._mock_merge(http.client.CONFLICT)
299
+ self._mock_pull_create(1, 2)
300
+ with LogCapture() as log:
301
+ task = self._create_task(
302
+ task_config={
303
+ "options": {
304
+ "create_pull_request_on_conflict": "False",
305
+ }
306
+ }
307
+ )
308
+ task()
309
+ actual_log = self._get_log_lines(log)
310
+
311
+ expected_log = log_header() + [
312
+ ("DEBUG", "Skipping branch main: is source branch"),
313
+ ("DEBUG", "Found descendents of main to update: ['feature/a-test']"),
314
+ (
315
+ "INFO",
316
+ "Merge conflict on branch feature/a-test: skipping pull request creation",
317
+ ),
318
+ ]
319
+ assert expected_log == actual_log
320
+ assert 5 == len(responses.calls)
321
+
322
+ @responses.activate
323
+ def test_merge__error_on_merge_conflict_pr(self):
324
+ self._mock_repo()
325
+ self._mock_branch(self.branch)
326
+ self.mock_pulls()
327
+ # branches
328
+ branches = []
329
+ branches.append(self._get_expected_branch("main"))
330
+ branches.append(self._get_expected_branch("feature/one"))
331
+ branches = self._mock_branches(branches)
332
+ # pull request
333
+ pull = self._get_expected_pull_request(1, 2)
334
+ pull["base"]["ref"] = "feature/one"
335
+ pull["base"]["sha"] = branches[1]["commit"]["sha"]
336
+ pull["head"]["ref"] = "main"
337
+ self.mock_pulls(pulls=[pull])
338
+ # compare
339
+ self._mock_compare(
340
+ base="feature/one",
341
+ head=self.project_config.repo_commit,
342
+ files=[{"filename": "test.txt"}],
343
+ )
344
+ # merge
345
+ self._mock_merge(http.client.CONFLICT)
346
+ # merge conflict PR to return exception
347
+ self._mock_pull_create(8, 8, status=http.client.UNPROCESSABLE_ENTITY)
348
+ with LogCapture() as log:
349
+ task = self._create_task()
350
+ task._init_task()
351
+ task._merge("feature/one", "main", self.project_config.repo_commit)
352
+ actual_log = self._get_log_lines(log)
353
+
354
+ assert actual_log[0][0] == "ERROR"
355
+ assert actual_log[0][1].startswith(
356
+ "Error creating merge conflict pull request to merge main into feature/one:\n"
357
+ )
358
+
359
+ @responses.activate
360
+ def test_task_output__feature_branch_existing_pull(self):
361
+ self._mock_repo()
362
+ self._mock_branch(self.branch)
363
+
364
+ branch_name = "feature/a-test"
365
+ branches = []
366
+ branches.append(self._get_expected_branch("main"))
367
+ branches.append(self._get_expected_branch(branch_name))
368
+ branches = self._mock_branches(branches)
369
+
370
+ pull = self._get_expected_pull_request(1, 2)
371
+ pull["base"]["ref"] = branch_name
372
+ pull["base"]["sha"] = branches[1]["commit"]["sha"]
373
+ pull["head"]["ref"] = self.branch
374
+ self.mock_pulls(pulls=[pull])
375
+
376
+ self._mock_compare(
377
+ base=branches[1]["name"],
378
+ head=self.project_config.repo_commit,
379
+ files=[{"filename": "test.txt"}],
380
+ )
381
+ self._mock_merge(http.client.CONFLICT)
382
+
383
+ with LogCapture() as log:
384
+ task = self._create_task()
385
+ task()
386
+ log_lines = self._get_log_lines(log)
387
+
388
+ expected = log_header() + [
389
+ ("DEBUG", "Skipping branch main: is source branch"),
390
+ ("DEBUG", "Found descendents of main to update: ['feature/a-test']"),
391
+ (
392
+ "INFO",
393
+ "Merge conflict on branch feature/a-test: merge PR already exists",
394
+ ),
395
+ ]
396
+ assert expected == log_lines
397
+ assert 6 == len(responses.calls)
398
+
399
+ @responses.activate
400
+ def test_task_output__main_parent_with_child_pr(self):
401
+ self._mock_repo()
402
+ self._mock_branch(self.branch)
403
+ # branches
404
+ parent_branch_name = "feature/a-test"
405
+ child_branch_name = "feature/a-test__a-child"
406
+ branches = []
407
+ branches.append(self._get_expected_branch("main"))
408
+ branches.append(self._get_expected_branch(parent_branch_name))
409
+ branches.append(self._get_expected_branch(child_branch_name))
410
+ branches = self._mock_branches(branches)
411
+ # pull request
412
+ pull = self._get_expected_pull_request(1, 2)
413
+ pull["base"]["ref"] = parent_branch_name
414
+ pull["base"]["sha"] = branches[1]["commit"]["sha"]
415
+ pull["head"]["ref"] = child_branch_name
416
+ self.mock_pulls(pulls=[pull])
417
+ # compare
418
+ self._mock_compare(
419
+ base=parent_branch_name,
420
+ head=self.project_config.repo_commit,
421
+ files=[{"filename": "test.txt"}],
422
+ )
423
+ # merge
424
+ self._mock_merge(http.client.CONFLICT)
425
+ # create PR
426
+ self._mock_pull_create(1, 2)
427
+ with LogCapture() as log:
428
+ task = self._create_task()
429
+ task()
430
+ actual_log = self._get_log_lines(log)
431
+ expected_log = log_header() + [
432
+ ("DEBUG", "Skipping branch main: is source branch"),
433
+ (
434
+ "DEBUG",
435
+ "Skipping branch feature/a-test__a-child: is not a direct descendent of main",
436
+ ),
437
+ ("DEBUG", "Found descendents of main to update: ['feature/a-test']"),
438
+ (
439
+ "INFO",
440
+ "Merge conflict on branch feature/a-test: created pull request #2",
441
+ ),
442
+ ]
443
+ assert expected_log == actual_log
444
+ assert 7 == len(responses.calls)
445
+
446
+ @responses.activate
447
+ def test_task_output__main_parent_with_child_skip_pull_requests(self):
448
+ self._mock_repo()
449
+ self._mock_branch(self.branch)
450
+ # branches
451
+ parent_branch_name = "feature/a-test"
452
+ child_branch_name = "feature/a-test__a-child"
453
+ branches = []
454
+ branches.append(self._get_expected_branch("main"))
455
+ branches.append(self._get_expected_branch(parent_branch_name))
456
+ branches.append(self._get_expected_branch(child_branch_name))
457
+ branches = self._mock_branches(branches)
458
+ # pull request
459
+ pull = self._get_expected_pull_request(1, 2)
460
+ pull["base"]["ref"] = parent_branch_name
461
+ pull["base"]["sha"] = branches[1]["commit"]["sha"]
462
+ pull["head"]["ref"] = child_branch_name
463
+ self.mock_pulls(pulls=[pull])
464
+ # compare
465
+ self._mock_compare(
466
+ base=parent_branch_name,
467
+ head=self.project_config.repo_commit,
468
+ files=[{"filename": "test.txt"}],
469
+ )
470
+ # merge
471
+ self._mock_merge(http.client.CONFLICT)
472
+ # create PR
473
+ self._mock_pull_create(1, 2)
474
+ with LogCapture() as log:
475
+ task = self._create_task(
476
+ task_config={
477
+ "options": {
478
+ "create_pull_request_on_conflict": "False",
479
+ }
480
+ }
481
+ )
482
+ task()
483
+ actual_log = self._get_log_lines(log)
484
+ expected_log = log_header() + [
485
+ ("DEBUG", "Skipping branch main: is source branch"),
486
+ (
487
+ "DEBUG",
488
+ "Skipping branch feature/a-test__a-child: is not a direct descendent of main",
489
+ ),
490
+ ("DEBUG", "Found descendents of main to update: ['feature/a-test']"),
491
+ (
492
+ "INFO",
493
+ "Merge conflict on branch feature/a-test: skipping pull request creation",
494
+ ),
495
+ ]
496
+ assert expected_log == actual_log
497
+ assert 5 == len(responses.calls)
498
+
499
+ @responses.activate
500
+ def test_task_output__main_merge_to_feature(self):
501
+ """Tests that commits to the main branch are merged to the expected feature branches"""
502
+
503
+ prefix = "neptune/"
504
+ source_branch = "main"
505
+ child_branches = [
506
+ f"{prefix}230",
507
+ f"{prefix}work-a",
508
+ f"{prefix}work-b",
509
+ ]
510
+ other_branches = [
511
+ "venus/work-a",
512
+ f"{prefix}work-a__child_a",
513
+ f"{prefix}work-a__child_a__grandchild",
514
+ f"{prefix}work-b__child_b",
515
+ f"{prefix}orphan__with_child",
516
+ f"{prefix}230__cool_feature",
517
+ f"{prefix}230__cool_feature__child",
518
+ ]
519
+ self._setup_mocks([source_branch] + child_branches + other_branches)
520
+
521
+ with LogCapture() as log:
522
+ task = self._create_task(
523
+ task_config={
524
+ "options": {"source_branch": source_branch, "branch_prefix": prefix}
525
+ }
526
+ )
527
+ task()
528
+
529
+ expected_log = log_header() + [
530
+ ("DEBUG", "Skipping branch main: is source branch"),
531
+ (
532
+ "DEBUG",
533
+ "Skipping branch venus/work-a: does not match prefix 'neptune/'",
534
+ ),
535
+ (
536
+ "DEBUG",
537
+ "Skipping branch neptune/work-a__child_a: is not a direct descendent of main",
538
+ ),
539
+ (
540
+ "DEBUG",
541
+ "Skipping branch neptune/work-a__child_a__grandchild: is not a direct descendent of main",
542
+ ),
543
+ (
544
+ "DEBUG",
545
+ "Skipping branch neptune/work-b__child_b: is not a direct descendent of main",
546
+ ),
547
+ (
548
+ "DEBUG",
549
+ "Skipping branch neptune/orphan__with_child: is not a direct descendent of main",
550
+ ),
551
+ (
552
+ "DEBUG",
553
+ "Skipping branch neptune/230__cool_feature: is not a direct descendent of main",
554
+ ),
555
+ (
556
+ "DEBUG",
557
+ "Skipping branch neptune/230__cool_feature__child: is not a direct descendent of main",
558
+ ),
559
+ (
560
+ "DEBUG",
561
+ "Found descendents of main to update: ['neptune/230', 'neptune/work-a', 'neptune/work-b']",
562
+ ),
563
+ (
564
+ "INFO",
565
+ "Merged 1 commits into branch: neptune/230",
566
+ ),
567
+ (
568
+ "INFO",
569
+ "Merged 1 commits into branch: neptune/work-a",
570
+ ),
571
+ (
572
+ "INFO",
573
+ "Merged 1 commits into branch: neptune/work-b",
574
+ ),
575
+ ]
576
+ actual_log = self._get_log_lines(log)
577
+ assert expected_log == actual_log
578
+ assert 9 == len(responses.calls)
579
+
580
+ @responses.activate
581
+ def test_branches_to_merge__main_to_feature_and_next_release(self):
582
+ """Tests that when main branch is the source_branch
583
+ that all expected child branches and the *lowest numbered*
584
+ release branch are merged into."""
585
+
586
+ self._setup_mocks(
587
+ [
588
+ "main",
589
+ "feature/230",
590
+ "feature/340",
591
+ "feature/450",
592
+ "feature/work-a",
593
+ "feature/work-b",
594
+ "feature/work-a__child_a",
595
+ "feature/work-a__child_a__grandchild",
596
+ "feature/work-b__child_b",
597
+ "feature/orphan__with_child",
598
+ "feature/230__cool_feature",
599
+ "feature/230__cool_feature__child",
600
+ ]
601
+ )
602
+
603
+ task = self._create_task(
604
+ task_config={
605
+ "options": {
606
+ "source_branch": "main",
607
+ }
608
+ }
609
+ )
610
+ task._init_task()
611
+
612
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
613
+ expected_branches_to_merge = [
614
+ "feature/230",
615
+ "feature/work-a",
616
+ "feature/work-b",
617
+ ]
618
+ assert expected_branches_to_merge == actual_branches
619
+ assert 2 == len(responses.calls)
620
+
621
+ @responses.activate
622
+ def test_branches_to_merge__no_prefix_merge_to_feature(self):
623
+ """Tests that when source_branch is a branch other than main
624
+ and doesn't start with 'feature/', that it is merged
625
+ to all non-child feature/ branches"""
626
+
627
+ source_branch = "some-branch"
628
+ expected_branches_to_merge = ["feature/work-a", "feature/work-b"]
629
+ other_branches = [
630
+ "feature/work-a__child",
631
+ "some-branch__child",
632
+ "main",
633
+ ]
634
+ self._setup_mocks([source_branch] + expected_branches_to_merge + other_branches)
635
+
636
+ task = self._create_task(
637
+ task_config={
638
+ "options": {
639
+ "source_branch": source_branch,
640
+ }
641
+ }
642
+ )
643
+ task._init_task()
644
+
645
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
646
+ assert expected_branches_to_merge == actual_branches
647
+ assert 2 == len(responses.calls)
648
+
649
+ @responses.activate
650
+ def test_branches_to_merge__merge_feature_to_children(self):
651
+ """Tests that only direct descendents of a branch
652
+ with the given branch_prefix receive merges."""
653
+
654
+ prefix = "mars/"
655
+ source_branch = f"{prefix}a-test"
656
+ child_branches = [
657
+ f"{prefix}a-test__a-child1",
658
+ f"{prefix}a-test__a-child2",
659
+ ]
660
+ other_branches = [
661
+ "main",
662
+ "saturn/a-test__child",
663
+ f"{prefix}a-test__a-child1__grandchild1",
664
+ f"{prefix}a-test__a-child2__grandchild2",
665
+ ]
666
+
667
+ self._setup_mocks([source_branch] + child_branches + other_branches)
668
+
669
+ task = self._create_task(
670
+ task_config={
671
+ "options": {
672
+ "source_branch": source_branch,
673
+ "branch_prefix": prefix,
674
+ }
675
+ }
676
+ )
677
+ task._init_task()
678
+
679
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
680
+ assert child_branches == actual_branches
681
+ assert 2 == len(responses.calls)
682
+
683
+ @responses.activate
684
+ def test_branches_to_merge__merge_feature_child_to_grandchildren(self):
685
+ """Tests that when source branch is a child branch, we only merge
686
+ to granchildren."""
687
+ source_branch = "feature/test__work"
688
+ child_branches = [
689
+ "feature/test__work__child1",
690
+ "feature/test__work__child2",
691
+ ]
692
+ other_branches = [
693
+ "feature/test__work__child1__grandchild1",
694
+ "feature/test__work__child2__grandchild2",
695
+ "feature/test__workchild__2",
696
+ ]
697
+ self._setup_mocks([source_branch] + child_branches + other_branches)
698
+
699
+ task = self._create_task(
700
+ task_config={
701
+ "options": {
702
+ "source_branch": source_branch,
703
+ }
704
+ }
705
+ )
706
+ task._init_task()
707
+
708
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
709
+ assert child_branches == actual_branches
710
+ assert 2 == len(responses.calls)
711
+
712
+ @responses.activate
713
+ def test_branches_to_merge__feature_merge_no_children(self):
714
+ source_branch = "feature/a-test"
715
+ other_branch = "feature/b-test"
716
+ self._setup_mocks([source_branch, other_branch])
717
+
718
+ task = self._create_task(
719
+ task_config={
720
+ "options": {
721
+ "source_branch": source_branch,
722
+ }
723
+ }
724
+ )
725
+ task._init_task()
726
+
727
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
728
+
729
+ assert [] == actual_branches
730
+ # First API call is task.get_repo() (above)
731
+ # Second API call is to self.repo.branches
732
+ assert 2 == len(responses.calls)
733
+
734
+ @responses.activate
735
+ def test_merge_to_future_release_branches(self):
736
+ """Tests that commits to the main branch are merged to the expected feature branches"""
737
+ self._setup_mocks(
738
+ [
739
+ "main",
740
+ "feature/230",
741
+ "feature/232",
742
+ "feature/300",
743
+ "feature/work-item",
744
+ ]
745
+ )
746
+
747
+ task = self._create_task(
748
+ task_config={
749
+ "options": {
750
+ "source_branch": "feature/230",
751
+ "branch_prefix": "feature/",
752
+ "update_future_releases": True,
753
+ }
754
+ }
755
+ )
756
+ task._init_task()
757
+
758
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
759
+
760
+ assert ["feature/232", "feature/300"] == actual_branches
761
+ assert 2 == len(responses.calls)
762
+
763
+ @responses.activate
764
+ def test_merge_to_future_release_branches_skip(self):
765
+ """Tests that commits to the main branch are merged to the expected feature branches"""
766
+ self._setup_mocks(
767
+ [
768
+ "main",
769
+ "feature/230",
770
+ "feature/232",
771
+ "feature/300",
772
+ "feature/302",
773
+ "feature/work-item",
774
+ ]
775
+ )
776
+
777
+ task = self._create_task(
778
+ task_config={
779
+ "options": {
780
+ "source_branch": "feature/230",
781
+ "branch_prefix": "feature/",
782
+ "update_future_releases": False,
783
+ }
784
+ }
785
+ )
786
+ task._init_task()
787
+
788
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
789
+
790
+ assert [] == actual_branches
791
+ assert 2 == len(responses.calls)
792
+
793
+ @responses.activate
794
+ def test_merge_to_future_release_branches_skip_future(self):
795
+ """
796
+ Tests that commits are not merged to "release" (numeric) branches
797
+ """
798
+
799
+ self._setup_mocks(
800
+ [
801
+ "main",
802
+ "feature/230",
803
+ "feature/232",
804
+ "feature/300",
805
+ "feature/work-item",
806
+ ]
807
+ )
808
+
809
+ task = self._create_task(
810
+ task_config={
811
+ "options": {
812
+ "source_branch": "main",
813
+ "branch_prefix": "feature/",
814
+ "update_future_releases": False,
815
+ "skip_future_releases": True,
816
+ }
817
+ }
818
+ )
819
+ task._init_task()
820
+
821
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
822
+
823
+ assert ["feature/230", "feature/work-item"] == actual_branches
824
+ assert 2 == len(responses.calls)
825
+
826
+ @responses.activate
827
+ def test_merge_to_future_release_branches_noskip_future(self):
828
+ """Tests that commits to the main branch are merged to the expected feature branches"""
829
+ self._setup_mocks(
830
+ [
831
+ "main",
832
+ "feature/230",
833
+ "feature/232",
834
+ "feature/300",
835
+ "feature/work-item",
836
+ ]
837
+ )
838
+
839
+ task = self._create_task(
840
+ task_config={
841
+ "options": {
842
+ "source_branch": "main",
843
+ "branch_prefix": "feature/",
844
+ "update_future_releases": False,
845
+ "skip_future_releases": False,
846
+ }
847
+ }
848
+ )
849
+ task._init_task()
850
+
851
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
852
+
853
+ assert [
854
+ "feature/230",
855
+ "feature/232",
856
+ "feature/300",
857
+ "feature/work-item",
858
+ ] == actual_branches
859
+ assert 2 == len(responses.calls)
860
+
861
+ @responses.activate
862
+ def test_merge_to_future_release_branches_missing_slash(self):
863
+ """Tests that commits to the main branch are merged to the expected feature branches"""
864
+ self._setup_mocks(
865
+ [
866
+ "main",
867
+ "prefix-no-slash230",
868
+ "prefix-no-slash232",
869
+ "prefix-no-slash300",
870
+ "prefix-no-slashwork-item",
871
+ ]
872
+ )
873
+
874
+ task = self._create_task(
875
+ task_config={
876
+ "options": {
877
+ "source_branch": "prefix-no-slash230",
878
+ "branch_prefix": "prefix-no-slash",
879
+ "update_future_releases": True,
880
+ }
881
+ }
882
+ )
883
+ task._init_task()
884
+
885
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
886
+
887
+ assert ["prefix-no-slash232", "prefix-no-slash300"] == actual_branches
888
+ assert 2 == len(responses.calls)
889
+
890
+ @responses.activate
891
+ def test_branches_to_merge__future_release_branches_and_children(self):
892
+ """Tests that commits to the upcoming release branch
893
+ are merged to future release branches and direct child descendents."""
894
+
895
+ self._setup_mocks(
896
+ [
897
+ "feature/230",
898
+ "feature/300",
899
+ "feature/400",
900
+ "feature/230__child1",
901
+ "feature/230__child1__grandchild",
902
+ "prefix-mismatch/230__child2",
903
+ ]
904
+ )
905
+
906
+ task = self._create_task(
907
+ task_config={
908
+ "options": {
909
+ "source_branch": "feature/230",
910
+ "branch_prefix": "feature/",
911
+ "update_future_releases": True,
912
+ }
913
+ }
914
+ )
915
+ task._init_task()
916
+
917
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
918
+ assert ["feature/230__child1", "feature/300", "feature/400"] == actual_branches
919
+ assert 2 == len(responses.calls)
920
+
921
+ @responses.activate
922
+ def test_merge_to_children_not_future_releases_output(self):
923
+ """Tests that commits to the main branch are merged to child feature branches
924
+ and not to future prerelease branches."""
925
+
926
+ prefix = "jupiter/"
927
+ source_branch = f"{prefix}230"
928
+ branch_to_merge = f"{prefix}230__child1"
929
+ other_branches = [
930
+ f"{prefix}300",
931
+ f"{prefix}230__child1__grandchild",
932
+ "prefix-mismatch/230__child2",
933
+ f"{prefix}130",
934
+ ]
935
+ self._setup_mocks([source_branch, branch_to_merge] + other_branches)
936
+
937
+ with LogCapture() as log:
938
+ task = self._create_task(
939
+ task_config={
940
+ "options": {
941
+ "source_branch": source_branch,
942
+ "branch_prefix": prefix,
943
+ }
944
+ }
945
+ )
946
+ task()
947
+
948
+ expected_log = log_header() + [
949
+ ("DEBUG", "Skipping branch jupiter/230: is source branch"),
950
+ (
951
+ "DEBUG",
952
+ "Skipping branch jupiter/300: is not a direct descendent of jupiter/230",
953
+ ),
954
+ (
955
+ "DEBUG",
956
+ "Skipping branch jupiter/230__child1__grandchild: is not a direct descendent of jupiter/230",
957
+ ),
958
+ (
959
+ "DEBUG",
960
+ "Skipping branch prefix-mismatch/230__child2: does not match prefix 'jupiter/'",
961
+ ),
962
+ (
963
+ "DEBUG",
964
+ "Skipping branch jupiter/130: is not a direct descendent of jupiter/230",
965
+ ),
966
+ (
967
+ "DEBUG",
968
+ "Found child branches to update: ['jupiter/230__child1']",
969
+ ),
970
+ (
971
+ "INFO",
972
+ "Merged 1 commits into branch: jupiter/230__child1",
973
+ ),
974
+ ]
975
+ actual_log = self._get_log_lines(log)
976
+ assert expected_log == actual_log
977
+ assert 5 == len(responses.calls)
978
+
979
+ @responses.activate
980
+ def test_branches_to_merge__children_not_future_releases(self):
981
+ """Tests that commits to the main branch are merged to child feature branches
982
+ and not to future prerelease branches."""
983
+
984
+ prefix = "jupiter/"
985
+ source_branch = f"{prefix}230"
986
+ branch_to_merge = f"{prefix}230__child"
987
+ other_branches = [
988
+ f"{prefix}300",
989
+ f"{prefix}230__child__grandchild",
990
+ "prefix-mismatch/230__child2",
991
+ f"{prefix}130",
992
+ ]
993
+ self._setup_mocks([source_branch, branch_to_merge] + other_branches)
994
+
995
+ task = self._create_task(
996
+ task_config={
997
+ "options": {
998
+ "source_branch": source_branch,
999
+ "branch_prefix": prefix,
1000
+ }
1001
+ }
1002
+ )
1003
+ task._init_task()
1004
+
1005
+ actual_branches = [branch.name for branch in task._get_branches_to_merge()]
1006
+ expected_branches = ["jupiter/230__child"]
1007
+
1008
+ assert expected_branches == actual_branches
1009
+ assert 2 == len(responses.calls)
1010
+
1011
+ def test_is_release_branch(self):
1012
+ prefix = "test/"
1013
+ valid_release_branches = [
1014
+ f"{prefix}000",
1015
+ f"{prefix}100",
1016
+ f"{prefix}199",
1017
+ f"{prefix}230",
1018
+ f"{prefix}20302",
1019
+ f"{prefix}3810102",
1020
+ f"{prefix}9711112",
1021
+ ]
1022
+ invalid_release_branches = [
1023
+ f"{prefix}200_",
1024
+ f"{prefix}_200" f"{prefix}230_",
1025
+ f"{prefix}230__child",
1026
+ f"{prefix}230__grand__child",
1027
+ f"{prefix}230a",
1028
+ f"{prefix}r1",
1029
+ f"{prefix}R1",
1030
+ ]
1031
+ task = self._create_task(
1032
+ task_config={
1033
+ "options": {
1034
+ "branch_prefix": prefix,
1035
+ }
1036
+ }
1037
+ )
1038
+ for branch in valid_release_branches:
1039
+ assert task._is_release_branch(branch)
1040
+ for branch in invalid_release_branches:
1041
+ assert not task._is_release_branch(branch)
1042
+
1043
+ @responses.activate
1044
+ def test_set_next_release(self):
1045
+ """Tests that the method sets _next_release as
1046
+ the lowest number that corresponds to a release branch"""
1047
+ self._setup_mocks(
1048
+ [
1049
+ "main",
1050
+ "feature/300",
1051
+ "feature/230",
1052
+ "feature/230__child__grandchild",
1053
+ "feature/88",
1054
+ "prefix-mismatch/230__child2",
1055
+ "feature/130",
1056
+ "feature/131",
1057
+ "f/33",
1058
+ "featurette/20",
1059
+ "features/15",
1060
+ ]
1061
+ )
1062
+
1063
+ task = self._create_task(
1064
+ task_config={
1065
+ "options": {
1066
+ "source_branch": "main",
1067
+ "branch_prefix": "feature/",
1068
+ }
1069
+ }
1070
+ )
1071
+ task._init_task()
1072
+
1073
+ repo_branches = list(task.repo.branches())
1074
+ assert task._get_next_release(repo_branches) == 88
1075
+
1076
+ @responses.activate
1077
+ def test_is_future_release_branch(self):
1078
+ """Tests whether the given branch name
1079
+ is a release branch that is occurring after
1080
+ the next release."""
1081
+
1082
+ self._setup_mocks(["feature/8"])
1083
+
1084
+ task = self._create_task(
1085
+ task_config={
1086
+ "options": {
1087
+ "source_branch": "main",
1088
+ "branch_prefix": "feature/",
1089
+ }
1090
+ }
1091
+ )
1092
+ task._init_task()
1093
+
1094
+ repo_branches = list(task.repo.branches())
1095
+ assert task._get_next_release(repo_branches) == 8
1096
+
1097
+ assert not task._is_future_release_branch("f", 8)
1098
+ assert not task._is_future_release_branch("feature", 8)
1099
+ assert not task._is_future_release_branch("feature/", 8)
1100
+ assert not task._is_future_release_branch("feature/_", 8)
1101
+ assert not task._is_future_release_branch("feature/0", 8)
1102
+ assert not task._is_future_release_branch("feature/O", 8)
1103
+ assert not task._is_future_release_branch("feature/7", 8)
1104
+ assert not task._is_future_release_branch("feature/8", 8)
1105
+ assert not task._is_future_release_branch("feature/9_", 8)
1106
+
1107
+ assert task._is_future_release_branch("feature/9", 8)
1108
+ assert task._is_future_release_branch("feature/75", 8)
1109
+ assert task._is_future_release_branch("feature/123", 8)
1110
+ assert task._is_future_release_branch("feature/4567", 8)
1111
+ assert task._is_future_release_branch("feature/10000", 8)
1112
+
1113
+
1114
+ def log_header():
1115
+ return [
1116
+ ("INFO", "Beginning task: MergeBranch"),
1117
+ ("INFO", ""),
1118
+ ]