Skip to content

Commit

Permalink
Merge branch 'main' into feature/loose-version-release-branches
Browse files Browse the repository at this point in the history
  • Loading branch information
jstvz committed Jun 4, 2024
2 parents 35082a0 + 8ad7eb7 commit 7b311b4
Show file tree
Hide file tree
Showing 89 changed files with 3,589 additions and 508 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/chores.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ jobs:
' cumulusci/cumulusci.yml
- name: Commit changes
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git switch -c "update-sfdc-api-v$VERSION"
git add cumulusci/cumulusci.yml
git commit -m "Automated update to sfdc API version $VERSION"
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/feature_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
jobs:
lint:
name: Lint
if: ${{ github.event_name == 'pull_request' }}
if: ${{ contains(fromJSON('["workflow_dispatch", "pull_request"]'), github.event_name) }}
uses: SFDO-Tooling/.github/.github/workflows/pre-commit.yml@main
docs:
name: Build Docs
Expand Down Expand Up @@ -42,6 +42,12 @@ jobs:
matrix:
os: [macos-latest, sfdc-ubuntu-latest, sfdc-windows-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
exclude:
- os: macos-latest
python-version: 3.8
include:
- os: macos-13
python-version: 3.8
steps:
- uses: actions/checkout@v2
- name: Set up Python
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,14 @@ jobs:
sed -e 's_\(https.*\/\)\([0-9]*\)$_[#\2](\1\2)_' \
-e 's_by @\(.*\) in_by [@\1](https://github.com/\1) in_' >> changelog.md
python utility/update-history.py
- name: Lint history
run: |
npm install prettier
npx prettier --write docs/history.md
- name: Commit changes
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git switch -c "release-$(hatch version)"
git add docs/history.md cumulusci/__about__.py
git commit -m "Update changelog (automated)"
Expand Down
2 changes: 1 addition & 1 deletion cumulusci/__about__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.83.0"
__version__ = "3.88.0"
1 change: 1 addition & 0 deletions cumulusci/core/dependencies/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ class UnmanagedDependency(StaticDependency, abc.ABC):
subfolder: Optional[str] = None
namespace_inject: Optional[str] = None
namespace_strip: Optional[str] = None
collision_check: Optional[bool] = None

def _get_unmanaged(self, org: OrgConfig):
if self.unmanaged is None:
Expand Down
10 changes: 10 additions & 0 deletions cumulusci/core/dependencies/tests/test_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -903,3 +903,13 @@ def test_parse_unmanaged_dependency(self):
}
)
assert isinstance(u, UnmanagedZipURLDependency)

u = parse_dependency(
{
"github": "https://github.com/Test/TestRepo",
"ref": "aaaaaaaa",
"collision_check": False,
"namespace_inject": "ns",
}
)
assert isinstance(u, UnmanagedGitHubRefDependency)
3 changes: 2 additions & 1 deletion cumulusci/core/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ def _load_project_config(self, *args, **kwargs):
self.project_config = self.project_config_cls(
self.universal_config, *args, **kwargs
)
self.project_config._add_tasks_directory_to_python_path()
if self.project_config is not None:
self.project_config._add_tasks_directory_to_python_path()

def _load_keychain(self):
if self.keychain is not None:
Expand Down
2 changes: 1 addition & 1 deletion cumulusci/core/sfdx.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def sfdx(
stdout=sarge.Capture(buffer_size=-1) if capture_output else None,
stderr=sarge.Capture(buffer_size=-1) if capture_output else None,
shell=True,
env={**env, "SFDX_DISABLE_TELEMETRY": "true"},
env={**env, "SFDX_TOOL": "CCI"},
)
p.run()
if capture_output:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,11 @@ interactions:
include_file: GET_sobjects_Global_describe.yaml
- &id007
include_file: GET_sobjects_Account_describe.yaml
- &id010
include_file: GET_sobjects_Account_describe.yaml
- *id006
- *id007
- *id010
- request:
method: POST
uri: https://orgname.my.salesforce.com/services/data/vxx.0/composite/sobjects
Expand Down
36 changes: 33 additions & 3 deletions cumulusci/core/tests/test_datasets_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def count(sobject):
objs["Account"].remove("Description")
objs["Account"].remove("History__c")
objs["Account"].remove("ns__Description__c")
objs["Account"].remove("ns__LinkedAccount__c")
objs["Account"].remove("Primary_Contact__c")
dataset.update_schema_subset(objs)
timer.checkpoint("Updated Subset")
Expand Down Expand Up @@ -225,11 +226,19 @@ def test_datasets_extract_standard_objects(
def test_datasets_read_explicit_extract_declaration(
self, sf, project_config, org_config, delete_data_from_org, ensure_accounts
):
object_counts = {"Account": 6, "Contact": 1, "Opportunity": 5}
object_counts = {
"Account": 6,
"Contact": 1,
"Opportunity": 5,
"Lead": 1,
"Event": 2,
}
obj_describes = (
describe_for("Account"),
describe_for("Contact"),
describe_for("Opportunity"),
describe_for("Lead"),
describe_for("Event"),
)
with patch.object(type(org_config), "is_person_accounts_enabled", False), patch(
"cumulusci.core.datasets.get_org_schema",
Expand Down Expand Up @@ -263,12 +272,16 @@ def write_yaml(filename: str, json: Any):
"Contact": {
"fields": ["FirstName", "LastName", "AccountId"]
},
"Event": {"fields": ["Subject", "WhoId"]},
}
},
)
loading_rules = write_yaml(
"loading_rules.load.yml",
[{"sf_object": "Account", "load_after": "Contact"}],
[
{"sf_object": "Account", "load_after": "Contact"},
{"sf_object": "Lead", "load_after": "Event"},
],
)

