I'm wondering what the best way to use CumulusCI is to deploy changes that managed package upgrades usually skip. The common problem areas are:

  • Layouts
  • Flexipages
  • Picklist values

We package daily and there is a lot of change at present.

My first thought is to have a folder containing a copy of the changed metadata for each version:




with older versions discarded after a few weeks. (Though automating the checkout of each version from Git and only varying which metadata files are deployed could be a better approach.)

So to go from 2.159 to 2.162 all 3 of the above would be deployed whereas to go from 2.161 to 2.162 only the last one would need to be deployed.

But from a scan over the CumulusCI documentation and Trailheads I don't think this pattern fits easily? Brute force might be:

          path: upgrades/v2.163
        task: deploy

          path: upgrades/v2.164
        task: deploy

          path: upgrades/v2.165
        task: deploy

What is the best way to do this sort of incremental upgrading from version to version?

(Having a way to signal that there is a local change that would be lost would also be useful.)


I'm now thinking this is probably better handled in GitHub Actions where I want to checkout a tag or hash and then for that tag or hash run a series of sfdx force:source:deploy -p filepath ideally taken from e.g. a JSON file.

  • Are you trying to deploy in orgs whose state you completely control (i.e., no possibility of admin changes between versions) or in orgs that might be further customized/owned by a customer?
    – David Reed
    Mar 13, 2023 at 15:55
  • Hi @DavidReed, Our internal orgs are in the first category, as are most of our current customers at the moment. But yes, some "locally modified" warning will be needed eventually.
    – Keith C
    Mar 13, 2023 at 16:03
  • ... Tooling API calls like select masterlabel, description, createddate, lastmodifieddate from flexipage might help spot the local modifications.
    – Keith C
    Mar 13, 2023 at 16:05

2 Answers 2


This is fundamentally a Hard Problem, or rather two hard problems. CumulusCI can support you in implementing solutions to those hard problems, but it won't abstract them away.

Problem 1: Upgrading from any version N to any version M

I am not aware of a better solution to this problem than the one you've shared, where you actually store and selectively deploy each version's resources.

The "fix" if there is one is to keep your support window very narrow. Ideally, if you can only support your latest version, use push upgrades, and perform deployments only against the latest version for anything not push-upgradeable, your overhead stays fairly minimal.

Problem 2: Safe upgrades against intermediate modification

Even harder is this challenge. Given a customer with a journey like this:

|    Acquire product @ 1.0
|    Edit page layout Foo
|    Edit lightning page Bar
|    ...
|    Upgrade managed package to version 2.0
|    ... upgrade assets to 2.0?

There's really no way to do a safe three-way merge between the non-push-upgradeable assets of package version 2.0 and the customer-modified components existing in their org. You could try with an actual three-way merge algorithm on the XML metadata, but there's no guarantee that the output would be valid or sensical. It needs to be a semantic merge.

There is a strategy that CumulusCI offers to sidestep this problem: Metadata ETL. Metadata ETL allows you to store fine-grained modifications to metadata, instead of a copy of the metadata. So from version 1.0 to 2.0, for example, you can facilitate an upgrade by saying "Add this button to this named layout", or "Add this value to this existing picklist". CumulusCI then extracts the customer-modified component, performs only the surgical change specified, and re-deploys it into the org.

Metadata ETL can unlock capabilities that are otherwise impossible for safely updating existing orgs, but it's not a silver bullet. You'll still have to invest effort writing series of transformations to deliver enablement/setup automation to your existing customers. And the framework covers a number of common areas, but far from everything you might want to change in your metadata.

A lighter-weight solution might be to simply warn the customer that you're about to overwrite their changes, and insist they do the upgrade in a sandbox and then manually reconcile. It's not a great customer experience, but if you're making it opt-in and providing value with the upgrade, some customers may take you up on it.

I have that type of collision detection on the roadmap for our MetaDeploy delivery platform (Safe HarborTM) and it will likely get built this year, but I cannot make any specific promises.

  • Thank-you David - very helpful as usual. We are at a fairly early stage with this product so can make do with the "overwrite" approach. The change merging isn't simple, so feels like something that someone should take on for the benefit of the community; +1 for the collision detection feature.
    – Keith C
    Mar 16, 2023 at 7:50

I've written a GitHub custom action that consumes one or more JSON files that identify the metadata files to deploy for a product version. Sufficient for my needs.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .