Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@W-16566993: Migrating From SFDX to SFCLI #3829

Merged
merged 11 commits into from
Oct 14, 2024
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 @@ -267,14 +267,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 @@ -286,13 +286,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
Loading