Skip to content

Commit

Permalink
@W-16566993: Migrating From SFDX to SFCLI (#3829)
Browse files Browse the repository at this point in the history
[W-16566993](https://gus.lightning.force.com/a07EE00001zeux8YAA)

Migrating from SFDX CLI to SF CLI

---------

Co-authored-by: James Estevez <[email protected]>
  • Loading branch information
lakshmi2506 and jstvz committed Nov 12, 2024
1 parent 42093d7 commit 77e2fdc
Show file tree
Hide file tree
Showing 28 changed files with 111 additions and 116 deletions.
1 change: 0 additions & 1 deletion cumulusci/cli/tests/test_org.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,6 @@ def test_org_list(self, cli_tbl):
],
title="Connected Orgs",
)

assert scratch_table_call in cli_tbl.call_args_list
assert connected_table_call in cli_tbl.call_args_list
runtime.keychain.cleanup_org_cache_dirs.assert_called_once()
Expand Down
31 changes: 15 additions & 16 deletions cumulusci/core/config/scratch_org_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def days_alive(self) -> Optional[int]:
return delta.days + 1

def create_org(self) -> None:
"""Uses sfdx force:org:create to create the org"""
"""Uses sf org create scratch to create the org"""
if not self.config_file:
raise ScratchOrgException(
f"Scratch org config {self.name} is missing a config_file"
Expand All @@ -72,7 +72,7 @@ def create_org(self) -> None:
args: List[str] = self._build_org_create_args()
extra_args = os.environ.get("SFDX_ORG_CREATE_ARGS", "")
p: sarge.Command = sfdx(
f"force:org:create --json {extra_args}",
f"org create scratch --json {extra_args}",
args=args,
username=None,
log_note="Creating scratch org",
Expand Down Expand Up @@ -139,33 +139,32 @@ def _build_org_create_args(self) -> List[str]:
args = ["-f", self.config_file, "-w", "120"]
devhub_username: Optional[str] = self._choose_devhub_username()
if devhub_username:
args += ["--targetdevhubusername", devhub_username]
args += ["--target-dev-hub", devhub_username]
if not self.namespaced:
args += ["-n"]
args += ["--no-namespace"]
if self.noancestors:
args += ["--noancestors"]
args += ["--no-ancestors"]
if self.days:
args += ["--durationdays", str(self.days)]
args += ["--duration-days", str(self.days)]
if self.release:
args += [f"release={self.release}"]
args += [f"--release={self.release}"]
if self.sfdx_alias:
args += ["-a", self.sfdx_alias]
with open(self.config_file, "r") as org_def:
org_def_data = json.load(org_def)
org_def_has_email = "adminEmail" in org_def_data
if self.email_address and not org_def_has_email:
args += [f"adminEmail={self.email_address}"]
args += [f"--admin-email={self.email_address}"]
if self.default:
args += ["-s"]
if instance := self.instance or os.environ.get("SFDX_SIGNUP_INSTANCE"):
args += [f"instance={instance}"]
args += ["--set-default"]

return args

def _choose_devhub_username(self) -> Optional[str]:
"""Determine which devhub username to specify when calling sfdx, if any."""
# If a devhub was specified via `cci org scratch`, use it.
# (This will return None if "devhub" isn't set in the org config,
# in which case sfdx will use its defaultdevhubusername.)
# in which case sf will use its target-dev-hub.)
devhub_username = self.devhub
if not devhub_username and self.keychain is not None:
# Otherwise see if one is configured via the "devhub" service
Expand All @@ -178,7 +177,7 @@ def _choose_devhub_username(self) -> Optional[str]:
return devhub_username

def generate_password(self) -> None:
"""Generates an org password with: sfdx force:user:password:generate.
"""Generates an org password with: sf org generate password.
On a non-zero return code, set the password_failed in our config
and log the output (stdout/stderr) from sfdx."""

Expand All @@ -187,7 +186,7 @@ def generate_password(self) -> None:
return

p: sarge.Command = sfdx(
"force:user:password:generate",
"org generate password",
self.username,
log_note="Generating scratch org user password",
)
Expand All @@ -214,13 +213,13 @@ def can_delete(self) -> bool:
return bool(self.date_created)

def delete_org(self) -> None:
"""Uses sfdx force:org:delete to delete the org"""
"""Uses sf org delete scratch to delete the org"""
if not self.created:
self.logger.info("Skipping org deletion: the scratch org does not exist.")
return

p: sarge.Command = sfdx(
"force:org:delete -p", self.username, "Deleting scratch org"
"org delete scratch -p", self.username, "Deleting scratch org"
)
sfdx_output: List[str] = list(p.stdout_text) + list(p.stderr_text)

Expand Down
14 changes: 7 additions & 7 deletions cumulusci/core/config/sfdx_org_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def sfdx_info(self):
if not self.print_json:
self.logger.info(f"Getting org info from Salesforce CLI for {username}")

# Call force:org:display and parse output to get instance_url and
# Call org display and parse output to get instance_url and
# access_token
p = sfdx("force:org:display --json", self.username)
p = sfdx("org display --json", self.username)

org_info = None
stderr_list = [line.strip() for line in p.stderr_text]
Expand Down Expand Up @@ -166,7 +166,7 @@ def get_access_token(self, **userfields):
else:
username = result[0]["Username"]

p = sfdx(f"force:org:display --targetusername={username} --json")
p = sfdx(f"org display --target-org={username} --json")
if p.returncode:
output = p.stdout_text.read()
try:
Expand All @@ -183,9 +183,9 @@ def get_access_token(self, **userfields):
return info["result"]["accessToken"]

def force_refresh_oauth_token(self):
# Call force:org:display and parse output to get instance_url and
# Call org display and parse output to get instance_url and
# access_token
p = sfdx("force:org:open -r", self.username, log_note="Refreshing OAuth token")
p = sfdx("org open -r", self.username, log_note="Refreshing OAuth token")

stdout_list = [line.strip() for line in p.stdout_text]

Expand All @@ -198,7 +198,7 @@ def force_refresh_oauth_token(self):

# Added a print json argument to check whether it is there or not
def refresh_oauth_token(self, keychain, print_json=False):
"""Use sfdx force:org:describe to refresh token instead of built in OAuth handling"""
"""Use sfdx org display to refresh token instead of built in OAuth handling"""
if hasattr(self, "_sfdx_info"):
# Cache the sfdx_info for 1 hour to avoid unnecessary calls out to sfdx CLI
delta = datetime.datetime.utcnow() - self._sfdx_info_date
Expand All @@ -208,7 +208,7 @@ def refresh_oauth_token(self, keychain, print_json=False):
# Force a token refresh
self.force_refresh_oauth_token()
self.print_json = print_json
# Get org info via sfdx force:org:display
# Get org info via sf org display
self.sfdx_info
# Get additional org info by querying API
self._load_orginfo()
18 changes: 8 additions & 10 deletions cumulusci/core/config/tests/test_config_expensive.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ def test_get_access_token(self, Command):
with mock.patch("cumulusci.core.config.sfdx_org_config.sfdx", sfdx):
access_token = config.get_access_token(alias="dadvisor")
sfdx.assert_called_once_with(
"force:org:display --targetusername[email protected] --json"
"org display --target-org[email protected] --json"
)
assert access_token == "the-token"

Expand Down Expand Up @@ -792,7 +792,6 @@ def test_build_org_create_args(self, scratch_def_file):
"noancestors": True,
"sfdx_alias": "project__org",
"default": True,
"instance": "NA01",
"release": "previous",
},
"test",
Expand All @@ -804,18 +803,17 @@ def test_build_org_create_args(self, scratch_def_file):
"tmp.json",
"-w",
"120",
"--targetdevhubusername",
"--target-dev-hub",
"[email protected]",
"-n",
"--noancestors",
"--durationdays",
"--no-namespace",
"--no-ancestors",
"--duration-days",
"1",
"release=previous",
"--release=previous",
"-a",
"project__org",
"[email protected]",
"-s",
"instance=NA01",
"[email protected]",
"--set-default",
]

def test_build_org_create_args__email_in_scratch_def(self):
Expand Down
2 changes: 1 addition & 1 deletion cumulusci/core/dependencies/tests/test_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ def test_get_metadata_package_zip_builder__sfdx(
context=mock.ANY,
)
sfdx_mock.assert_called_once_with(
"force:source:convert",
"project convert source",
args=["-d", mock.ANY, "-r", "force-app"],
capture_output=True,
check_return=True,
Expand Down
8 changes: 2 additions & 6 deletions cumulusci/core/keychain/base_project_keychain.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,7 @@ def set_default_org(self, name):
org.config["default"] = True
org.save()
if org.created:
sfdx(
sarge.shell_format(
"force:config:set defaultusername={}", org.sfdx_alias
)
)
sfdx(sarge.shell_format("force config set target-org={}", org.sfdx_alias))

def unset_default_org(self):
"""unset the default orgs for tasks"""
Expand All @@ -110,7 +106,7 @@ def unset_default_org(self):
if org_config.default:
del org_config.config["default"]
org_config.save()
sfdx("force:config:set defaultusername=")
sfdx("config unset target-org=")

# This implementation of get_default_org, set_default_org, and unset_default_org
# is currently kept for backwards compatibility, but EncryptedFileProjectKeychain
Expand Down
14 changes: 7 additions & 7 deletions cumulusci/core/sfdx.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ def sfdx(
Returns a `sarge` Command instance with returncode, stdout, stderr
"""
command = f"sfdx {command}"
command = f"sf {command}"
if args is not None:
for arg in args:
command += " " + shell_quote(arg)
if username:
command += f" -u {shell_quote(username)}"
command += f" -o {shell_quote(username)}"
if log_note:
logger.info(f"{log_note} with command: {command}")
# Avoid logging access token
if access_token:
command += f" -u {shell_quote(access_token)}"
command += f" -o {shell_quote(access_token)}"
env = env or {}
p = sarge.Command(
command,
Expand Down Expand Up @@ -86,15 +86,15 @@ def shell_quote(s: str):

def get_default_devhub_username():
p = sfdx(
"force:config:get defaultdevhubusername --json",
"config get target-dev-hub --json",
log_note="Getting default Dev Hub username from sfdx",
check_return=True,
)
result = json.load(p.stdout_text)
if "result" not in result or "value" not in result["result"][0]:
raise SfdxOrgException(
"No sfdx config found for defaultdevhubusername. "
"Please use the sfdx force:config:set to set the defaultdevhubusername and run again."
"No sf config found for target-dev-hub. "
"Please use the sf config set to set the target-dev-hub and run again."
)
username = result["result"][0]["value"]
return username
Expand Down Expand Up @@ -145,7 +145,7 @@ def convert_sfdx_source(
if name:
args += ["-n", name]
sfdx(
"force:source:convert",
"project convert source",
args=args,
capture_output=True,
check_return=True,
Expand Down
9 changes: 5 additions & 4 deletions cumulusci/core/tests/test_sfdx.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ class TestSfdx:
def test_posix_quoting(self, Command):
sfdx("cmd", args=["a'b"])
cmd = Command.call_args[0][0]
assert cmd == r"sfdx cmd 'a'\''b'"
assert cmd == r"sf cmd 'a'\''b'"

@mock.patch("platform.system", mock.Mock(return_value="Windows"))
@mock.patch("sarge.Command")
def test_windows_quoting(self, Command):
sfdx("cmd", args=['a"b'], access_token="token")
cmd = Command.call_args[0][0]
assert cmd == r'sfdx cmd "a\"b" -u token'
print(cmd)
assert cmd == r'sf cmd "a\"b" -o token'

@mock.patch("platform.system", mock.Mock(return_value="Windows"))
def test_shell_quote__str_with_space(self):
Expand Down Expand Up @@ -93,7 +94,7 @@ def test_convert_sfdx():
assert p is not None

sfdx.assert_called_once_with(
"force:source:convert",
"project convert source",
args=["-d", mock.ANY, "-r", path, "-n", "Test Package"],
capture_output=True,
check_return=True,
Expand All @@ -109,7 +110,7 @@ def test_convert_sfdx__cwd():
assert p is not None

sfdx.assert_called_once_with(
"force:source:convert",
"project convert source",
args=["-d", mock.ANY, "-n", "Test Package"],
capture_output=True,
check_return=True,
Expand Down
8 changes: 4 additions & 4 deletions cumulusci/cumulusci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -271,14 +271,14 @@ tasks:
path: unpackaged/config/qa
group: Salesforce Metadata
dx:
description: Execute an arbitrary Salesforce DX command against an org. Use the 'command' option to specify the command, such as 'force:package:install'
description: Execute an arbitrary Salesforce DX command against an org. Use the 'command' option to specify the command, such as 'package install'
class_path: cumulusci.tasks.sfdx.SFDXOrgTask
group: Salesforce DX
dx_convert_to:
description: Converts src directory metadata format into sfdx format under force-app
class_path: cumulusci.tasks.sfdx.SFDXBaseTask
options:
command: "force:mdapi:convert -r src"
command: "project convert mdapi -r src"
group: Salesforce DX
dx_convert_from:
description: Converts force-app directory in sfdx format into metadata format under src
Expand All @@ -290,13 +290,13 @@ tasks:
description: Uses sfdx to pull from a scratch org into the force-app directory
class_path: cumulusci.tasks.sfdx.SFDXOrgTask
options:
command: "force:source:pull"
command: "project retrieve start --ignore-conflicts"
group: Salesforce DX
dx_push:
description: Uses sfdx to push the force-app directory metadata into a scratch org
class_path: cumulusci.tasks.sfdx.SFDXOrgTask
options:
command: "force:source:push"
command: "project deploy start --ignore-conflicts"
group: Salesforce DX
enable_einstein_prediction:
description: Enable an Einstein Prediction Builder prediction.
Expand Down
4 changes: 2 additions & 2 deletions cumulusci/tasks/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class SalesforceCommand(Command):
"""Execute a Command with SF credentials provided on the environment.
Provides:
* SF_INSTANCE_URL
* SF_ORG_INSTANCE_URL
* SF_ACCESS_TOKEN
"""

Expand All @@ -158,7 +158,7 @@ def _update_credentials(self):
def _get_env(self):
env = super(SalesforceCommand, self)._get_env()
env["SF_ACCESS_TOKEN"] = self.org_config.access_token
env["SF_INSTANCE_URL"] = self.org_config.instance_url
env["SF_ORG_INSTANCE_URL"] = self.org_config.instance_url
return env


Expand Down
Loading

0 comments on commit 77e2fdc

Please sign in to comment.