Skip to content

Commit cd43818

Browse files
committed
Adding an out-dir option to retreive changes
1 parent 950f27a commit cd43818

2 files changed

Lines changed: 78 additions & 7 deletions

File tree

cumulusci/tasks/salesforce/sourcetracking.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ def _reset_sfdx_snapshot(self):
179179
"namespace_tokenize"
180180
]
181181

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

183191
def _write_manifest(changes, path, api_version):
184192
"""Write a package.xml for the specified changes and API version."""
@@ -226,6 +234,7 @@ def retrieve_components(
226234
project_config: BaseProjectConfig = None,
227235
retrieve_complete_profile: bool = False,
228236
capture_output: bool = False,
237+
output_dir: str = None,
229238
):
230239
"""Retrieve specified components from an org into a target folder.
231240
@@ -238,7 +247,10 @@ def retrieve_components(
238247
to a namespace prefix to replace it with a `%%%NAMESPACE%%%` token.
239248
"""
240249

241-
target = os.path.realpath(target)
250+
# Always use output_dir if specified, else use target
251+
retrieve_target = (
252+
os.path.realpath(output_dir) if output_dir else os.path.realpath(target)
253+
)
242254
profiles = []
243255
# If retrieve_complete_profile and project_config is None, raise error
244256
# This is because project_config is only required if retrieve_complete_profile is True
@@ -302,6 +314,8 @@ def retrieve_components(
302314
"-w",
303315
"5",
304316
"--ignore-conflicts",
317+
"--output-dir",
318+
retrieve_target,
305319
],
306320
capture_output=capture_output,
307321
check_return=True,
@@ -364,6 +378,9 @@ def _init_options(self, kwargs):
364378
self.options.get("retrieve_complete_profile", False)
365379
)
366380

381+
# Get output_dir first
382+
output_dir = self.options.get("output_dir")
383+
367384
# Check which directories are configured as dx packages
368385
package_directories = []
369386
default_package_directory = None
@@ -392,6 +409,7 @@ def _init_options(self, kwargs):
392409
md_format = path not in package_directories
393410
self.md_format = md_format
394411
self.options["path"] = path
412+
self.options["output_dir"] = output_dir
395413

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

412430
target = os.path.realpath(self.options["path"])
431+
output_dir = self.options.get("output_dir")
413432
package_xml_opts = {}
414433
if self.options["path"] == "src":
415434
package_xml_opts.update(
@@ -430,6 +449,7 @@ def _run_task(self):
430449
extra_package_xml_opts=package_xml_opts,
431450
project_config=self.project_config,
432451
retrieve_complete_profile=self.options["retrieve_complete_profile"],
452+
output_dir=output_dir,
433453
)
434454

435455
if self.options["snapshot"]:

cumulusci/tasks/salesforce/tests/test_sourcetracking.py

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
from cumulusci.utils import temporary_dir
2121

2222

23+
@pytest.fixture
24+
def vcr_cassette_dir():
25+
return os.path.join(os.path.dirname(__file__), "cassettes")
26+
27+
2328
class TestListChanges:
2429
"""List the changes from a scratch org"""
2530

@@ -180,12 +185,12 @@ def test_run_task(self, sfdx, create_task_fixture):
180185
},
181186
],
182187
}
183-
with mock.patch.object(
184-
RetrieveProfile, "_run_task"
185-
) as mock_retrieve_profile, mock.patch.object(
186-
pathlib.Path, "exists", return_value=True
187-
), mock.patch.object(
188-
pathlib.Path, "is_dir", return_value=True
188+
with (
189+
mock.patch.object(
190+
RetrieveProfile, "_run_task"
191+
) as mock_retrieve_profile,
192+
mock.patch.object(pathlib.Path, "exists", return_value=True),
193+
mock.patch.object(pathlib.Path, "is_dir", return_value=True),
189194
):
190195
task._run_task()
191196
assert sfdx_calls == [
@@ -208,6 +213,52 @@ def test_run_task__no_changes(self, sfdx, create_task_fixture):
208213
task._run_task()
209214
assert "No changes to retrieve" in messages
210215

216+
def test_run_task_with_output_dir(self, sfdx, create_task_fixture):
217+
sfdx_calls = []
218+
sfdx.side_effect = lambda cmd, *args, **kw: sfdx_calls.append(cmd)
219+
220+
with temporary_dir():
221+
task = create_task_fixture(
222+
RetrieveChanges,
223+
{
224+
"include": "Test",
225+
"namespace_tokenize": "ns",
226+
"retrieve_complete_profile": True,
227+
"output_dir": "output",
228+
},
229+
)
230+
task._init_task()
231+
task.tooling = mock.Mock()
232+
task.tooling.query_all.return_value = {
233+
"totalSize": 1,
234+
"records": [
235+
{
236+
"MemberType": "CustomObject",
237+
"MemberName": "Test__c",
238+
"RevisionCounter": 1,
239+
},
240+
{
241+
"MemberType": "Profile",
242+
"MemberName": "TestProfile",
243+
"RevisionCounter": 1,
244+
},
245+
],
246+
}
247+
with (
248+
mock.patch.object(
249+
RetrieveProfile, "_run_task"
250+
) as mock_retrieve_profile,
251+
mock.patch.object(pathlib.Path, "exists", return_value=True),
252+
mock.patch.object(pathlib.Path, "is_dir", return_value=True),
253+
):
254+
task._run_task()
255+
assert sfdx_calls == [
256+
"project convert mdapi",
257+
"project retrieve start",
258+
"project convert source",
259+
]
260+
mock_retrieve_profile.assert_called()
261+
211262

212263
class TestSnapshotChanges:
213264
@mock.patch("cumulusci.tasks.salesforce.sourcetracking.sfdx")

0 commit comments

Comments
 (0)