Improve Solution import time
Microsoft is investing a lot in advancements in the overall Application Lifecycle Management process and capabilities. One area they already made a lot of improvements is the Solution import time. In this blog post, we will discuss how this improved solution import time can be achieved.
Background
As mentioned Microsoft has improved the import time when it is done with the correct configuration. At one customer project, I was able to get our import down from usually 60 minutes to around 5 min.
What we have to do is use managed solutions and do an Update as well as have both “ConvertToManaged” and “OverwriteUnmanagedCustomizations” set to false time can be improved tremendously.
The question is what those two configurations do and why they improve the import time so much.
ConvertToManaged
As the name says it will convert components to Managed. This means when there is a component in your solution, which is already present in the target environment as unmanaged, it will be changed to a managed solution.
OverwriteUnmanagedCustomizations
When this configuration is set to true it will overwrite unmanaged customizations if there are any.
The reason why the import gets so slow when those are true is that the import engine has to loop through all components and compare them to the ones already present in the environment. When they are false the components will just get overwritten (with minimal changes) without comparing them.
Configuration
In this chapter, I will explain how this change is configured. There will be explanations for the “classic” UI and YAML. Both are for Azure DevOps pipelines, but could also be done in GitHub Actions.
The Maker portal does not have the option to change the mentioned parameters (there they are true with every import). Every tool that uses the API (MS Docs) is able to set those parameters. This means it not only is available in a pipeline (as I show it in this article) but also in some XrmToolBox Tools (or any other tool) such as the Solution Transferer.
Thanks to Tanguy Touzard (LinkedIn) for mentioning it to me.
- task: PowerPlatformImportSolution@2 displayName: Import Solution - ${{ solution }} inputs: authenticationType: 'PowerPlatformSPN' PowerPlatformSPN: '<Name of your connection>' SolutionInputFile: '<Path to your solution>' ConvertToManaged: false OverwriteUnmanagedCustomizations: false AsyncOperation: true MaxAsyncWaitTime: '60'
In the classic UI, it is important to mention that the naming of the configuration is incorrect. “OverwriteUnmanagedCustomizations” is correctly called “Overwrite unmanaged customizations”. The problem comes with “ConvertToManaged”, in the UI it is called “Import as a Managed solution”.
Optimization
As always there are ways of optimizing this process. As I mentioned earlier you should upgrade every once in a while. The best-case scenario would be to do this in the same pipeline. To achieve this we could add parameters to the pipeline. Those could be set on run time and change the behaviour of the pipeline.
Afaik this is only possible in YAML pipelines.
We would need 4 parameters:
- Import as Holding Solution
- Apply Upgrade
- Convert to Managed
- Overwrite Unmanaged
- name: importHolding displayName: Import as Holding Solution default: False type: boolean values: - False - True - name: applyUpgrade displayName: Apply Upgrade default: False type: boolean values: - False - True - name: overwriteUnmanaged displayName: Overwrite Unmanaged type: boolean default: False values: - False - True - name: convertToManaged displayName: Convert to Managed type: boolean default: False values: - False - True
The actual step also needs to be changed in a way that it is using the new parameters.
- task: PowerPlatformImportSolution@2 displayName: Import Solution - ${{ solution }} inputs: authenticationType: 'PowerPlatformSPN' PowerPlatformSPN: '<Name of your connection>' SolutionInputFile: '<Path to your solution>' HoldingSolution: ${{ parameters.importHolding }} ConvertToManaged: ${{ parameters.convertToManaged}} OverwriteUnmanagedCustomizations: ${{ parameters.overwriteUnmanaged}} AsyncOperation: true MaxAsyncWaitTime: '60'
As you might have noticed we also have created a parameter to decide on whether to directly apply the upgrade. When this is set to true an extra step to apply the upgrade should be executed.
This parameter is needed, instead of applying it directly all the time, in case there is a need to do some manual steps (for example migration) before the upgrade is applied (and potentially components deleted).
Conclusion
To be able to apply the mentioned improvements you can’t use the maker portal for importing your solutions. When this prerequisite is met this advancement is easily implemented.
It is just important to use Update in combination with the correct configuration.
My recommendation is to run the mentioned configuration as your default and every “once in a while” (maybe once a quarter or so) run a “full-blown” upgrade where you also set the mentioned configuration to true. With this, you will still “clean up” your downstream environments.
I hope this article was helpful. If you have any questions do not hesitate to leave me a comment or get in touch with me.
You can also subscribe and get new blog posts emailed to you directly.
Using update has significantly improved our import times. Few caveats to it though, which have caught me out a couple of times, is that some changes do not get applied in an Update. Two examples of this are removing columns from relationship mapping and removing security roles from apps. These changes are only applied using Upgrade. This makes sense when you think about it as Update doesn’t do a full comparison. There are no doubt other areas where an Upgrade is required but hopefully this will save others time trying to investigate why changes were not applied as desired.
[…] the correct settings (see my latest blog post about this) are used a managed import might be faster than a managed […]