Idempotent Missing Dependencies

A recent update to the solution engine means we now have fewer merge conflicts due to a change in the critical solution.xml file which makes it easier to implement healthy ALM for Power Platform developments.

Source control is the foundation for healthy Power Platform/Dynamics development and ALM. Each developer (or team if working on the same feature) should also have a unique environment.

A key feature of source control is branching and merging. The process to implement a new feature (or bug fix) can be generalised as:

  1. a feature branch is taken from the ‘main’ or ‘release’ branch,
  2. an environment is created matching the feature branch
  3. alterations are made in solutions within the platform to implement the feature
  4. the solution.zip is exported, unpacked using Solution Packager, and the changes committed to the feature branch in source control
  5. the feature branch is merged back into the main branch via a pull request after passing quality checks

Solution.xml

Until recently step 5 (merging) has proved difficult due to the critical solution.xml file located in the Other folder. Solution.xml contains the solution manifest, comprising:

  • UniqueName, LocalisedNames, Descriptions - the solution unique name, localised names and descriptions in various locales
  • Version - the solution version
  • Managed - indicating if it is a managed (0) or unmanaged (1) solution.
  • Publisher - the unique name, localised name and description of the publisher along with the customisation prefix
  • RootComponents listing the components added or modified in the solution
  • MissingDependencies listing the components that must be present before the solution can install (provided either by other managed solutions or within the unmanaged layer).

Missing dependencies

There has long been an issue with the elements within RootComponents and MissingDependencies being output in a seemingly random order, causing merge conflicts when using standard source control tools, especially git merge.

For around six months (maybe more), RootComponents has been output in a consistent order. Around a week ago (in a crm4 environment), MissingDepencenies now also outputs in a consistent order.

Before 25th May 2021:

      <MissingDependency>
        <Required key="245" type="61" schemaName="LeadManagement/Lead/Lead_main_system_library.js" displayName="LeadManagement/Lead/Lead_main_system_library.js" solution="msdynce_LeadManagement (9.0.4.0066)" />
        <Dependent key="217" type="60" displayName="Marketing List Light" parentDisplayName="Marketing List" id="{07a20eff-82ea-442b-ad8e-8295048e563d}" />
      </MissingDependency>
      <MissingDependency>
        <Required key="246" type="1" schemaName="productassociation" displayName="Product Association" solution="msdynce_ProductManagement (9.0.4.0066)" />
        <Dependent key="247" type="60" displayName="ACME" parentDisplayName="Product" id="{943e12e4-81e2-4c06-ab05-21aaefdec284}" />
      </MissingDependency>
      <MissingDependency>
        <Required key="248" type="1" schemaName="productsubstitute" displayName="Product Relationship" solution="msdynce_ProductManagement (9.0.4.0066)" />
        <Dependent key="247" type="60" displayName="ACME" parentDisplayName="Product" id="{943e12e4-81e2-4c06-ab05-21aaefdec284}" />
      </MissingDependency>
      <MissingDependency>
        <Required key="249" type="1" schemaName="dynamicproperty" displayName="Property" solution="msdynce_ProductManagement (9.0.4.0066)" />
        <Dependent key="247" type="60" displayName="ACME" parentDisplayName="Product" id="{943e12e4-81e2-4c06-ab05-21aaefdec284}" />
      </MissingDependency>

After 25th May 2021:

Notice the 'key' attribute is missing and the dependencies are output in solution component type and schemaName order.

      <MissingDependency>
        <Required type="1" schemaName="dynamicproperty" displayName="Property" solution="msdynce_ProductManagement (9.0.4.0066)" />
        <Dependent type="60" displayName="ACME" parentDisplayName="Product" id="{943e12e4-81e2-4c06-ab05-21aaefdec284}" />
      </MissingDependency>
      <MissingDependency>
        <Required type="1" schemaName="productassociation" displayName="Product Association" solution="msdynce_ProductManagement (9.0.4.0066)" />
        <Dependent type="60" displayName="ACME" parentDisplayName="Product" id="{943e12e4-81e2-4c06-ab05-21aaefdec284}" />
      </MissingDependency>
      <MissingDependency>
        <Required type="1" schemaName="productsubstitute" displayName="Product Relationship" solution="msdynce_ProductManagement (9.0.4.0066)" />
        <Dependent type="60" displayName="ACME" parentDisplayName="Product" id="{943e12e4-81e2-4c06-ab05-21aaefdec284}" />
      </MissingDependency>
      <MissingDependency>
        <Required type="61" schemaName="LeadManagement/Lead/Lead_main_system_library.js" displayName="LeadManagement/Lead/Lead_main_system_library.js" solution="msdynce_LeadManagement (9.0.4.0066)" />
        <Dependent type="60" displayName="Marketing List Light" parentDisplayName="Marketing List" id="{07a20eff-82ea-442b-ad8e-8295048e563d}" />
      </MissingDependency>

Remaining differences

Only the ImportExportXml version attribute and the Version element remain variable.

Remaining variable parts of solution.xml

Conflicts in the ImportExportXml version are easy to merge manually, and are probably unavoidable given that Microsoft controls the dataverse version.

To avoid conflicts, the solution Version element it can be reset to 0.0.0.0 upon every export, as implemented by the Advanced ALM for App Makers pipeline, see export-Solution.yml. The Version is reset when a solution is built via a pipeline.

Summary

  • Solution.xml now outputs in a consistent idempotent order, no longer containing a sequential key attribute in the MissingDependency element.
  • We can merge customisations exported from separate environments with fewer conflicts.
  • We still need to be careful about editing the same components across environments as documented by Microsoft.