# Don't actually extract data.
Expand All @@ -286,17 +299,34 @@ def write_yaml(filename: str, json: Any):
"fields": ["FirstName", "LastName"],
"lookups": {
"AccountId": {
"table": "Account",
"table": ["Account"],
"key_field": "AccountId",
"after": "Insert Account",
}
},
},
"Insert Event": {
"sf_object": "Event",
"table": "Event",
"fields": ["Subject"],
"lookups": {
"WhoId": {
"table": ["Contact", "Lead"],
"key_field": "WhoId",
"after": "Insert Lead",
}
},
},
"Insert Account": {
"sf_object": "Account",
"table": "Account",
"fields": ["Name"],
},
"Insert Lead": {
"sf_object": "Lead",
"table": "Lead",
"fields": ["Company", "LastName"],
},
}
assert tuple(actual.items()) == tuple(expected.items()), actual.items()

Expand Down
17 changes: 16 additions & 1 deletion cumulusci/cumulusci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ tasks:
settings_type: EnhancedNotesSettings
settings_field: IsEnhancedNotesEnabled
value: True
retrieve_tasks:
description: Retrieves the tasks under the particular category or group
class_path: cumulusci.tasks.preflight.retrieve_tasks.RetrieveTasks
custom_settings_value_wait:
description: Waits for a specific field value on the specified custom settings object and field
class_path: cumulusci.tasks.salesforce.custom_settings_wait.CustomSettingValueWait
Expand Down Expand Up @@ -412,6 +415,14 @@ tasks:
description: Prints the metadata types in a project
class_path: cumulusci.tasks.util.ListMetadataTypes
group: Salesforce Metadata
list_nonsource_trackable_components:
description: List the components of non source trackable Metadata types.
class_path: cumulusci.tasks.salesforce.nonsourcetracking.ListComponents
group: Salesforce Metadata
list_nonsource_trackable_metadatatypes:
description: Returns non source trackable metadata types supported by org
class_path: cumulusci.tasks.salesforce.nonsourcetracking.ListNonSourceTrackable
group: Salesforce Metadata
meta_xml_apiversion:
description: Set the API version in ``*meta.xml`` files
class_path: cumulusci.tasks.metaxml.UpdateApi
Expand Down Expand Up @@ -501,6 +512,10 @@ tasks:
description: Retrieve changed components from a scratch org
class_path: cumulusci.tasks.salesforce.sourcetracking.RetrieveChanges
group: Salesforce Metadata
retrieve_nonsource_trackable:
description: Retrieves the non source trackable components filtered
class_path: cumulusci.tasks.salesforce.nonsourcetracking.RetrieveComponents
group: Salesforce Metadata
retrieve_qa_config:
description: Retrieves the current changes in the scratch org into unpackaged/config/qa
class_path: cumulusci.tasks.salesforce.sourcetracking.RetrieveChanges
Expand Down Expand Up @@ -1465,7 +1480,7 @@ project:
namespace:
install_class:
uninstall_class:
api_version: "59.0"
api_version: "60.0"
git:
default_branch: master
prefix_feature: feature/
Expand Down
14 changes: 14 additions & 0 deletions cumulusci/oauth/salesforce.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@
PROD_LOGIN_URL = os.environ.get("SF_PROD_LOGIN_URL") or "https://login.salesforce.com"


def update_login_urls():
"""
Updating to setup the environment variables dynamically
"""
global PROD_LOGIN_URL, SANDBOX_LOGIN_URL
PROD_LOGIN_URL = (
os.environ.get("SF_PROD_LOGIN_URL") or "https://login.salesforce.com"
)
SANDBOX_LOGIN_URL = (
os.environ.get("SF_SANDBOX_LOGIN_URL") or "https://test.salesforce.com"
)


