Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion cumulusci/tasks/salesforce/sourcetracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ def _reset_sfdx_snapshot(self):
"namespace_tokenize"
]

retrieve_changes_task_options["output_dir"] = {
"description": (
"The output directory for the retrieved metadata. "
+ "If not specified, defaults to force-app or the target directory passed to retrieve changes."
),
"required": False,
}


def _write_manifest(changes, path, api_version):
"""Write a package.xml for the specified changes and API version."""
Expand Down Expand Up @@ -226,6 +234,7 @@ def retrieve_components(
project_config: BaseProjectConfig = None,
retrieve_complete_profile: bool = False,
capture_output: bool = False,
output_dir: str = None,
):
"""Retrieve specified components from an org into a target folder.

Expand All @@ -238,7 +247,10 @@ def retrieve_components(
to a namespace prefix to replace it with a `%%%NAMESPACE%%%` token.
"""

target = os.path.realpath(target)
# Always use output_dir if specified, else use target
retrieve_target = (
os.path.realpath(output_dir) if output_dir else os.path.realpath(target)
)
profiles = []
# If retrieve_complete_profile and project_config is None, raise error
# This is because project_config is only required if retrieve_complete_profile is True
Expand Down Expand Up @@ -302,6 +314,8 @@ def retrieve_components(
"-w",
"5",
"--ignore-conflicts",
"--output-dir",
retrieve_target,
],
capture_output=capture_output,
check_return=True,
Expand Down Expand Up @@ -364,6 +378,9 @@ def _init_options(self, kwargs):
self.options.get("retrieve_complete_profile", False)
)

# Get output_dir first
output_dir = self.options.get("output_dir")

# Check which directories are configured as dx packages
package_directories = []
default_package_directory = None
Expand Down Expand Up @@ -392,6 +409,7 @@ def _init_options(self, kwargs):
md_format = path not in package_directories
self.md_format = md_format
self.options["path"] = path
self.options["output_dir"] = output_dir

if "api_version" not in self.options:
self.options[
Expand All @@ -410,6 +428,7 @@ def _run_task(self):
self.logger.info("{MemberType}: {MemberName}".format(**change))

target = os.path.realpath(self.options["path"])
output_dir = self.options.get("output_dir")
package_xml_opts = {}
if self.options["path"] == "src":
package_xml_opts.update(
Expand All @@ -430,6 +449,7 @@ def _run_task(self):
extra_package_xml_opts=package_xml_opts,
project_config=self.project_config,
retrieve_complete_profile=self.options["retrieve_complete_profile"],
output_dir=output_dir,
)

if self.options["snapshot"]:
Expand Down
63 changes: 57 additions & 6 deletions cumulusci/tasks/salesforce/tests/test_sourcetracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
from cumulusci.utils import temporary_dir


@pytest.fixture
def vcr_cassette_dir():
return os.path.join(os.path.dirname(__file__), "cassettes")


class TestListChanges:
"""List the changes from a scratch org"""

Expand Down Expand Up @@ -180,12 +185,12 @@ def test_run_task(self, sfdx, create_task_fixture):
},
],
}
with mock.patch.object(
RetrieveProfile, "_run_task"
) as mock_retrieve_profile, mock.patch.object(
pathlib.Path, "exists", return_value=True
), mock.patch.object(
pathlib.Path, "is_dir", return_value=True
with (
mock.patch.object(
RetrieveProfile, "_run_task"
) as mock_retrieve_profile,
mock.patch.object(pathlib.Path, "exists", return_value=True),
mock.patch.object(pathlib.Path, "is_dir", return_value=True),
):
task._run_task()
assert sfdx_calls == [
Expand All @@ -208,6 +213,52 @@ def test_run_task__no_changes(self, sfdx, create_task_fixture):
task._run_task()
assert "No changes to retrieve" in messages

def test_run_task_with_output_dir(self, sfdx, create_task_fixture):
sfdx_calls = []
sfdx.side_effect = lambda cmd, *args, **kw: sfdx_calls.append(cmd)

with temporary_dir():
task = create_task_fixture(
RetrieveChanges,
{
"include": "Test",
"namespace_tokenize": "ns",
"retrieve_complete_profile": True,
"output_dir": "output",
},
)
task._init_task()
task.tooling = mock.Mock()
task.tooling.query_all.return_value = {
"totalSize": 1,
"records": [
{
"MemberType": "CustomObject",
"MemberName": "Test__c",
"RevisionCounter": 1,
},
{
"MemberType": "Profile",
"MemberName": "TestProfile",
"RevisionCounter": 1,
},
],
}
with (
mock.patch.object(
RetrieveProfile, "_run_task"
) as mock_retrieve_profile,
mock.patch.object(pathlib.Path, "exists", return_value=True),
mock.patch.object(pathlib.Path, "is_dir", return_value=True),
):
task._run_task()
assert sfdx_calls == [
"project convert mdapi",
"project retrieve start",
"project convert source",
]
mock_retrieve_profile.assert_called()


class TestSnapshotChanges:
@mock.patch("cumulusci.tasks.salesforce.sourcetracking.sfdx")
Expand Down
Loading