This is the third of a multi-part series suggesting an ALM process in projects where Microsoft Dynamics CRM is used as a data store.
My pervious blog post was about setting a Development Build for the developers so that they can build the system (including all latest Microsoft CRM Dynamics artefacts) end to end. In this post, I will write about about setting up a Team Build.
The purpose of the Team build is to compile and build all system artefacts to produce a deployable package. The package is then read by the deployment scripts to deploy the system to a target environment. For a very simple project, the deliverable may be an executable or an MSI. For a more complicated system, it may include published websites, assemblies, databases, etc. For Microsoft Dynamics CRM, the deliverables will be a managed / unmanaged solution along with artefacts such a data maps, data import files, de-duplication rules, SSRS Reports, etc.
CRM Deployment Overview:
Before describing the team build, let’s first take a brief look of what the CRM deployment script would do.
- Create a new CRM Organisation.
- Set Organisation settings.
- Import Solution.
- Import Data Maps.
- Import Data.
- Import Bulk Deletion Operations.
- Publish SSRS Reports.
- Set Field Level Security.
- Publish unpublished workflows.
Above is one of the several possibilities and might not meet your exact requirements. For example, your solution might have to be deployed to an existing organisation, in which case step 1 is not needed. I will detail the deployment process in more detail in the next blog.
Structuring CRM Package
Having taken a look at how the deployment of CRM would take place, let’s take a look at the Dynamics CRM deliverables and how to structure them in the deployment package. Some of the deliverables (such as plug-in assemblies) needs to be compiled, some needs to be taken straight from the source control. In any case, it is essential that the deliverables are taken from source control and not from the a CRM development instance. The following diagram describes how I would structure the deliverables in the CRM folder.
All these folders are contents of the CRM folder that is included in the cabinet file produced by the build. Let’s have a look at each of the folders
- Assemblies: The folder contains Microsoft Dynamics CRM deployment assemblies such as Microsoft.xrm.sdk.deployment.dll.
- BulkDeleteOperations: The folder contains the exported Bulk deleted operations files from the Development instance of CRM.
- Data: The folder contains initialisation data for the system. The folder contains a csv file for each entity that needs to have initialization data as well as a data map file.
- DedupeRules: Contains the de-duplication rules for entities.
- FieldLevelSecurity: Contain team association for field level security of custom and out-of-the-box entities.
- Reports: Contain details of the the reports to be published.
- Settings: Contains organisation setting details.
- Solutions: Contains the managed or unmanaged solutions that contains all the customisations.
- Workflows: Imported solutions do not have workflows enabled automatically for themselves. This folder contains information of workflows that would need to be enabled. Structuring CRM Package
Structuring CRM Source
The Microsoft Dynamics CRM source code would be structured as CRM SDK creates them. These will be built as part of compilation of CRM solution in team build. The following diagram describes a typical structure of CRM source code.
Team Build:
The Team build will take the contents of the above-mentioned folders, apart from the Solution folder, straight from the source control. The data csv files would be maintained in source control, while other files such as Data Import files,bulk deletion operations, de-duplication rules, etc would be exported from the CRM development instance and checked-in into source control.
The solutions, on the other hand, would be created by Team Build using the CRM’s SolutionPackager utility. However, before the solution is package, a mapping file should be created to map plug-in assemblies correctly. The FileMapping.ps1file perform this action. The following target in your team build will package the CRM solution for you.
<Target Name="PackageCRMSolution">
<BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="...Packaging CRM Solution" Status="Succeeded" Condition="'$(BuildUri)' != ''"/><!-- Copying CRM deployment files-->
<BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="......Copying CRM Deployment files" Status="Succeeded" Condition="'$(BuildUri)' != ''"/>
<ItemGroup>
<CrmDeploymentFiles Include="$(SolutionRoot)\Build\Deployment\CRM\**\*.*" Exclude="$(SolutionRoot)\Build\Deployment\CRM\Solutions\SolutionFiles\*.zip"/>
</ItemGroup>
<Microsoft.Build.Tasks.Copy SourceFiles="@(CrmDeploymentFiles)" DestinationFiles="@(CrmDeploymentFiles->'$(BinariesRoot)\Release\Server\CRM\%(RecursiveDir)%(Filename)%(Extension)')" /><!-- File Mapping -->
<BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="......Run File Mapping" Status="Succeeded" Condition="'$(BuildUri)' != ''"/>
<Microsoft.Build.Tasks.Exec command="powershell $(BuildToolsPath)\FileMapping.ps1 -binarySearchLocation "$(BinariesRoot)\Release\Server\CRM" -unpackFolderLocation "$(SolutionRoot)\Source\CRM\Solution1" -outputLocation "$(BinariesRoot)\Release\Server\CRM"" /><!-- Solution Packager UnManaged-->
<BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="......Package CRM solution - Unmanaged" Status="Succeeded" Condition="'$(BuildUri)' != ''" />
<Microsoft.Build.Tasks.Exec command="$(BuildToolsPath)\SolutionPackager /a:Pack /z:"$(BinariesRoot)\Release\Server\CRM\Solutions\CrmSolution1_1_0_0_0_unmanaged.zip" /f:"$(SolutionRoot)\Source\CRM\Solution1" /p:Unmanaged /m:"$(BinariesRoot)\Release\Server\CRM\mapping.xml""/><BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="......Package CRM solution - Managed" Status="Succeeded" Condition="'$(BuildUri)' != ''"/>
<Microsoft.Build.Tasks.Exec command="$(BuildToolsPath)\SolutionPackager /a:Pack /z:"$(BinariesRoot)\Release\Server\CRM\Solutions\CrmSolution_1_0_0_0_managed.zip" /f:"$(SolutionRoot)\Source\CRM\Solution1" /p:Managed /m:"$(BinariesRoot)\Release\Server\CRM\mapping.xml""/><ItemGroup>
<CRMFilesToCleanUp Include="$(BinariesRoot)\Release\Server\CRM\*.*" Exclude="$(BinariesRoot)\Release\Server\CRM\*.zip" />
</ItemGroup>
<Delete Files="@(CRMFilesToCleanUp)" Condition="@(CRMFilesToCleanUp) != ''" /><BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="...Completed Packaging CRM Solution" Status="Succeeded" Condition="'$(BuildUri)' != ''"/>
</Target>
Once the above target is included in your team build, your build will produce the CRM deployment folder as described above. I like to create a cabinet (.cab) file out of all files in the Drop folder, but it is certainly optional. In my next blog, I will write about the deployment script to deploy the CRM deliverable files produced by the team build.
1 comment:
Can you please provide a working example of this... Thank you..
Post a Comment