def jwt_session(
client_id, private_key, username, url=None, auth_url=None, is_sandbox=False
):
Expand All @@ -31,6 +44,7 @@ def jwt_session(
:param username: Username to authenticate as
:param url: Org's instance_url
"""
update_login_urls()
if auth_url:
aud = (
SANDBOX_LOGIN_URL
Expand Down
5 changes: 4 additions & 1 deletion cumulusci/oauth/tests/test_salesforce.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from unittest import mock

import pytest
Expand Down Expand Up @@ -28,10 +29,12 @@ def test_jwt_session(encode):
@mock.patch("cumulusci.oauth.salesforce.jwt.encode")
def test_jwt_session__enhanced_domains_enabled(encode):
# raise an assertion error if the registered url was not accessed
os.environ["SF_PROD_LOGIN_URL"] = "https://login.test1.salesforce.com"
os.environ["SF_SANDBOX_LOGIN_URL"] = "https://test.test1.salesforce.com"
with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps:
rsps.add(
responses.POST,
"https://test.salesforce.com/services/oauth2/token",
"https://test.test1.salesforce.com/services/oauth2/token",
body='{"message":"well done mate!"}',
status=200,
)
Expand Down
12 changes: 6 additions & 6 deletions cumulusci/robotframework/Salesforce.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,11 +600,11 @@ def select_record_type(self, label):
self.selenium.click_button("Next")

@capture_screenshot_on_error
def select_app_launcher_app(self, app_name):
def select_app_launcher_app(self, app_name, timeout=30):
"""Navigates to a Salesforce App via the App Launcher"""
locator = lex_locators["app_launcher"]["app_link"].format(app_name)
self.open_app_launcher()
self.selenium.wait_until_page_contains_element(locator, timeout=30)
self.selenium.wait_until_page_contains_element(locator, timeout)
self.selenium.set_focus_to_element(locator)
elem = self.selenium.get_webelement(locator)
link = elem.find_element_by_xpath("../../..")
Expand All @@ -623,19 +623,19 @@ def select_app_launcher_tab(self, tab_name):
self.wait_until_modal_is_closed()

@capture_screenshot_on_error
def wait_until_modal_is_open(self):
def wait_until_modal_is_open(self, timeout=15):
"""Wait for modal to open"""
self.selenium.wait_until_page_contains_element(
lex_locators["modal"]["is_open"],
timeout=15,
timeout,
error="Expected to see a modal window, but didn't",
)

@capture_screenshot_on_error
def wait_until_modal_is_closed(self):
def wait_until_modal_is_closed(self, timeout=15):
"""Wait for modal to close"""
self.selenium.wait_until_page_does_not_contain_element(
lex_locators["modal"]["is_open"], timeout=15
lex_locators["modal"]["is_open"], timeout
)

@capture_screenshot_on_error
Expand Down
8 changes: 7 additions & 1 deletion cumulusci/salesforce_api/retrieve_profile_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ def __init__(
class RetrieveProfileApi(BaseSalesforceApiTask):
def _init_task(self):
super(RetrieveProfileApi, self)._init_task()
self.api_version = self.org_config.latest_api_version
self.api_version = self.project_config.config["project"]["package"][
"api_version"
]

def _retrieve_existing_profiles(self, profiles: List[str]):
query = self._build_query(["Name"], "Profile", {"Name": profiles})
Expand All @@ -97,6 +99,10 @@ def _retrieve_existing_profiles(self, profiles: List[str]):
for data in result["records"]:
existing_profiles.append(data["Name"])

# Since System Administrator is named Admin in Metadata API
if "Admin" in profiles:
existing_profiles.extend(["Admin", "System Administrator"])

return existing_profiles

def _run_query(self, query):
Expand Down
6 changes: 4 additions & 2 deletions cumulusci/salesforce_api/tests/test_retrieve_profile_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def retrieve_profile_api_instance():
project_config = MagicMock()
task_config = MagicMock()
org_config = MagicMock()
org_config.latest_api_version = "58.0"
project_config.config = {"project": {"package": {"api_version": "58.0"}}}
sf_mock.query.return_value = {"records": []}
api = RetrieveProfileApi(
project_config=project_config, org_config=org_config, task_config=task_config
Expand All @@ -36,7 +36,7 @@ def test_init_task(retrieve_profile_api_instance):


def test_retrieve_existing_profiles(retrieve_profile_api_instance):
profiles = ["Profile1", "Profile2"]
profiles = ["Profile1", "Profile2", "Admin"]
result = {"records": [{"Name": "Profile1"}]}
with patch.object(
RetrieveProfileApi, "_build_query", return_value="some_query"
Expand All @@ -47,6 +47,8 @@ def test_retrieve_existing_profiles(retrieve_profile_api_instance):

assert "Profile1" in existing_profiles
assert "Profile2" not in existing_profiles
assert "Admin" in existing_profiles
assert "System Administrator" in existing_profiles


def test_run_query_sf(retrieve_profile_api_instance):
Expand Down
Loading

0 comments on commit 7b311b4

Please sign in to comment.