In the Microsoft Power Platform, there is a concept of patching solutions. Patches are useful when you want to deploy code from one environment to another. With patches, you would have already released a solution from one environment to another, and then be in a situation where you need to deploy a fix or enhancement to that solution. Instead of updating the original solution and deploying that full solution again, the concept of patches was introduced to enable us to deploy only what has changed. We could create a new small solution with only the code we need to deploy without creating a patch, but the nice feature of patches is they are tracked back to the original solution, so we can ultimately roll these changes back into the base solution.
Patches are also layered on top of the original solution, which is important in terms of predictability of code deployments. This is especially handy if you are creating an app or ISV code, or are keeping a close eye on what is deployed in your production orgs. Patches should be faster to deploy as you are only deploying part of a solution, and individual developers can deploy patches instead of waiting for other devs to complete functionality.
Let’s take a look at how patching works.
In this post, we will:
- Export a managed solution 22.214.171.124 from Source
- Import the managed solution 126.96.36.199 into the Target
- Update source and export managed solution 188.8.131.52
- Import managed solution 184.108.40.206 into the Target
- Create managed solution patch 220.127.116.11
- Update the source org and export 18.104.22.168
- Deploy patch 22.214.171.124 into to target
- Create patch 126.96.36.199
- Import 188.8.131.52 into target
- Patch 184.108.40.206
- Roll back a patch
- Clone solution
Before we start, Dynamics 365 / Power Apps / Power Platform solution versions are in the format <major>.<minor>.<build>.<revision>. You can read more about the format in my blog post on how solution version numbers work, but for now, we just need to know the main structure.
To understand patching and upgrades, we need to understand Solution Layering in the Power Platform.
Each solution in the Power Platform sits in a layer. Let’s look at an example. If we create a solution in our target org, and add the Contact entity, we can select the entity and see the solution layers by selecting See Solution Layers:
We see the order of each later, starting with the System layer at number 1. Then each solution has a layer number, and at the top we have the active layer, in this case at number 18:
If we look at an entity such as Action Calls, which is part of the Unified Service Desk solution, we see there is only one layer, i.e. it is not used by other solutions:
We will look at what happens when a patch and solution is deployed further along in this post.
Export Managed Solution 220.127.116.11 from Source
In our source environment, we have a solution and some code. The version number of the solution after creating it is set to 18.104.22.168. The solution contains:
- The Contact entity, with all the assets added. Note in the real world, you should add only the components you need
Let’s start with a simple export/import. We will export the solution as a managed solution:
On exporting, the solution version is set to 22.214.171.124. I.e. the revision number has been incremented. We can change this number if we want, but it makes sense to keep this:
Import 126.96.36.199 into Target
Now let’s import this managed solution into a new environment. We see the solution has been imported, and the solution tells us we cannot make changes to it as it is managed:
If we look at the solution layers for the Contact, we can see it has been added as a layer right at the top:
Update Source and Export 188.8.131.52
Now, let’s make an update to the solution in our source org. In this case, we are making a change to the solution directly, instead of using patches which we will discuss shortly. In some cases, we may not want to make these changes directly, e.g. if there are multiple developers that don’t have their code ready, but one developer does. Let’s assume that it’s ok to update this solution directly here, to see how this works.
We will change the text in the file carl_Contact.js file, and we will also change the First Name field from the default 50 characters to 100 characters:
On exporting, the revision number of the solution is incremented to 184.108.40.206.
Note we are exporting the original solution with all its assets.
Import 220.127.116.11 into Target
On importing into the target environment, our version will be increased to 18.104.22.168:
And we are prompted to:
- Upgrade (recommended). This option upgrades your solution to the latest version and rolls up all previous patches in one step. Any components associated to the previous solution version that are not in the newer solution version will be deleted.
- Stage for Upgrade. This option upgrades your solution to the higher version, but defers the deletion of the previous version and any related patches until you apply a solution upgrade later.
- Update (not recommended). This option replaces your solution with this version. Components that are not in the newer solution will not be deleted and will remain in the system.
And scrolling down, we see:
- Maintain customizations (recommended). This option maintains any unmanaged customizations performed on components, but also implies that some of the updates included in this solution will not take effect.
- Overwrite customizations (not recommended). This option overwrites or removes any unmanaged customizations previously performed on components in this solution. This option does not affect components that support merge behavior (forms, sitemap, ribbon, app modules). Components that have other managed solutions on top of the existing solution you are replacing do also still remain on top and are not affected by this option
Let’s keep the recommended defaults and select Import. We see there are 2 versions of the solution now imported – 22.214.171.124 and 126.96.36.199:
And after refreshing, we see only the one latest Contact Enhancements solution with version 188.8.131.52:
If we check the Solution History, we can see after version 184.108.40.206 was installed, there was an automatic uninstall of solution 220.127.116.11:
If we were to check our updated carl_Contact.js file, we would see the updated file. The first name has increased to max length of 100:
The solution layers for Contact still look like below:
The reason the import removed the previous version, is because we chose option 1 to upgrade, which “upgrades your solution to the latest version and rolls up all previous patches in one step”.
Create Patch Solution 18.104.22.168
Let’s now create a patch. Let’s say we need to change the first name length from 100 now to 120. First thing we will do is create the patch.
Select the solution, then Clone->Clone a patch:
We see the base solution name, which we can overwrite to something more meaningful such as Contact Enhanccements – FirstName 120, and it says “create a patch for the selected unmanaged solution. A patch contains changes to the existing solution”. The version number is automatically incremented to 22.214.171.124. Note the build number has incremented here:
We see the patch solution created:
If we were to look at the metadata for these 2 solutions, we would see the Solution Id is the same. Opening the patch solution, there are no components:
Let’s add our entity into the solution:
Select the First Name field:
Increase the First Name field to 120 characters:
And let’s add some fields to the Contact entity and see how these are handled. We will add 2 fields:
We will add these fields to the Contact form:
Let’s update the Web Resource so we can confirm it worked:
Export Patch 126.96.36.199
Export the solution (exporting the solution automatically increments the last digit, so you could have an incremented version number if you don’t change it):
Deploy Patch 188.8.131.52 to Target
Now let’s deploy the patch to the target environment:
Now in the target, we see:
Let’s update a Contact record by populating the new fields:
Create Patch 184.108.40.206
Note. if we went into the parent solution now in the source org, we would not be able to edit it. We get the message “You cannot directly edit the components within a parent solution. If customization is enabled, you may do so through the patches“:
Let’s create a new patch, this time to increase the first name field size again, and to add a 3rd field. First, we will create the patch by selecting the original solution and choose Clone->Clone a patch. The patch version is 220.127.116.11:
We will increase the First Name field size to 150:
We will add a 3rd field, New Field 3.
Export the patch:
Import 18.104.22.168 into Target
Let’s import the 22.214.171.124 patch into the target. We now have 3 solutions – 1 parent solution and 2 patches:
And we have 3 fields in the Contact entity:
At this point, the Contact First Name field is 150 characters:
The solution layers look like below, where each patch has created its own layer on top of the Contact Enhancements layer:
Adding another Solution and Layer
Now let’s say we import a new managed solution completely separate from the above solutions. Our solution is imported from another org and is called Awesome Contacts. It contains the Contact entity with the First Name, of max length 200 now in the target:
Let’s create another patch from our original solution:
With the First Name = 250 characters:
And import it into our target org.
After importing, we see the field length of First Name is not 250, but 200:
This is because the patch is inserted between the new Awesome Contacts solution and the Contact Enhancements solution, i.e. it sits above the Contact Enhancements layer, so the newer Awesome Contacts has the “winning” field length:
Here we can see that patching is giving us some level of predictability in terms of what will happen when managed solutions and patches are imported.
Rolling Back a Patch
What’s nice about patches is they are easy to roll back.
Let’s say in our target org we don’t want the Awesome Contacts installed, and we don’t want the last patch installed. Let’s look at what happens.
First, delete the Awesome Contacts solution:
Our layers now look like:
And the field length is 200:
Now if we delete the Contact Enhancements – FirstName 250:
We are back to a field length of 150:
With the layers looking like:
At some point in the process, we may decide to roll our patches up into our parent solution. Doing so means we will have a new solution that contains all the latest code, and having one solution instead of a solution with multiple patches makes it easy to deploy to a new environment.
To roll up patches into a solution, we use Clone Solution. To do this, select the parent solution and click Clone->Clone to Solution (note if you chose a patch solution, this option would be greyed out):
We are now presented with the ability to change the major and minor version numbers of this solution. Notice that the minor version number has been automatically incremented for us:
Once the cloning is complete, the older version of the solution and its patches have been deleted automatically:
FYI, note that the target environment does not give us this option:
Hopefully this helps with your understanding of how patching and solutions work.