From 3d784423783566d682a62cab38be2f714f462a55 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 11:16:23 -0700 Subject: [PATCH 1/4] Release v4.4.0 (#3898) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Arvind Bhamidipati Co-authored-by: James Estevez --- cumulusci/__about__.py | 2 +- docs/history.md | 250 ++++++++++++++++++++++------------------- 2 files changed, 134 insertions(+), 118 deletions(-) diff --git a/cumulusci/__about__.py b/cumulusci/__about__.py index 29baa2b4f6..ecdb1cef9e 100644 --- a/cumulusci/__about__.py +++ b/cumulusci/__about__.py @@ -1 +1 @@ -__version__ = "4.3.0.dev0" +__version__ = "4.4.0" diff --git a/docs/history.md b/docs/history.md index a2cf0fdc6b..2e7e443c03 100644 --- a/docs/history.md +++ b/docs/history.md @@ -2,13 +2,32 @@ +## v4.4.0 (2025-05-05) + + + +## What's Changed + +### Changes + +- Add new tasks get_assignable_permission_sets and get_assignable_licenses by [@vsbharath](https://github.com/vsbharath) in [#3892](https://github.com/SFDO-Tooling/CumulusCI/pull/3892) + +### Issues Fixed + +- fix: Make get permset licenses return active only by [@jstvz](https://github.com/jstvz) in [#3888](https://github.com/SFDO-Tooling/CumulusCI/pull/3888) +- fix: Read the docs configuration by LaTeX into PDF by [@dcinzona](https://github.com/dcinzona) in [#3891](https://github.com/SFDO-Tooling/CumulusCI/pull/3891) + +**Full Changelog**: https://github.com/SFDO-Tooling/CumulusCI/compare/v4.3.0.dev0...v4.4.0 + + + ## v4.3.0.dev0 (2025-02-19) ## What's Changed -### Changes +### Changes - @W-17717398: Fix for Error When Local Records Are Empty During SELECT Action by [@aditya-balachander](https://github.com/aditya-balachander) in [#3877](https://github.com/SFDO-Tooling/CumulusCI/pull/3877) - Changed Check Components to add a get repo components function by [@jain-naman-sf](https://github.com/jain-naman-sf) in [#3881](https://github.com/SFDO-Tooling/CumulusCI/pull/3881) @@ -16,15 +35,13 @@ **Full Changelog**: https://github.com/SFDO-Tooling/CumulusCI/compare/v4.3.0...v4.3.0.dev0 - - ## v4.3.0 (2025-02-07) ## What's Changed -### Changes +### Changes - Fix the check_sobjects_available task to take the api_version from Cumulusci.yml by [@lakshmi2506](https://github.com/lakshmi2506) in [#3875](https://github.com/SFDO-Tooling/CumulusCI/pull/3875) @@ -36,7 +53,7 @@ ## What's Changed -### Changes +### Changes - fix: Prevent 'directory not empty' error in `snowfakery` on Linux by [@schenkkp](https://github.com/schenkkp) in [#3864](https://github.com/SFDO-Tooling/CumulusCI/pull/3864) - @W-17621812: Update \_get_required_permission_types to handle SELECT operations by [@aditya-balachander](https://github.com/aditya-balachander) in [#3870](https://github.com/SFDO-Tooling/CumulusCI/pull/3870) @@ -54,7 +71,7 @@ ## What's Changed -### Changes +### Changes - Remove default declaration for select rows query by [@mjawadtp](https://github.com/mjawadtp) in [#3867](https://github.com/SFDO-Tooling/CumulusCI/pull/3867) @@ -75,7 +92,7 @@ ## What's Changed -### Changes +### Changes - @W-17427085: Set ANNOY related dependencies to be optional by [@aditya-balachander](https://github.com/aditya-balachander) in [#3858](https://github.com/SFDO-Tooling/CumulusCI/pull/3858) - Update on the documentation for SFDX_ORG_CREATE_ARGS environment variable by [@lakshmi2506](https://github.com/lakshmi2506) in [#3861](https://github.com/SFDO-Tooling/CumulusCI/pull/3861) @@ -88,7 +105,7 @@ ## What's Changed -### Changes +### Changes - @W-16485311: Core Logic for Selecting Records from Target Org by [@aditya-balachander](https://github.com/aditya-balachander) in [#3818](https://github.com/SFDO-Tooling/CumulusCI/pull/3818) - Add integration tests for all selection strategies by [@mjawadtp](https://github.com/mjawadtp) in [#3851](https://github.com/SFDO-Tooling/CumulusCI/pull/3851) @@ -101,7 +118,7 @@ ## v4.0.1 (2024-11-18) -### Issues Fixed +### Issues Fixed - Fixed a ModuleNotFoundError for docutils by adding the dependency `docutils` by [@jstvz](https://github.com/jstvz) in [#3558](https://github.com/SFDO-Tooling/CumulusCI/pull/3558). @@ -111,7 +128,7 @@ ## What's Changed -### Critical Changes +### Critical Changes - Python versions 3.8, 3.9, and 3.10 are no longer supported. - Switch to `sf` CLI commands [@lakshmi2506](https://github.com/lakshmi2506) in [#3829](https://github.com/SFDO-Tooling/CumulusCI/pull/3829) @@ -125,7 +142,7 @@ ## What's Changed -### Changes +### Changes - fix: escape stage name when running ensure_record_type task by [@leo-dcfa](https://github.com/leo-dcfa) in [#3827](https://github.com/SFDO-Tooling/CumulusCI/pull/3827) - fix: Upgrade upload-artifact action by [@jstvz](https://github.com/jstvz) in [#3831](https://github.com/SFDO-Tooling/CumulusCI/pull/3831) @@ -144,7 +161,7 @@ ## What's Changed -### Changes +### Changes - fix: Update input handlers with new Salesforce lightning-primitive tags by [@chanyahn-st](https://github.com/chanyahn-st) in [#3822](https://github.com/SFDO-Tooling/CumulusCI/pull/3822) @@ -160,7 +177,7 @@ ## What's Changed -### Changes +### Changes - Fix to Include All Keys in standardValue XML for add_standard_value_set_entries Task from Entries Option with Backward Compatibility by [@lakshmi2506](https://github.com/lakshmi2506) in [#3820](https://github.com/SFDO-Tooling/CumulusCI/pull/3820) @@ -172,7 +189,7 @@ ## What's Changed -### Changes +### Changes - Fix to Suppress the required field check for the upsert action at mapping step by [@lakshmi2506](https://github.com/lakshmi2506) in [#3817](https://github.com/SFDO-Tooling/CumulusCI/pull/3817) @@ -184,7 +201,7 @@ ## What's Changed -### Changes +### Changes - Add tasks to extract and upload files (Salesforce Files) by [@mjawadtp](https://github.com/mjawadtp) in [#3801](https://github.com/SFDO-Tooling/CumulusCI/pull/3801) - Update the validation for loading to check the required fields as well by [@lakshmi2506](https://github.com/lakshmi2506) in [#3807](https://github.com/SFDO-Tooling/CumulusCI/pull/3807) @@ -197,7 +214,7 @@ ## What's Changed -### Changes +### Changes - Added the `list_files` task to display files in an org by [@lakshmi2506](https://github.com/lakshmi2506) in [#3799](https://github.com/SFDO-Tooling/CumulusCI/pull/3799) - The `api_names` option of the `assign_permission_set_licenses` task now accepts either `DeveloperName` or `PermissionSetLicenseKey` by [@lakshmi2506](https://github.com/lakshmi2506) in [#3798](https://github.com/SFDO-Tooling/CumulusCI/pull/3798) @@ -208,12 +225,12 @@ ## What's Changed -### Changes +### Changes - Extend modal close wait with custom timeout by [@leboff](https://github.com/leboff) in [#3783](https://github.com/SFDO-Tooling/CumulusCI/pull/3783) - Added check_output true to get the logs of metadata retrieval by [@lakshmi2506](https://github.com/lakshmi2506) in [#3789](https://github.com/SFDO-Tooling/CumulusCI/pull/3789) -### Issues Fixed +### Issues Fixed - Fix retrieve unpackaged so it is usable in metadeploy by [@yippie](https://github.com/yippie) in [#3566](https://github.com/SFDO-Tooling/CumulusCI/pull/3566) @@ -229,7 +246,7 @@ ## What's Changed -### Changes +### Changes - Don't add fullname tag in 2GP package.xml by [@leboff](https://github.com/leboff) in [#3748](https://github.com/SFDO-Tooling/CumulusCI/pull/3748) @@ -251,7 +268,7 @@ ## What's Changed -### Changes +### Changes - @W-15258380 - Reloading of login URL's from env before creating jwt session by [@lakshmi2506](https://github.com/lakshmi2506) in [#3765](https://github.com/SFDO-Tooling/CumulusCI/pull/3765) @@ -263,7 +280,7 @@ ## What's Changed -### Changes +### Changes - Fix Invalid Lookups of namespaced fields by [@aditya-balachander](https://github.com/aditya-balachander) in [#3759](https://github.com/SFDO-Tooling/CumulusCI/pull/3759) - Fix Id Not Specified on Update Call by [@aditya-balachander](https://github.com/aditya-balachander) in [#3761](https://github.com/SFDO-Tooling/CumulusCI/pull/3761) @@ -277,7 +294,7 @@ ## What's Changed -### Changes +### Changes - Fix: Type Error while loading Contacts when PersonAccount is enabled by [@jkasturi-sf](https://github.com/jkasturi-sf) in [#3756](https://github.com/SFDO-Tooling/CumulusCI/pull/3756) @@ -289,7 +306,7 @@ ## What's Changed -### Changes +### Changes - Polymorphic Lookup Data Extraction by [@aditya-balachander](https://github.com/aditya-balachander) in [#3741](https://github.com/SFDO-Tooling/CumulusCI/pull/3741) - ADR: Migrate from SFDX to SF CLI by [@jstvz](https://github.com/jstvz) in [#3630](https://github.com/SFDO-Tooling/CumulusCI/pull/3630) @@ -303,7 +320,7 @@ ## What's Changed -### Changes +### Changes - Fix `is_person_type` `AttributeError` in record type handling by [@aditya-balachander](https://github.com/aditya-balachander) in [#3739](https://github.com/SFDO-Tooling/CumulusCI/pull/3739) @@ -315,7 +332,7 @@ ## What's Changed -### Changes +### Changes - Incorrect generation of record type mapping table name in a namespaced org context by [@lakshmi2506](https://github.com/lakshmi2506) in [#3713](https://github.com/SFDO-Tooling/CumulusCI/pull/3713) - Retrieve pre-flight checks by [@lakshmi2506](https://github.com/lakshmi2506) in [#3723](https://github.com/SFDO-Tooling/CumulusCI/pull/3723) @@ -339,7 +356,7 @@ ## What's Changed -### Changes +### Changes - Allowed namespace injection without managed by [@jain-naman-sf](https://github.com/jain-naman-sf) in [#3677](https://github.com/SFDO-Tooling/CumulusCI/pull/3677) - Update pyright configuration for 1.1.339 by [@jstvz](https://github.com/jstvz) in [#3715](https://github.com/SFDO-Tooling/CumulusCI/pull/3715) @@ -353,11 +370,11 @@ ## What's Changed -### Critical Changes +### Critical Changes - Remove `robot_lint` task and dependencies by [@jstvz](https://github.com/jstvz) in [#3697](https://github.com/SFDO-Tooling/CumulusCI/pull/3697) -### Changes +### Changes - Show an error message when no `origin` remote is present by [@lakshmi2506](https://github.com/lakshmi2506) in [#3679](https://github.com/SFDO-Tooling/CumulusCI/pull/3679) - Improve task `return_values` documentation by [@lakshmi2506](https://github.com/lakshmi2506) in [#3689](https://github.com/SFDO-Tooling/CumulusCI/pull/3689) @@ -365,7 +382,7 @@ - Support Python 3.12 by [@jstvz](https://github.com/jstvz) in [#3691](https://github.com/SFDO-Tooling/CumulusCI/pull/3691) - Make task `options` read only when using Pydantic option validation by [@aditya-balachander](https://github.com/aditya-balachander) in [#3695](https://github.com/SFDO-Tooling/CumulusCI/pull/3695) -### Issues Fixed +### Issues Fixed - Fix Github url parse error for some scenarios by [@mgrandhi](https://github.com/mgrandhi) in [#3683](https://github.com/SFDO-Tooling/CumulusCI/pull/3683) @@ -381,7 +398,7 @@ ## What's Changed -### Changes +### Changes - Add option to specify release window in `cci org scratch` by [@jain-naman-sf](https://github.com/jain-naman-sf) in [#3653](https://github.com/SFDO-Tooling/CumulusCI/pull/3653) - Add describe_metadatatypes task by [@lakshmi2506](https://github.com/lakshmi2506) in [#3669](https://github.com/SFDO-Tooling/CumulusCI/pull/3669) @@ -400,7 +417,7 @@ ## What's Changed -### Changes +### Changes - Allow setting Major and Minor Version in upload_production task by [@jain-naman-sf](https://github.com/jain-naman-sf) in [#3651](https://github.com/SFDO-Tooling/CumulusCI/pull/3651) - Add better error handling for empty or invalid org and service env vars by [@prescod](https://github.com/prescod) in [#3365](https://github.com/SFDO-Tooling/CumulusCI/pull/3365) @@ -414,7 +431,7 @@ - Improve message description handling for scratch org cli `not_found` error by [@lakshmi2506](https://github.com/lakshmi2506) in [#3659](https://github.com/SFDO-Tooling/CumulusCI/pull/3659) - Add `deactivate_flows` task by [@lakshmi2506](https://github.com/lakshmi2506) in [#3664](https://github.com/SFDO-Tooling/CumulusCI/pull/3664) -### Issues Fixed +### Issues Fixed - Add guard for empty body to github_release_report by [@jstvz](https://github.com/jstvz) in [#3645](https://github.com/SFDO-Tooling/CumulusCI/pull/3645) @@ -435,7 +452,7 @@ ## What's Changed -### Changes +### Changes - Added workarounds to support Vlocity local compilation in CI by [@jstvz](https://github.com/jstvz) in [#3642](https://github.com/SFDO-Tooling/CumulusCI/pull/3642) @@ -447,12 +464,12 @@ ## What's Changed -### Changes +### Changes - Updated Permission Set preflights to handle Permission Set Groups by [@jkasturi-sf](https://github.com/jkasturi-sf) in [#3623](https://github.com/SFDO-Tooling/CumulusCI/pull/3623) - Added the `create_pull_request_on_conflict` option to automerge tasks by [@BenjaminFrench](https://github.com/ BenjaminFrench) in [#3632](https://github.com/SFDO-Tooling/CumulusCI/pull/3632) -### Issues Fixed +### Issues Fixed - Fixed issues with uploading some Unlocked Packages by [@jstvz](https://github.com/jstvz) in [#3636](https://github.com/SFDO-Tooling/CumulusCI/pull/3636) - Corrected behavior of the `skip_future_releases` option by [@jstvz](https://github.com/jstvz) in [#3624](https://github.com/SFDO-Tooling/CumulusCI/pull/3624) @@ -465,7 +482,7 @@ ## What's Changed -### Changes +### Changes - Add preflight check for PSL assignments by [@davidmreed](https://github.com/davidmreed) in [#3616](https://github.com/SFDO-Tooling/CumulusCI/pull/3616) - Use Marketing Cloud's validate endpoint to update deployment packages by [@davidmreed](https://github.com/davidmreed) and [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3598](https://github.com/SFDO-Tooling/CumulusCI/pull/3598) @@ -478,7 +495,7 @@ ## What's Changed -### Changes +### Changes - Use Marketing Cloud's validate endpoint to update deployment packages by [@davidmreed](https://github.com/davidmreed) and [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3598](https://github.com/SFDO-Tooling/CumulusCI/pull/3598) @@ -490,7 +507,7 @@ ## What's Changed -### Changes +### Changes - Added opt-in Pydantic-based task option parsing. by [@prescod](https://github.com/prescod) in [#1618](https://github.com/SFDO-Tooling/CumulusCI/pull/1618) - Add deploy transform to inject org URLs by [@davidmreed](https://github.com/davidmreed) in [#3596](https://github.com/SFDO-Tooling/CumulusCI/pull/3596) @@ -503,7 +520,7 @@ ## What's Changed -### Issues Fixed +### Issues Fixed - Ensure that top-level 'tasks' directory is read for custom tasks by [@prescod](https://github.com/prescod) in [#3582](https://github.com/SFDO-Tooling/CumulusCI/pull/3582) @@ -515,7 +532,7 @@ ## What's Changed -### Changes +### Changes - Fix bug that prevented "api" declaration in `extract_declaration` from being respected during `capture_sample_dataset`. by [@prescod](https://github.com/prescod) in [#3568](https://github.com/SFDO-Tooling/CumulusCI/pull/3568) - Update windows install steps by [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3571](https://github.com/SFDO-Tooling/CumulusCI/pull/3571) @@ -530,13 +547,13 @@ ## What's Changed -### Changes +### Changes - Allow use of static release notes on GitHub by [@davidmreed](https://github.com/davidmreed) in [#3550](https://github.com/SFDO-Tooling/CumulusCI/pull/3550) - `cci service update` by [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3481](https://github.com/SFDO-Tooling/CumulusCI/pull/3481) - Add TimelineObjectDefinition metadata type by [@jstvz](https://github.com/jstvz) in [#3551](https://github.com/SFDO-Tooling/CumulusCI/pull/3551) -### Issues Fixed +### Issues Fixed - Fix an issue with `capture_sample_data` and record type capturing. by [@prescod](https://github.com/prescod) in [#3552](https://github.com/SFDO-Tooling/CumulusCI/pull/3552) @@ -550,7 +567,7 @@ No changes (other than dependency updates) since v3.72.1.dev2 . Please see the c ## What's Changed -### Changes +### Changes - Include `modelVersion` in MCPM Payload by [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3523](https://github.com/SFDO-Tooling/CumulusCI/pull/3523) - Fix MCPM deploy again by [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3526](https://github.com/SFDO-Tooling/CumulusCI/pull/3526) @@ -563,7 +580,7 @@ No changes (other than dependency updates) since v3.72.1.dev2 . Please see the c ## What's Changed -### Changes +### Changes - Include `modelVersion` in MCPM Payload by [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3523](https://github.com/SFDO-Tooling/CumulusCI/pull/3523) - Fix MCPM deploy again by [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3526](https://github.com/SFDO-Tooling/CumulusCI/pull/3526) @@ -574,7 +591,7 @@ No changes (other than dependency updates) since v3.72.1.dev2 . Please see the c ## What's Changed -### Changes +### Changes - Change `deploy_marketing_cloud_package` task to include `modelVersion` in MCPM Payload by [@TheBitShepherd](https://github.com/TheBitShepherd) in [#3523](https://github.com/SFDO-Tooling/CumulusCI/pull/3523) @@ -584,7 +601,7 @@ No changes (other than dependency updates) since v3.72.1.dev2 . Please see the c ## What's Changed -### Issues Fixed +### Issues Fixed - Fixed an issue preventing installation of CumulusCI's sdist in [#3520](https://github.com/SFDO-Tooling/CumulusCI/pull/3520) @@ -592,11 +609,11 @@ No changes (other than dependency updates) since v3.72.1.dev2 . Please see the c ## What's Changed -### Changes +### Changes - Improve documentation of tasks w.r.t required/option/defauled fields. by [@prescod](https://github.com/prescod) in [#3447](https://github.com/SFDO-Tooling/CumulusCI/pull/3447) -### Issues Fixed +### Issues Fixed - Ensure that products have a slug before publishing translations by [@prescod](https://github.com/prescod) in [#3483](https://github.com/SFDO-Tooling/CumulusCI/pull/3483) - Remove deprecated Playwright keywords by [@jstvz](https://github.com/jstvz) in [#3503](https://github.com/SFDO-Tooling/CumulusCI/pull/3503) @@ -606,11 +623,11 @@ No changes (other than dependency updates) since v3.72.1.dev2 . Please see the c ## 3.71.0 (2022-12-20) -Critical Changes +Critical Changes - A few weeks ago we soft-launched a `load_data` feature that matched the dataset loaded to the `org_shape`. If you had discovered and used the `load_data` option called `org_shape_match_only`, you should switch to the new task because eventually we will remove the option and only use the new `load_sample_data` task. (#3455) -Changes +Changes - CumulusCI has two new tasks for working with sample data: `load_sample_data` and `capture_sample_data`. (#3455) - CumulusCI now offers the ability to inject arbitrary IDs into a project's metadata components. See the [Find-and-Replace Id Injection](https://cumulusci.readthedocs.io/en/latest/deploy.html#find-and-replace-id-injection) source transform for more information. (#3460) @@ -623,7 +640,7 @@ Changes ## 3.69.0 (2022-11-14) -Changes +Changes - Added support for debugging and breakpoints in Playwright-based Robot Framework by @boakley in @@ -647,11 +664,11 @@ Changes ## 3.68.0 (2022-10-31) -Critical Changes +Critical Changes - Upgraded Robot Framework from version 4.1.3 to version 6. As with most Robot Framework updates, there are a host of new features and a few deprecated features and backwards incompatibilities. For a complete list consult the [Robot Framework release notes](https://github.com/robotframework/robotframework/releases) in https://github.com/SFDO-Tooling/CumulusCI/pull/3417 -Changes +Changes - Add support for InstallKey, sourceOrg, release keys on 2GP version create by @davidmreed in https://github.com/SFDO-Tooling/CumulusCI/pull/3403 - We now support the `Territory2`, `Territory2Model`, `Territory2Type`, and `Territory2Rule` MetaData types. by @TheBitShepherd in https://github.com/SFDO-Tooling/CumulusCI/pull/3406 @@ -661,7 +678,7 @@ Changes - Snowfakery (upgraded to 3.4) can now generate Event or Meeting Schedules similar to Calendar Apps - Snowfakery now has a Salesforce.ContentFile feature for generating Content Versions -Issues Fixed +Issues Fixed - Bumped key_size from 2048 to 4096 on advice from a security audit by @boakley in https://github.com/SFDO-Tooling/CumulusCI/pull/3389 - Fixed an issue where unknown deploy statuses could cause polling to hang in the deploy_marketing_cloud_package task by @TheBitShepherd in https://github.com/SFDO-Tooling/CumulusCI/pull/3394 @@ -698,7 +715,7 @@ Issues Fixed ## 3.66.0 (2022-09-29) -Changes +Changes - New Metadata ETL task `set_object_settings` to enable and disable settings on standard and custom objects (thanks \@jlantz) (#3364) - For Robot tests on the Firefox profile, we now accept all cookies to prevent lightning pages from failing to render due to cross-domain cookies. (#3366) @@ -707,7 +724,7 @@ Changes - CumulusCI now supports the following Metadata type: `AIApplicationConfig` (#3368) - CumulusCI now supports the following types from [Net Zero Cloud\'s Tooling API](https://developer.salesforce.com/docs/atlas.en-us.netzero_cloud_dev_guide.meta/netzero_cloud_dev_guide/netzero_cloud_tooling_api_parent.htm): `BldgEnrgyIntensityCnfg`, `StnryAssetEnvSrcCnfg`, `VehicleAssetEmssnSrcCnfg`. (#3372) -Issues Fixed +Issues Fixed - A failure when calling `capture page screenshot` no longer causes a Robot test to fail (#3366) - Fixed an issue where the `cci --version` command failed to output the current version (#3367) @@ -716,24 +733,24 @@ Issues Fixed ## 3.65.0 (2022-09-16) -Changes +Changes - Improve logging and add error handling for Vlocity tasks by \@prescod in (#3357) ## 3.64.0 (2022-08-18) -Changes +Changes - Support for upcoming Salesforce 240 Release in Robot by \@boakley (#3321) -Issues Fixed +Issues Fixed - Fix crash with unusual Unicode characters in metadata on Windows running `update_package_xml` by \@prescod (#3323) - Fix Scratch org creation in latest sfdx by \@prescod (#3334) ## 3.63.0 (2022-08-04) -Changes +Changes - CumulusCI can now validate MetaDeploy plans in cumulusci.yml by @jstvz in (#3298) - Sensitive service info is now masked in the `cci service info` command - by @bethbrains in (#3295) @@ -742,14 +759,14 @@ Changes - New task for deploying remote site settings that are required by OmniStudio - `deploy_omni_studio_site_settings` by @Br4nd0R in (#3303) - Added new robot keywords available when using the SalesforcePlaywright library; get current record id, wait until loading is complete and go to record home. These keywords work in a similar fashion to the existing keywords of the same name that are based on Selenium - by @boakley in (#3310) -Issues Fixed +Issues Fixed - Fixed two issues which prevented the `set_recently_viewed` feature from working by @prescod in (#3305) - The GithubIssuesParser class will now fall back if issues are disabled by @davidmreed in (#3293) ## 3.62.0 (2022-07-21) -Changes +Changes - CumulusCI now supports pinning dependencies on other projects by @davidmreed in (#3270) - Add extract declarations concept to CumulusCI by @prescod in (#3285) @@ -758,13 +775,13 @@ Changes ## 3.61.1 (2022-07-10) -Issues Fixed +Issues Fixed - Fix `metadeploy_publish` error caused by supported_orgs case-sensitivity (#3277) ## 3.61.0 (2022-07-09) -Changes +Changes - `metadeploy_publish` consumes legal targets for supported orgs (#3239) - Add update_profile support for record type layouts by (#3243) @@ -773,7 +790,7 @@ Changes - Import persistent orgs from the SFDX keychain (#3253) - Speed up Snowfakery handling of small batch sizes (#3188) -Issues Fixed +Issues Fixed - Fix JWT audience for sandboxes (#3240) - Fixed a bug where scratch org attributes configured via cumulusci.yml were @@ -1789,9 +1806,9 @@ Critical Changes: subfolders will see a change in resolution behavior. Previously, a dependency specified like this: - dependencies: - - github: https://github.com/SalesforceFoundation/NPSP - subfolder: unpackaged/config/trial + dependencies: + - github: https://github.com/SalesforceFoundation/NPSP + subfolder: unpackaged/config/trial would always deploy from the latest commit on the default branch. Now, this dependency will be resolved to a GitHub commit @@ -1802,12 +1819,12 @@ Critical Changes: - The `project__dependencies` section in `cumulusci.yml` no longer supports nested dependencies specified like this: - dependencies: - - namespace: "test" - version: "1.0" - dependencies: - - namespace: "parent" - version: "2.2" + dependencies: + - namespace: "test" + version: "1.0" + dependencies: + - namespace: "parent" + version: "2.2" All dependencies should be listed in install order. @@ -1976,12 +1993,12 @@ Critical changes: - The `project__dependencies` section in `cumulusci.yml` will no longer support nested dependencies specified like this : - dependencies: - - namespace: "test" - version: "1.0" dependencies: - - namespace: "parent" - version: "2.2" + - namespace: "test" + version: "1.0" + dependencies: + - namespace: "parent" + version: "2.2" All dependencies should be listed in install order. @@ -3588,33 +3605,33 @@ New features: : - - Added keywords for generating a collection of sObjects according to a template: + Added keywords for generating a collection of sObjects according to a template: - : - `Generate Test Data` - - `Salesforce Collection Insert` - - `Salesforce Collection Update` + : - `Generate Test Data` + - `Salesforce Collection Insert` + - `Salesforce Collection Update` - - + - - Changes to Page Objects: + Changes to Page Objects: - : - More than one page object can be loaded at once. - Once loaded, the keywords of a page object remain - visible in the suite. Robot will give priority to - keywords in the reverse order in which they were - imported. - - There is a new keyword, `Log Current Page Object`, - which can be useful to see information about the - most recently loaded page object. - - There is a new keyword, `Get Page Object`, which - will return the robot library for a given page - object. This can be used in other keywords to access - keywords from another page object if necessary. - - The `Go To Page` keyword will now automatically load - the page object for the given page. + : - More than one page object can be loaded at once. + Once loaded, the keywords of a page object remain + visible in the suite. Robot will give priority to + keywords in the reverse order in which they were + imported. + - There is a new keyword, `Log Current Page Object`, + which can be useful to see information about the + most recently loaded page object. + - There is a new keyword, `Get Page Object`, which + will return the robot library for a given page + object. This can be used in other keywords to access + keywords from another page object if necessary. + - The `Go To Page` keyword will now automatically load + the page object for the given page. - - Added a basic debugger for Robot tests. It can be enabled - using the `-o debug True` option to the robot task. + - Added a basic debugger for Robot tests. It can be enabled + using the `-o debug True` option to the robot task. - Added support for deploying new metadata types `ProfilePasswordPolicy` and `ProfileSessionSetting`. @@ -3689,8 +3706,8 @@ New features: permanently set this option, add this in `~/.cumulusci/cumulusci.yml`: - cli: - plain_output: True + cli: + plain_output: True - Added additional info to the `cci version` command, including the Python version, an upgrade check, and a warning on Python 2. @@ -4971,12 +4988,12 @@ Resolving a few issues from beta77: below. In flows that need to inject the actual namespace prefix, override the [unmanaged]{.title-ref} option .. : - custom_deploy_task: - class_path: cumulusci.tasks.salesforce.Deploy - options: - path: your/custom/metadata - namespace_inject: $project_config.project__package__namespace - unmanaged: False + custom_deploy_task: + class_path: cumulusci.tasks.salesforce.Deploy + options: + path: your/custom/metadata + namespace_inject: $project_config.project__package__namespace + unmanaged: False ### Enhancements @@ -5691,13 +5708,13 @@ Resolving a few issues from beta77: - **IMPORANT** This release changes the yaml structure for flows. The new structure now looks like this: - flows: - flow_name: - tasks: - 1: - task: deploy - 2: - task: run_tests + flows: + flow_name: + tasks: + 1: + task: deploy + 2: + task: run_tests - See the new flow customization examples in the cookbook for examples of why this change was made and how to use it: @@ -6107,4 +6124,3 @@ Resolving a few issues from beta77: ## 2.0.0-alpha1 (2016-10-21) - First release on PyPI. - From 0b9160c58b09977a4311e30b2850d9129d54e9e9 Mon Sep 17 00:00:00 2001 From: Bharath Chadarajupalli Date: Mon, 2 Jun 2025 13:25:22 -0700 Subject: [PATCH 2/4] Add output_dir option to retrieve_changes task (#3901) Added output_dir option to specify a custom output directory for retrieved changes Updated retrieve_components function to handle the output_dir parameter Modified error handling to provide clearer messages when no results are found Updated test cases to verify the output_dir functionality --- cumulusci/tasks/salesforce/sourcetracking.py | 22 ++++++- .../salesforce/tests/test_sourcetracking.py | 63 +++++++++++++++++-- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/cumulusci/tasks/salesforce/sourcetracking.py b/cumulusci/tasks/salesforce/sourcetracking.py index 27567ddb20..f58a52e651 100644 --- a/cumulusci/tasks/salesforce/sourcetracking.py +++ b/cumulusci/tasks/salesforce/sourcetracking.py @@ -179,6 +179,14 @@ def _reset_sfdx_snapshot(self): "namespace_tokenize" ] +retrieve_changes_task_options["output_dir"] = { + "description": ( + "The output directory for the retrieved metadata. " + + "If not specified, defaults to force-app or the target directory passed to retrieve changes." + ), + "required": False, +} + def _write_manifest(changes, path, api_version): """Write a package.xml for the specified changes and API version.""" @@ -226,6 +234,7 @@ def retrieve_components( project_config: BaseProjectConfig = None, retrieve_complete_profile: bool = False, capture_output: bool = False, + output_dir: str = None, ): """Retrieve specified components from an org into a target folder. @@ -238,7 +247,10 @@ def retrieve_components( to a namespace prefix to replace it with a `%%%NAMESPACE%%%` token. """ - target = os.path.realpath(target) + # Always use output_dir if specified, else use target + retrieve_target = ( + os.path.realpath(output_dir) if output_dir else os.path.realpath(target) + ) profiles = [] # If retrieve_complete_profile and project_config is None, raise error # This is because project_config is only required if retrieve_complete_profile is True @@ -302,6 +314,8 @@ def retrieve_components( "-w", "5", "--ignore-conflicts", + "--output-dir", + retrieve_target, ], capture_output=capture_output, check_return=True, @@ -364,6 +378,9 @@ def _init_options(self, kwargs): self.options.get("retrieve_complete_profile", False) ) + # Get output_dir first + output_dir = self.options.get("output_dir") + # Check which directories are configured as dx packages package_directories = [] default_package_directory = None @@ -392,6 +409,7 @@ def _init_options(self, kwargs): md_format = path not in package_directories self.md_format = md_format self.options["path"] = path + self.options["output_dir"] = output_dir if "api_version" not in self.options: self.options[ @@ -410,6 +428,7 @@ def _run_task(self): self.logger.info("{MemberType}: {MemberName}".format(**change)) target = os.path.realpath(self.options["path"]) + output_dir = self.options.get("output_dir") package_xml_opts = {} if self.options["path"] == "src": package_xml_opts.update( @@ -430,6 +449,7 @@ def _run_task(self): extra_package_xml_opts=package_xml_opts, project_config=self.project_config, retrieve_complete_profile=self.options["retrieve_complete_profile"], + output_dir=output_dir, ) if self.options["snapshot"]: diff --git a/cumulusci/tasks/salesforce/tests/test_sourcetracking.py b/cumulusci/tasks/salesforce/tests/test_sourcetracking.py index 258d1a1e32..206b344970 100644 --- a/cumulusci/tasks/salesforce/tests/test_sourcetracking.py +++ b/cumulusci/tasks/salesforce/tests/test_sourcetracking.py @@ -20,6 +20,11 @@ from cumulusci.utils import temporary_dir +@pytest.fixture +def vcr_cassette_dir(): + return os.path.join(os.path.dirname(__file__), "cassettes") + + class TestListChanges: """List the changes from a scratch org""" @@ -180,12 +185,12 @@ def test_run_task(self, sfdx, create_task_fixture): }, ], } - with mock.patch.object( - RetrieveProfile, "_run_task" - ) as mock_retrieve_profile, mock.patch.object( - pathlib.Path, "exists", return_value=True - ), mock.patch.object( - pathlib.Path, "is_dir", return_value=True + with ( + mock.patch.object( + RetrieveProfile, "_run_task" + ) as mock_retrieve_profile, + mock.patch.object(pathlib.Path, "exists", return_value=True), + mock.patch.object(pathlib.Path, "is_dir", return_value=True), ): task._run_task() assert sfdx_calls == [ @@ -208,6 +213,52 @@ def test_run_task__no_changes(self, sfdx, create_task_fixture): task._run_task() assert "No changes to retrieve" in messages + def test_run_task_with_output_dir(self, sfdx, create_task_fixture): + sfdx_calls = [] + sfdx.side_effect = lambda cmd, *args, **kw: sfdx_calls.append(cmd) + + with temporary_dir(): + task = create_task_fixture( + RetrieveChanges, + { + "include": "Test", + "namespace_tokenize": "ns", + "retrieve_complete_profile": True, + "output_dir": "output", + }, + ) + task._init_task() + task.tooling = mock.Mock() + task.tooling.query_all.return_value = { + "totalSize": 1, + "records": [ + { + "MemberType": "CustomObject", + "MemberName": "Test__c", + "RevisionCounter": 1, + }, + { + "MemberType": "Profile", + "MemberName": "TestProfile", + "RevisionCounter": 1, + }, + ], + } + with ( + mock.patch.object( + RetrieveProfile, "_run_task" + ) as mock_retrieve_profile, + mock.patch.object(pathlib.Path, "exists", return_value=True), + mock.patch.object(pathlib.Path, "is_dir", return_value=True), + ): + task._run_task() + assert sfdx_calls == [ + "project convert mdapi", + "project retrieve start", + "project convert source", + ] + mock_retrieve_profile.assert_called() + class TestSnapshotChanges: @mock.patch("cumulusci.tasks.salesforce.sourcetracking.sfdx") From ec52411914b4131d3217bc74406ec7270f7fa65e Mon Sep 17 00:00:00 2001 From: Jorge Soler Date: Fri, 20 Jun 2025 10:18:16 +0800 Subject: [PATCH 3/4] fixing calculation of maanged context for multi packages with same namespace --- cumulusci/core/config/org_config.py | 14 +++++- cumulusci/core/utils.py | 33 +++++++++++++ cumulusci/tasks/apex/anon.py | 11 ++--- cumulusci/tasks/apex/testrunner.py | 12 ++--- cumulusci/tasks/metadata_etl/base.py | 13 ++---- cumulusci/tasks/salesforce/Deploy.py | 8 ++-- cumulusci/tasks/salesforce/composite.py | 11 ++--- .../tasks/salesforce/custom_settings_wait.py | 11 ++--- .../tasks/salesforce/enable_prediction.py | 11 ++--- .../tests/test_ProfileGrantAllAccess.py | 46 ++++++++++++++++++- 10 files changed, 119 insertions(+), 51 deletions(-) diff --git a/cumulusci/core/config/org_config.py b/cumulusci/core/config/org_config.py index e179fbbe3b..75e6887611 100644 --- a/cumulusci/core/config/org_config.py +++ b/cumulusci/core/config/org_config.py @@ -318,10 +318,16 @@ def has_minimum_package_version(self, package_identifier, version_identifier): @property def installed_packages(self): - """installed_packages is a dict mapping a namespace or package Id (033*) to the installed package + """installed_packages is a dict mapping a namespace, package name, or package Id (033*) to the installed package version(s) matching that identifier. All values are lists, because multiple second-generation packages may be installed with the same namespace. + Keys include: + - namespace: "mycompany" + - package name: "My Package Name" + - namespace@version: "mycompany@1.2.3" + - package ID: "033ABCDEF123456" + To check if a required package is present, call `has_minimum_package_version()` with either the namespace or 033 Id of the desired package and its version, in 1.2.3 format. @@ -329,7 +335,7 @@ def installed_packages(self): """ if self._installed_packages is None: isp_result = self.salesforce_client.restful( - "tooling/query/?q=SELECT SubscriberPackage.Id, SubscriberPackage.NamespacePrefix, " + "tooling/query/?q=SELECT SubscriberPackage.Id, SubscriberPackage.Name, SubscriberPackage.NamespacePrefix, " "SubscriberPackageVersionId FROM InstalledSubscriberPackage" ) _installed_packages = defaultdict(list) @@ -357,10 +363,14 @@ def installed_packages(self): version += f"b{spv['BuildNumber']}" version_info = VersionInfo(spv["Id"], StrictVersion(version)) namespace = sp["NamespacePrefix"] + package_name = sp["Name"] _installed_packages[namespace].append(version_info) namespace_version = f"{namespace}@{version}" _installed_packages[namespace_version].append(version_info) _installed_packages[sp["Id"]].append(version_info) + # Add package name as a key for specific package detection + if package_name: + _installed_packages[package_name].append(version_info) self._installed_packages = _installed_packages return self._installed_packages diff --git a/cumulusci/core/utils.py b/cumulusci/core/utils.py index 88cd570657..5e2a0b3a71 100644 --- a/cumulusci/core/utils.py +++ b/cumulusci/core/utils.py @@ -362,3 +362,36 @@ def make_jsonable(x): return x except (TypeError, OverflowError): return str(x) + + +def determine_managed_mode(options, project_config, org_config): + """Determine the managed mode based on options, project config, and org config. + + Args: + options: Dict of task options that may contain 'managed' or 'unmanaged' flags + project_config: Project configuration object with package info + org_config: Org configuration object with installed packages and namespace info + + Returns: + bool: True if in managed mode, False if in unmanaged mode + """ + if "managed" in options: + return process_bool_arg(options["managed"]) + + # Get package and namespace information + package_name = getattr(project_config, 'project__package__name', None) + namespace = getattr(project_config, 'project__package__namespace', None) + installed_packages = getattr(org_config, 'installed_packages', {}) + + if "unmanaged" in options: + # Explicit unmanaged flag always takes precedence + return not process_bool_arg(options.get("unmanaged", True)) + elif package_name and any(package_name in key for key in installed_packages.keys()): + # If this specific package is installed (or there is any installed package with a Name that contains package_name), we're in managed context + return True + elif bool(namespace) and namespace == getattr(org_config, 'namespace', None): + # We're in a namespaced org (packaging org) developing unmanaged code + return False + else: + # Fall back to checking namespace in installed packages + return bool(namespace) and namespace in installed_packages diff --git a/cumulusci/tasks/apex/anon.py b/cumulusci/tasks/apex/anon.py index 56bea2a4c4..378f91ce28 100644 --- a/cumulusci/tasks/apex/anon.py +++ b/cumulusci/tasks/apex/anon.py @@ -4,7 +4,7 @@ SalesforceException, TaskOptionsError, ) -from cumulusci.core.utils import process_bool_arg +from cumulusci.core.utils import process_bool_arg, determine_managed_mode from cumulusci.tasks.salesforce import BaseSalesforceApiTask from cumulusci.utils import in_directory, inject_namespace from cumulusci.utils.http.requests_utils import safe_json_from_response @@ -107,12 +107,9 @@ def _process_apex_string(self, apex_string): def _prepare_apex(self, apex): # Process namespace tokens namespace = self.project_config.project__package__namespace - if "managed" in self.options: - managed = process_bool_arg(self.options["managed"]) - else: - managed = ( - bool(namespace) and namespace in self.org_config.installed_packages - ) + managed = determine_managed_mode( + self.options, self.project_config, self.org_config + ) if "namespaced" in self.options: namespaced = process_bool_arg(self.options["namespaced"]) else: diff --git a/cumulusci/tasks/apex/testrunner.py b/cumulusci/tasks/apex/testrunner.py index 5a51f655ed..d594370347 100644 --- a/cumulusci/tasks/apex/testrunner.py +++ b/cumulusci/tasks/apex/testrunner.py @@ -10,7 +10,7 @@ CumulusCIException, TaskOptionsError, ) -from cumulusci.core.utils import decode_to_unicode, process_bool_arg, process_list_arg +from cumulusci.core.utils import decode_to_unicode, process_bool_arg, process_list_arg, determine_managed_mode from cumulusci.tasks.salesforce import BaseSalesforceApiTask from cumulusci.utils.http.requests_utils import safe_json_from_response @@ -609,13 +609,9 @@ def _enqueue_test_run(self, class_ids): def _init_task(self): super()._init_task() - if "managed" in self.options: - self.options["managed"] = process_bool_arg(self.options["managed"] or False) - else: - namespace = self.options.get("namespace") - self.options["managed"] = ( - bool(namespace) and namespace in self.org_config.installed_packages - ) + self.options["managed"] = determine_managed_mode( + self.options, self.project_config, self.org_config + ) def _run_task(self): result = self._get_test_classes() diff --git a/cumulusci/tasks/metadata_etl/base.py b/cumulusci/tasks/metadata_etl/base.py index d7e9dbd849..d11cdf0d91 100644 --- a/cumulusci/tasks/metadata_etl/base.py +++ b/cumulusci/tasks/metadata_etl/base.py @@ -7,7 +7,7 @@ from cumulusci.core.enums import StrEnum from cumulusci.core.exceptions import CumulusCIException, TaskOptionsError from cumulusci.core.tasks import BaseSalesforceTask -from cumulusci.core.utils import process_bool_arg, process_list_arg +from cumulusci.core.utils import process_bool_arg, process_list_arg, determine_managed_mode from cumulusci.salesforce_api.metadata import ApiRetrieveUnpackaged from cumulusci.tasks.metadata.package import PackageXmlGenerator from cumulusci.utils import inject_namespace @@ -66,19 +66,16 @@ def _init_namespace_injection(self): self.options.get("namespace_inject") or self.project_config.project__package__namespace ) - if "managed" in self.options: - self.options["managed"] = process_bool_arg(self.options["managed"] or False) - else: - self.options["managed"] = ( - bool(namespace) and namespace in self.org_config.installed_packages - ) + self.options["managed"] = determine_managed_mode( + self.options, self.project_config, self.org_config + ) if "namespaced_org" in self.options: self.options["namespaced_org"] = process_bool_arg( self.options["namespaced_org"] or False ) else: self.options["namespaced_org"] = ( - bool(namespace) and namespace == self.org_config.namespace + bool(namespace) and namespace == getattr(self.org_config, 'namespace', None) ) def _inject_namespace(self, text): diff --git a/cumulusci/tasks/salesforce/Deploy.py b/cumulusci/tasks/salesforce/Deploy.py index 66a5851b80..196204715e 100644 --- a/cumulusci/tasks/salesforce/Deploy.py +++ b/cumulusci/tasks/salesforce/Deploy.py @@ -12,7 +12,7 @@ SourceTransform, SourceTransformList, ) -from cumulusci.core.utils import process_bool_arg, process_list_arg +from cumulusci.core.utils import process_bool_arg, process_list_arg, determine_managed_mode from cumulusci.salesforce_api.metadata import ApiDeploy, ApiRetrieveUnpackaged from cumulusci.salesforce_api.package_zip import MetadataPackageZipBuilder from cumulusci.salesforce_api.rest_deploy import RestDeploy @@ -154,9 +154,9 @@ def _get_api(self, path=None): ) def _has_namespaced_package(self, ns: Optional[str]) -> bool: - if "unmanaged" in self.options: - return not process_bool_arg(self.options.get("unmanaged", True)) - return bool(ns) and ns in self.org_config.installed_packages + return determine_managed_mode( + self.options, self.project_config, self.org_config + ) def _is_namespaced_org(self, ns: Optional[str]) -> bool: if "namespaced_org" in self.options: diff --git a/cumulusci/tasks/salesforce/composite.py b/cumulusci/tasks/salesforce/composite.py index cd83202221..2634faa2a0 100644 --- a/cumulusci/tasks/salesforce/composite.py +++ b/cumulusci/tasks/salesforce/composite.py @@ -6,7 +6,7 @@ from cumulusci.cli.ui import CliTable from cumulusci.core.exceptions import SalesforceException -from cumulusci.core.utils import process_bool_arg, process_list_arg +from cumulusci.core.utils import process_bool_arg, process_list_arg, determine_managed_mode from cumulusci.tasks.salesforce import BaseSalesforceApiTask from cumulusci.utils import inject_namespace @@ -83,12 +83,9 @@ def _process_json(self, body): body = body.replace("%%%USERID%%%", user_id) namespace = self.project_config.project__package__namespace - if "managed" in self.options: - managed = process_bool_arg(self.options["managed"]) - else: - managed = ( - bool(namespace) and namespace in self.org_config.installed_packages - ) + managed = determine_managed_mode( + self.options, self.project_config, self.org_config + ) _, body = inject_namespace( "composite", diff --git a/cumulusci/tasks/salesforce/custom_settings_wait.py b/cumulusci/tasks/salesforce/custom_settings_wait.py index 77432d5517..d47aa0cd3f 100644 --- a/cumulusci/tasks/salesforce/custom_settings_wait.py +++ b/cumulusci/tasks/salesforce/custom_settings_wait.py @@ -3,7 +3,7 @@ from simple_salesforce.exceptions import SalesforceError from cumulusci.core.exceptions import TaskOptionsError -from cumulusci.core.utils import process_bool_arg +from cumulusci.core.utils import process_bool_arg, determine_managed_mode from cumulusci.tasks.salesforce import BaseSalesforceApiTask @@ -93,12 +93,9 @@ def _poll_again(self): def _apply_namespace(self): # Process namespace tokens namespace = self.project_config.project__package__namespace - if "managed" in self.options: - managed = process_bool_arg(self.options["managed"]) - else: - managed = ( - bool(namespace) and namespace in self.org_config.installed_packages - ) + managed = determine_managed_mode( + self.options, self.project_config, self.org_config + ) if "namespaced" in self.options: namespaced = process_bool_arg(self.options["namespaced"]) else: diff --git a/cumulusci/tasks/salesforce/enable_prediction.py b/cumulusci/tasks/salesforce/enable_prediction.py index bc99463e30..8a8d3f41b2 100644 --- a/cumulusci/tasks/salesforce/enable_prediction.py +++ b/cumulusci/tasks/salesforce/enable_prediction.py @@ -1,7 +1,7 @@ from simple_salesforce.exceptions import SalesforceError from cumulusci.core.exceptions import CumulusCIException -from cumulusci.core.utils import process_bool_arg, process_list_arg +from cumulusci.core.utils import process_bool_arg, process_list_arg, determine_managed_mode from cumulusci.tasks.salesforce import BaseSalesforceApiTask from cumulusci.utils import inject_namespace from cumulusci.utils.http.requests_utils import safe_json_from_response @@ -37,12 +37,9 @@ def _init_namespace_injection(self): or self.project_config.project__package__namespace ) self.options["namespace_inject"] = namespace - if "managed" in self.options: - self.options["managed"] = process_bool_arg(self.options["managed"] or False) - else: - self.options["managed"] = ( - bool(namespace) and namespace in self.org_config.installed_packages - ) + self.options["managed"] = determine_managed_mode( + self.options, self.project_config, self.org_config + ) if "namespaced_org" in self.options: self.options["namespaced_org"] = process_bool_arg( self.options["namespaced_org"] or False diff --git a/cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py b/cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py index efd3e76977..aff43dcf3a 100644 --- a/cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py +++ b/cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py @@ -591,7 +591,51 @@ def test_init_options__namespace_injection(): ) assert task.options["namespace_inject"] == "ns" assert task.options["namespaced_org"] - assert task.options["managed"] + assert not task.options["managed"] # Fixed: namespaced org should be unmanaged + + +def test_init_options__managed_explicit_unmanaged_flag(): + """Test that explicit unmanaged=True forces managed=False even with installed packages.""" + pc = create_project_config(namespace="ns") + org_config = DummyOrgConfig({"namespace": "other"}) + org_config._installed_packages = {"ns": None} # Package is installed + task = create_task( + ProfileGrantAllAccess, {"unmanaged": True}, project_config=pc, org_config=org_config + ) + assert not task.options["managed"] # Should be False due to explicit unmanaged=True + + +def test_init_options__managed_explicit_unmanaged_false(): + """Test that explicit unmanaged=False forces managed=True.""" + pc = create_project_config(namespace="ns") + org_config = DummyOrgConfig({"namespace": "other"}) + org_config._installed_packages = {} # No packages installed + task = create_task( + ProfileGrantAllAccess, {"unmanaged": False}, project_config=pc, org_config=org_config + ) + assert task.options["managed"] # Should be True due to explicit unmanaged=False + + +def test_init_options__managed_fallback_to_installed_packages(): + """Test that we fall back to installed packages check when not in namespaced org.""" + pc = create_project_config(namespace="ns") + org_config = DummyOrgConfig({"namespace": "different"}) # Different namespace + org_config._installed_packages = {"ns": None} # But package is installed + task = create_task( + ProfileGrantAllAccess, {}, project_config=pc, org_config=org_config + ) + assert task.options["managed"] # Should be True due to installed package + + +def test_init_options__managed_no_installed_package(): + """Test that managed=False when package is not installed and not in namespaced org.""" + pc = create_project_config(namespace="ns") + org_config = DummyOrgConfig({"namespace": "different"}) + org_config._installed_packages = {} # No packages installed + task = create_task( + ProfileGrantAllAccess, {}, project_config=pc, org_config=org_config + ) + assert not task.options["managed"] # Should be False - no package installed def test_generate_package_xml__retrieve(): From 9cd9cc6bcc8d4ef914f5be70772f2bcfaf5debc9 Mon Sep 17 00:00:00 2001 From: Jorge Soler Date: Fri, 20 Jun 2025 20:39:48 +0800 Subject: [PATCH 4/4] fixing __NAMESPACE_ORG__ issue with package xml --- cumulusci/utils/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cumulusci/utils/__init__.py b/cumulusci/utils/__init__.py index 2d740c40cb..b3a987e2d7 100644 --- a/cumulusci/utils/__init__.py +++ b/cumulusci/utils/__init__.py @@ -263,6 +263,14 @@ def inject_namespace( logger.info( f' {name}: Replaced {filename_token} with "{namespace_prefix}"' ) + + # Also replace ___NAMESPACED_ORG___ tokens in package.xml + prev_content = content + content = content.replace(namespaced_org_file_token, namespaced_org) + if logger and content != prev_content: + logger.info( + f' {name}: Replaced {namespaced_org_file_token} with "{namespaced_org}"' + ) prev_content = content content = content.replace(namespaced_org_token, namespaced_org)