Skip to content

Commit 702ce54

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

2 files changed

Lines changed: 70 additions & 1 deletion

File tree

cumulusci/tasks/salesforce/sourcetracking.py

Lines changed: 19 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,8 @@ 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 = os.path.realpath(output_dir) if output_dir else os.path.realpath(target)
242252
profiles = []
243253
# If retrieve_complete_profile and project_config is None, raise error
244254
# This is because project_config is only required if retrieve_complete_profile is True
@@ -302,6 +312,8 @@ def retrieve_components(
302312
"-w",
303313
"5",
304314
"--ignore-conflicts",
315+
"--output-dir",
316+
retrieve_target,
305317
],
306318
capture_output=capture_output,
307319
check_return=True,
@@ -364,6 +376,9 @@ def _init_options(self, kwargs):
364376
self.options.get("retrieve_complete_profile", False)
365377
)
366378

379+
# Get output_dir first
380+
output_dir = self.options.get("output_dir")
381+
367382
# Check which directories are configured as dx packages
368383
package_directories = []
369384
default_package_directory = None
@@ -392,6 +407,7 @@ def _init_options(self, kwargs):
392407
md_format = path not in package_directories
393408
self.md_format = md_format
394409
self.options["path"] = path
410+
self.options["output_dir"] = output_dir
395411

396412
if "api_version" not in self.options:
397413
self.options[
@@ -410,6 +426,7 @@ def _run_task(self):
410426
self.logger.info("{MemberType}: {MemberName}".format(**change))
411427

412428
target = os.path.realpath(self.options["path"])
429+
output_dir = self.options.get("output_dir")
413430
package_xml_opts = {}
414431
if self.options["path"] == "src":
415432
package_xml_opts.update(
@@ -430,6 +447,7 @@ def _run_task(self):
430447
extra_package_xml_opts=package_xml_opts,
431448
project_config=self.project_config,
432449
retrieve_complete_profile=self.options["retrieve_complete_profile"],
450+
output_dir=output_dir,
433451
)
434452

435453
if self.options["snapshot"]:

cumulusci/tasks/salesforce/tests/test_sourcetracking.py

Lines changed: 51 additions & 0 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

@@ -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 mock.patch.object(
248+
RetrieveProfile, "_run_task"
249+
) as mock_retrieve_profile, mock.patch.object(
250+
pathlib.Path, "exists", return_value=True
251+
), mock.patch.object(
252+
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)