diff --git a/Makefile b/Makefile index c8b07424dd..df28ac22bb 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,7 @@ coverage: ## check code coverage quickly with the default Python docs: ## generate Sphinx HTML documentation $(MAKE) -C docs clean cci task doc > docs/tasks.rst + cci flow doc > docs/flows.rst $(MAKE) -C docs html $(BROWSER) docs/_build/html/index.html diff --git a/cumulusci/cli/cci.py b/cumulusci/cli/cci.py index 8d14c0e8eb..5e5bd2fef9 100644 --- a/cumulusci/cli/cci.py +++ b/cumulusci/cli/cci.py @@ -46,13 +46,14 @@ from cumulusci.cli.runtime import get_installed_version from cumulusci.cli.ui import CliTable, CROSSMARK, SimpleSalesforceUIHelpers from cumulusci.salesforce_api.utils import get_simple_salesforce_connection -from cumulusci.utils import doc_task +from cumulusci.utils import doc_task, document_flow, flow_ref_title_and_intro from cumulusci.utils import parse_api_datetime from cumulusci.utils import get_cci_upgrade_command from cumulusci.utils.git import current_branch from cumulusci.utils.logging import tee_stdout_stderr from cumulusci.oauth.salesforce import CaptureSalesforceOAuth from cumulusci.core.utils import cleanup_org_cache_dirs +from cumulusci.utils.yaml.cumulusci_yml import cci_safe_load from .logger import init_logger, get_tempfile_logger @@ -1360,6 +1361,56 @@ def task_doc(runtime): click.echo("") +@flow.command(name="doc", help="Exports RST format documentation for all flows") +@pass_runtime(require_project=False) +def flow_doc(runtime): + with open("docs/flows.yml", "r", encoding="utf-8") as f: + flow_info = cci_safe_load(f) + + click.echo(flow_ref_title_and_intro(flow_info["intro_blurb"])) + + flow_info_groups = list(flow_info["groups"].keys()) + + flows = ( + runtime.project_config.list_flows() + if runtime.project_config is not None + else runtime.universal_config.list_flows() + ) + flows_by_group = group_items(flows) + flow_groups = sorted( + flows_by_group.keys(), + key=lambda group: flow_info_groups.index(group) + if group in flow_info_groups + else 100, + ) + + for group in flow_groups: + click.echo(f"{group}\n{'-' * len(group)}") + if group in flow_info["groups"]: + click.echo(flow_info["groups"][group]["description"]) + + for flow in sorted(flows_by_group[group]): + flow_name, flow_description = flow + try: + flow_coordinator = runtime.get_flow(flow_name) + except FlowNotFoundError as e: + raise click.UsageError(str(e)) + + additional_info = None + if flow_name in flow_info.get("flows", {}): + additional_info = flow_info["flows"][flow_name]["rst_text"] + + click.echo( + document_flow( + flow_name, + flow_description, + flow_coordinator, + additional_info=additional_info, + ) + ) + click.echo("") + + @task.command(name="info", help="Displays information for a task") @click.argument("task_name") @pass_runtime(require_project=False, require_keychain=True) diff --git a/cumulusci/cli/tests/test_cci.py b/cumulusci/cli/tests/test_cci.py index 3b3b27fbbc..ab474c418e 100644 --- a/cumulusci/cli/tests/test_cci.py +++ b/cumulusci/cli/tests/test_cci.py @@ -1956,6 +1956,58 @@ def test_flow_info__not_found(self): with self.assertRaises(click.UsageError): run_click_command(cci.flow_info, runtime=runtime, flow_name="test") + @mock.patch("cumulusci.cli.cci.group_items") + @mock.patch("cumulusci.cli.cci.document_flow") + def test_flow_doc__no_flows_rst_file(self, doc_flow, group_items): + runtime = mock.Mock() + runtime.universal_config.flows = {"test": {}} + flow_config = FlowConfig({"description": "Test Flow", "steps": {}}) + runtime.get_flow.return_value = FlowCoordinator(None, flow_config) + + group_items.return_value = {"Group One": [["test flow", "description"]]} + + run_click_command(cci.flow_doc, runtime=runtime) + group_items.assert_called_once() + doc_flow.assert_called() + + @mock.patch("cumulusci.cli.cci.click.echo") + @mock.patch("cumulusci.cli.cci.cci_safe_load") + def test_flow_doc__with_flows_rst_file(self, safe_load, echo): + runtime = CliRuntime( + config={ + "flows": { + "Flow1": { + "steps": {}, + "description": "Description of Flow1", + "group": "Group1", + } + } + }, + load_keychain=False, + ) + + safe_load.return_value = { + "intro_blurb": "opening blurb for flow reference doc", + "groups": { + "Group1": {"description": "This is a description of group1."}, + }, + "flows": {"Flow1": {"rst_text": "Some ``extra`` **pizzaz**!"}}, + } + + run_click_command(cci.flow_doc, runtime=runtime) + + assert 1 == safe_load.call_count + + expected_call_args = [ + "Flow Reference\n==========================================\n\nopening blurb for flow reference doc\n.. contents::\n :depth: 2\n :local:\n\n", + "Group1\n------", + "This is a description of group1.", + "Flow1\n^^^^^\n\n**Description:** Description of Flow1\n\nSome ``extra`` **pizzaz**!\n**Flow Steps**\n\n.. code-block:: console\n", + "", + ] + expected_call_args = [mock.call(s) for s in expected_call_args] + assert echo.call_args_list == expected_call_args + def test_flow_run(self): org_config = mock.Mock(scratch=True, config={}) runtime = CliRuntime( @@ -2009,9 +2061,7 @@ def test_flow_run_o_error(self): ) assert "-o" in str(e.value) - def test_flow_run_delete_non_scratch( - self, - ): + def test_flow_run_delete_non_scratch(self): org_config = mock.Mock(scratch=False) runtime = mock.Mock() runtime.get_org.return_value = ("test", org_config) diff --git a/cumulusci/core/flowrunner.py b/cumulusci/core/flowrunner.py index 6dfaf21672..80b0addc27 100644 --- a/cumulusci/core/flowrunner.py +++ b/cumulusci/core/flowrunner.py @@ -283,12 +283,24 @@ def _rule(self, fill="=", length=60, new_line=False): self.logger.info("") def get_summary(self): - """Returns an output string that contains the description of the flow, - the sequence of tasks and subflows, and any "when" conditions associated - with tasks.""" + """Returns an output string that contains the description of the flow + and its steps.""" lines = [] if "description" in self.flow_config.config: lines.append(f"Description: {self.flow_config.config['description']}") + + step_lines = self.get_flow_steps() + if step_lines: + lines.append("\nFlow Steps") + lines.extend(step_lines) + + return "\n".join(lines) + + def get_flow_steps(self, for_docs=False): + """Returns a list of flow steps (tasks and sub-flows) for the given flow. + For docs, indicates whether or not we want to use the string for use in a code-block + of an rst file. If True, will omit output of source information.""" + lines = [] previous_parts = [] previous_source = None for step in self.steps: @@ -311,18 +323,29 @@ def get_summary(self): else: source = "" if len(previous_parts) < i + 1 or previous_parts[i] != flow_name: + if for_docs: + source = "" + lines.append(f"{' ' * i}{steps[i]}) flow: {flow_name}{source}") if source: new_source = "" padding = " " * (i + 1) + " " * len(str(steps[i + 1])) - when = f"\n{padding} when: {step.when}" if step.when is not None else "" + when = f"{padding} when: {step.when}" if step.when is not None else "" + + if for_docs: + new_source = "" + lines.append( - f"{' ' * (i + 1)}{steps[i + 1]}) task: {task_name}{new_source}{when}" + f"{' ' * (i + 1)}{steps[i + 1]}) task: {task_name}{new_source}" ) + if when: + lines.append(when) + previous_parts = parts previous_source = step.project_config.source - return "\n".join(lines) + + return lines def run(self, org_config): self.org_config = org_config diff --git a/cumulusci/core/tests/test_flowrunner.py b/cumulusci/core/tests/test_flowrunner.py index e2ef08a7f7..48ce581fc5 100644 --- a/cumulusci/core/tests/test_flowrunner.py +++ b/cumulusci/core/tests/test_flowrunner.py @@ -150,6 +150,7 @@ def test_get_summary(self): actual_output = flow.get_summary() expected_output = ( "Description: test description" + + "\n\nFlow Steps" + "\n1) flow: nested_flow_2 [from current folder]" + "\n 1) task: pass_name" + "\n 2) flow: nested_flow" @@ -157,6 +158,38 @@ def test_get_summary(self): ) self.assertEqual(expected_output, actual_output) + def test_get_flow_steps(self): + self.project_config.config["flows"]["test"] = { + "description": "test description", + "steps": {"1": {"flow": "nested_flow_2"}}, + } + flow_config = self.project_config.get_flow("test") + flow = FlowCoordinator(self.project_config, flow_config, name="test_flow") + actual_output = flow.get_flow_steps() + expected_output = [ + "1) flow: nested_flow_2 [from current folder]", + " 1) task: pass_name", + " 2) flow: nested_flow", + " 1) task: pass_name", + ] + self.assertEqual(expected_output, actual_output) + + def test_get_flow_steps__for_docs(self): + self.project_config.config["flows"]["test"] = { + "description": "test description", + "steps": {"1": {"flow": "nested_flow_2"}}, + } + flow_config = self.project_config.get_flow("test") + flow = FlowCoordinator(self.project_config, flow_config, name="test_flow") + actual_output = flow.get_flow_steps(for_docs=True) + expected_output = [ + "1) flow: nested_flow_2", + " 1) task: pass_name", + " 2) flow: nested_flow", + " 1) task: pass_name", + ] + self.assertEqual(expected_output, actual_output) + def test_get_summary__substeps(self): flow = FlowCoordinator.from_steps( self.project_config, @@ -183,11 +216,13 @@ def test_get_summary__multiple_sources(self): ), ], ) + actual_output = flow.get_summary() assert ( - "1) flow: test" + "\nFlow Steps" + + "\n1) flow: test" + "\n 1) task: other:test1 [from other source]" + "\n 2) task: test2 [from current folder]" - ) == flow.get_summary() + ) == actual_output def test_init__options(self): """ A flow can accept task options and pass them to the task. """ diff --git a/cumulusci/tests/test_utils.py b/cumulusci/tests/test_utils.py index cb350301c6..a3769412e3 100644 --- a/cumulusci/tests/test_utils.py +++ b/cumulusci/tests/test_utils.py @@ -12,8 +12,10 @@ import responses from cumulusci import utils -from cumulusci.core.config import TaskConfig +from cumulusci.core.config import TaskConfig, FlowConfig +from cumulusci.core.flowrunner import FlowCoordinator from cumulusci.core.tasks import BaseTask +from cumulusci.tests.util import create_project_config class FunTestTask(BaseTask): @@ -261,6 +263,45 @@ def test_create_task_options_doc(self, option_info): assert option_two_doc == ["\t *Optional*", "\n\t Brief description here."] + def test_document_flow(self): + project_config = create_project_config("TestOwner", "TestRepo") + flow_config = FlowConfig({"description": "Test Flow", "steps": {}}) + coordinator = FlowCoordinator(project_config, flow_config, name="test_flow") + flow_doc = utils.document_flow("test flow", "test description.", coordinator) + + expected_doc = ( + "test flow" + "\n^^^^^^^^^\n" + "\n**Description:** test description.\n" + "\n**Flow Steps**\n" + "\n.. code-block:: console\n" + ) + + assert expected_doc == flow_doc + + def test_document_flow__additional_info(self): + flow_steps = ["1) (Task) Extract"] + flow_coordinator = mock.Mock(get_flow_steps=mock.Mock(return_value=flow_steps)) + other_info = "**this is** just some rst ``formatted`` text." + + flow_doc = utils.document_flow( + "test flow", + "test description.", + flow_coordinator, + additional_info=other_info, + ) + + expected_doc = ( + "test flow" + "\n^^^^^^^^^\n" + "\n**Description:** test description.\n" + f"\n{other_info}" + "\n**Flow Steps**\n" + "\n.. code-block:: console\n" + "\n\t1) (Task) Extract" + ) + assert expected_doc == flow_doc + @responses.activate def test_download_extract_zip(self): f = io.BytesIO() diff --git a/cumulusci/utils/__init__.py b/cumulusci/utils/__init__.py index 9c63f15cbe..5632d9457f 100644 --- a/cumulusci/utils/__init__.py +++ b/cumulusci/utils/__init__.py @@ -479,6 +479,43 @@ def create_task_options_doc(task_options): return doc +def flow_ref_title_and_intro(intro_blurb): + return f"""Flow Reference +========================================== +\n{intro_blurb} +.. contents:: + :depth: 2 + :local: + +""" + + +def document_flow(flow_name, description, flow_coordinator, additional_info=None): + """Document (project specific) flow configurations in RST format""" + doc = [] + + doc.append(f"{flow_name}\n{'^' * len(flow_name)}\n") + doc.append(f"**Description:** {description}\n") + + if additional_info: + doc.append(additional_info) + + doc.append("**Flow Steps**\n") + doc.append(".. code-block:: console\n") + flow_step_lines = flow_coordinator.get_flow_steps(for_docs=True) + # extra indent beneath code-block and finish with pipe for extra space afterwards + flow_step_lines = [f"\t{line}" for line in flow_step_lines] + # fix when clauses + lines = [] + for line in flow_step_lines: + if line.startswith("when"): + line = f"\t\t{line}" + lines.append(line) + doc.extend(lines) + + return "\n".join(doc) + + def package_xml_from_dict(items, api_version, package_name=None): lines = [] diff --git a/docs/flows.rst b/docs/flows.rst new file mode 100644 index 0000000000..6349ed23dd --- /dev/null +++ b/docs/flows.rst @@ -0,0 +1,657 @@ +Flow Reference +========================================== + +CumulusCI's suite of standard flows are grouped into various categories depending on their intended purpose. + +.. contents:: + :depth: 2 + :local: + + +Org Setup +--------- +These are the primary flows for doing full setup of an org. +They typically include a flow from the Dependency Management group, +a flow from either the Deployment or Install / Uninstall group, +and a flow from the Post-Install Configuration group. + +dev_org +^^^^^^^ + +**Description:** Set up an org as a development environment for unmanaged metadata + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) flow: deploy_unmanaged + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" and not org_config.scratch + 1) task: unschedule_apex + 2) task: update_package_xml + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) task: deploy + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3.1) task: dx_push + when: project_config.project__source_format == "sfdx" and org_config.scratch + 4) task: uninstall_packaged_incremental + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) flow: config_dev + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: snapshot_changes + +dev_org_beta_deps +^^^^^^^^^^^^^^^^^ + +**Description:** Set up an org as a development environment for unmanaged metadata based on the latest dependencies (including betas). + +**Flow Steps** + +.. code-block:: console + + 1) flow: beta_dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) flow: deploy_unmanaged + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" and not org_config.scratch + 1) task: unschedule_apex + 2) task: update_package_xml + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) task: deploy + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3.1) task: dx_push + when: project_config.project__source_format == "sfdx" and org_config.scratch + 4) task: uninstall_packaged_incremental + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) flow: config_dev + 1) task: deploy_post + 2) task: update_admin_profile + +dev_org_namespaced +^^^^^^^^^^^^^^^^^^ + +**Description:** Set up a namespaced scratch org as a development environment for unmanaged metadata + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) flow: deploy_unmanaged + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" and not org_config.scratch + 1) task: unschedule_apex + 2) task: update_package_xml + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) task: deploy + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3.1) task: dx_push + when: project_config.project__source_format == "sfdx" and org_config.scratch + 4) task: uninstall_packaged_incremental + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) flow: config_dev + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: snapshot_changes + +install_beta +^^^^^^^^^^^^ + +**Description:** Install and configure the latest beta version + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) task: install_managed_beta + 3) flow: config_managed + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: snapshot_changes + +install_prod +^^^^^^^^^^^^ + +**Description:** Install and configure the latest production version + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) task: install_managed + 3) flow: config_managed + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: snapshot_changes + +qa_org +^^^^^^ + +**Description:** Set up an org as a QA environment for unmanaged metadata + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) flow: deploy_unmanaged + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" and not org_config.scratch + 1) task: unschedule_apex + 2) task: update_package_xml + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) task: deploy + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3.1) task: dx_push + when: project_config.project__source_format == "sfdx" and org_config.scratch + 4) task: uninstall_packaged_incremental + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) flow: config_qa + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: snapshot_changes + +regression_org +^^^^^^^^^^^^^^ + +**Description:** Simulates an org that has been upgraded from the latest release of to the current beta and its dependencies, but deploys any unmanaged metadata from the current beta. + +**Flow Steps** + +.. code-block:: console + + 1) flow: install_regression + 1) flow: beta_dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) task: install_managed + 3) task: install_managed_beta + 2) flow: config_regression + 1) flow: config_managed + 1) task: deploy_post + 2) task: update_admin_profile + 3) task: snapshot_changes + +Dependency Management +--------------------- +These flows deploy dependencies (base packages and unmanaged metadata) to a target org environment. + +beta_dependencies +^^^^^^^^^^^^^^^^^ + +**Description:** Deploy the latest (beta) version of dependencies to prepare the org environment for the package metadata + +**Flow Steps** + +.. code-block:: console + + 1) task: update_dependencies + 2) task: deploy_pre + +dependencies +^^^^^^^^^^^^ + +**Description:** Deploy dependencies to prepare the org environment for the package metadata + +**Flow Steps** + +.. code-block:: console + + 1) task: update_dependencies + 2) task: deploy_pre + +Deployment +---------- +These flows deploy the main package metadata to a target org environment. + +deploy_packaging +^^^^^^^^^^^^^^^^ + +**Description:** Process and deploy the package metadata to the packaging org + +**Flow Steps** + +.. code-block:: console + + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" + 1) task: unschedule_apex + 2) task: create_managed_src + 3) task: update_package_xml + 4) task: deploy + 5) task: revert_managed_src + 6) task: uninstall_packaged_incremental + +deploy_unmanaged +^^^^^^^^^^^^^^^^ + +**Description:** Deploy the unmanaged metadata from the package + +**Flow Steps** + +.. code-block:: console + + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" and not org_config.scratch + 1) task: unschedule_apex + 2) task: update_package_xml + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) task: deploy + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3.1) task: dx_push + when: project_config.project__source_format == "sfdx" and org_config.scratch + 4) task: uninstall_packaged_incremental + when: project_config.project__source_format != "sfdx" or not org_config.scratch + +deploy_unmanaged_ee +^^^^^^^^^^^^^^^^^^^ + +**Description:** Deploy the unmanaged metadata from the package to an Enterprise Edition org + +**Flow Steps** + +.. code-block:: console + + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" + 1) task: unschedule_apex + 2) task: update_package_xml + 3) task: create_unmanaged_ee_src + 4) task: deploy + 5) task: revert_unmanaged_ee_src + 6) task: uninstall_packaged_incremental + +unmanaged_ee +^^^^^^^^^^^^ + +**Description:** Deploy the unmanaged package metadata and all dependencies to the target EE org + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) flow: deploy_unmanaged_ee + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" + 1) task: unschedule_apex + 2) task: update_package_xml + 3) task: create_unmanaged_ee_src + 4) task: deploy + 5) task: revert_unmanaged_ee_src + 6) task: uninstall_packaged_incremental + +Install / Uninstall +------------------- +These flows handle package installation and uninstallation in particular scenarios. + +install_prod_no_config +^^^^^^^^^^^^^^^^^^^^^^ + +**Description:** Install but do not configure the latest production version + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) task: install_managed + 3) task: deploy_post + +install_regression +^^^^^^^^^^^^^^^^^^ + +**Description:** Install the latest beta dependencies and upgrade to the latest beta version from the most recent production version + +**Flow Steps** + +.. code-block:: console + + 1) flow: beta_dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) task: install_managed + 3) task: install_managed_beta + +uninstall_managed +^^^^^^^^^^^^^^^^^ + +**Description:** Uninstall the installed managed version of the package. Run this before install_beta or install_prod if a version is already installed in the target org. + +**Flow Steps** + +.. code-block:: console + + 1) task: uninstall_post + 2) task: uninstall_managed + +Post-Install Configuration +-------------------------- +These flows perform configuration after the main package has been installed or deployed. + +config_apextest +^^^^^^^^^^^^^^^ + +**Description:** Configure an org to run apex tests after package metadata is deployed + +**Flow Steps** + +.. code-block:: console + + 1) task: deploy_post + 2) task: update_admin_profile + +config_dev +^^^^^^^^^^ + +**Description:** Configure an org for use as a dev org after package metadata is deployed + +**Flow Steps** + +.. code-block:: console + + 1) task: deploy_post + 2) task: update_admin_profile + +config_managed +^^^^^^^^^^^^^^ + +**Description:** Configure an org for use as a dev org after package metadata is deployed + +**Flow Steps** + +.. code-block:: console + + 1) task: deploy_post + 2) task: update_admin_profile + +config_packaging +^^^^^^^^^^^^^^^^ + +**Description:** Configure packaging org for upload after package metadata is deployed + +**Flow Steps** + +.. code-block:: console + + 1) task: update_admin_profile + +config_qa +^^^^^^^^^ + +**Description:** Configure an org for use as a QA org after package metadata is deployed + +**Flow Steps** + +.. code-block:: console + + 1) task: deploy_post + 2) task: update_admin_profile + +config_regression +^^^^^^^^^^^^^^^^^ + +**Description:** Configure an org for QA regression after the package is installed + +**Flow Steps** + +.. code-block:: console + + 1) flow: config_managed + 1) task: deploy_post + 2) task: update_admin_profile + +Continuous Integration +---------------------- +These flows are designed to be run automatically by a continuous integration (CI) system +in response to new commits. They typically set up an org and run Apex tests. + +ci_beta +^^^^^^^ + +**Description:** Install the latest beta version and runs apex tests from the managed package + +**Flow Steps** + +.. code-block:: console + + 1) flow: install_beta + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) task: install_managed_beta + 3) flow: config_managed + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: snapshot_changes + 2) task: run_tests + +ci_feature +^^^^^^^^^^ + +**Description:** Prepare an unmanaged metadata test org and run Apex tests. Intended for use against feature branch commits. + +**Flow Steps** + +.. code-block:: console + + 0.5) task: github_parent_pr_notes + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) flow: deploy_unmanaged + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" and not org_config.scratch + 1) task: unschedule_apex + 2) task: update_package_xml + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) task: deploy + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3.1) task: dx_push + when: project_config.project__source_format == "sfdx" and org_config.scratch + 4) task: uninstall_packaged_incremental + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) flow: config_apextest + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: run_tests + 5) task: github_automerge_feature + +ci_feature_2gp +^^^^^^^^^^^^^^ + +**Description:** Install as a managed 2gp package and run Apex tests. Intended for use after build_feature_test_package. + +**Flow Steps** + +.. code-block:: console + + 1) task: github_package_data + 2) flow: beta_dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 3) task: install_managed + 4) flow: config_managed + 1) task: deploy_post + 2) task: update_admin_profile + 5) task: run_tests + +ci_feature_beta_deps +^^^^^^^^^^^^^^^^^^^^ + +**Description:** Install the latest beta version of dependencies and run apex tests. + +**Flow Steps** + +.. code-block:: console + + 0.5) task: github_parent_pr_notes + 1) flow: beta_dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) flow: deploy_unmanaged + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" and not org_config.scratch + 1) task: unschedule_apex + 2) task: update_package_xml + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) task: deploy + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3.1) task: dx_push + when: project_config.project__source_format == "sfdx" and org_config.scratch + 4) task: uninstall_packaged_incremental + when: project_config.project__source_format != "sfdx" or not org_config.scratch + 3) flow: config_apextest + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: run_tests + 5) task: github_automerge_feature + +ci_master +^^^^^^^^^ + +**Description:** Deploy the package metadata to the packaging org and prepare for managed package version upload. Intended for use against main branch commits. + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) flow: deploy_packaging + 0) task: dx_convert_from + when: project_config.project__source_format == "sfdx" + 1) task: unschedule_apex + 2) task: create_managed_src + 3) task: update_package_xml + 4) task: deploy + 5) task: revert_managed_src + 6) task: uninstall_packaged_incremental + 3) flow: config_packaging + 1) task: update_admin_profile + +ci_release +^^^^^^^^^^ + +**Description:** Install a production release version and runs tests from the managed package + +**Flow Steps** + +.. code-block:: console + + 1) flow: install_prod + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) task: install_managed + 3) flow: config_managed + 1) task: deploy_post + 2) task: update_admin_profile + 4) task: snapshot_changes + 2) task: run_tests + +Release Operations +------------------ +These flows are used to release new package versions. + +build_feature_test_package +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Description:** Create a 2gp managed package version + +**Flow Steps** + +.. code-block:: console + + 1) flow: dependencies + 1) task: update_dependencies + 2) task: deploy_pre + 2) task: update_package_xml + when: project_config.project__source_format != "sfdx" + 3) task: create_package_version + +release_beta +^^^^^^^^^^^^ + +**Description:** Upload and release a beta version of the metadata currently in packaging + +**Flow Steps** + +.. code-block:: console + + 1) task: upload_beta + 2) task: github_release + 3) task: github_release_notes + 4) task: github_automerge_main + +release_production +^^^^^^^^^^^^^^^^^^ + +**Description:** Upload and release a production version of the metadata currently in packaging + +**Flow Steps** + +.. code-block:: console + + 1) task: upload_production + 2) task: github_release + 3) task: github_release_notes + +Other +----- +This is a catch-all group for any flows without a designated "group" attribute in ``cumulusci.yml``. + +robot_docs +^^^^^^^^^^ + +**Description:** Generates documentation for robot framework libraries + +**Flow Steps** + +.. code-block:: console + + 1) task: robot_libdoc + 2) task: robot_testdoc + +test_performance_LDV +^^^^^^^^^^^^^^^^^^^^ + +**Description:** Test performance in an LDV org + +**Flow Steps** + +.. code-block:: console + + 1) task: robot + +test_performance_scratch +^^^^^^^^^^^^^^^^^^^^^^^^ + +**Description:** Test performance of a scratch org + +**Flow Steps** + +.. code-block:: console + + 1) task: robot + diff --git a/docs/flows.yml b/docs/flows.yml new file mode 100644 index 0000000000..b8368d0f38 --- /dev/null +++ b/docs/flows.yml @@ -0,0 +1,32 @@ +intro_blurb: > + CumulusCI's suite of standard flows are grouped into various categories depending on their intended purpose. + +groups: + Org Setup: + description: | + These are the primary flows for doing full setup of an org. + They typically include a flow from the Dependency Management group, + a flow from either the Deployment or Install / Uninstall group, + and a flow from the Post-Install Configuration group. + Dependency Management: + description: | + These flows deploy dependencies (base packages and unmanaged metadata) to a target org environment. + Deployment: + description: | + These flows deploy the main package metadata to a target org environment. + Install / Uninstall: + description: | + These flows handle package installation and uninstallation in particular scenarios. + Post-Install Configuration: + description: | + These flows perform configuration after the main package has been installed or deployed. + Continuous Integration: + description: | + These flows are designed to be run automatically by a continuous integration (CI) system + in response to new commits. They typically set up an org and run Apex tests. + Release Operations: + description: | + These flows are used to release new package versions. + Other: + description: | + This is a catch-all group for any flows without a designated "group" attribute in ``cumulusci.yml``. diff --git a/docs/index.rst b/docs/index.rst index f40d68cc77..11d12b086d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,6 +24,7 @@ Contents: :maxdepth: 1 tasks + flows history authors contributing diff --git a/docs/tasks.rst b/docs/tasks.rst index cf3a820bbe..b7543a2f22 100644 --- a/docs/tasks.rst +++ b/docs/tasks.rst @@ -431,6 +431,11 @@ Options The value to check for +``-o treat_missing_as_failure TREATMISSINGASFAILURE`` + *Optional* + + If True, treat a missing Settings entity as a preflight failure, instead of raising an exception. Defaults to False. + **check_chatter_enabled** ========================================== @@ -469,6 +474,11 @@ Options Default: True +``-o treat_missing_as_failure TREATMISSINGASFAILURE`` + *Optional* + + If True, treat a missing Settings entity as a preflight failure, instead of raising an exception. Defaults to False. + **custom_settings_value_wait** ==========================================