Introduction
Leveraging Azure DevOps YAML pipelines to Export Solutions from Dynamics CRM/Power Platform allows us to automate the deployment process, ensuring our solutions are always up-to-date in the repository. This blog post will guide you through setting up an Azure DevOps YAML pipeline to export Dynamics 365 solutions from different environments and commit them to your repository.
Unique features of this YAML Pipeline
- Parameterized Execution: Customize the pipeline execution using the following parameters.
- Work Item Number: Identify the work item number associated with the ongoing work.
- Commit Message: Specify a commit message for the updates of the considered solutions.
- Work Type: Define the type of work in progress with options like 'work' or 'hotfix'.
- Dynamics 365 Solutions: Choose the Dynamics 365 solutions to export.
- Source Dynamics 365 Environment: Select the source Dynamics 365 environment for exporting solutions.
- Dynamic Variables: Utilize dynamic variables for various purposes.
- Version Control: Automatically set the version of the solutions before exporting.
- Branch Management: Define the branch name based on the work item number and type of work.
- Folder Paths: Specify folder paths for unpacking solutions and storing deployment settings.
- PowerApps CLI Integration: Install and use the PowerApps CLI for additional operations like creating deployment settings.
- Multi-Environment Support: Export solutions from various Dynamics 365 environments based on the selected environment.
- Batch Export: Export multiple solutions simultaneously for improved efficiency.
- Artifact Publishing: Publish exported solutions as built artifacts for easy access and sharing.
- Git Integration: Commit and push changes to the remote repository automatically, ensuring version control and collaboration.
Pipeline YAML
Here's the YAML pipeline that accomplishes the above tasks.
# Pipeline for the export and unpack of Dynamics 365 solutions
# Manual trigger
trigger: none
# Parameters
parameters:
- name: WorkItemNumberParameter
displayName: Work item number
type: string
- name: CommitMessageParameter
displayName: Commit message
type: string
- name: WorkTypeParameter
displayName: Work type
type: string
default: work
values:
- work
- hotfix
- name: Dynamics365Solutions
displayName: Dynamics 365 solutions
type: object
default:
- solutionone
- solutiontwo
- solutionthree
- name: Dynamics365EnvironmentParameter
displayName: Source Dynamics 365 environment
type: string
default: dev
values:
- dev
- dev01
- dev02
- dev03
- dev04
# Variables
variables:
- name: WorkItemNumber
value: ${{ parameters.WorkItemNumberParameter }}
- name: CommitMessage
value: ${{ parameters.CommitMessageParameter }}
- name: PowerPlatformSPN
value: 'Project EO - Dynamics 365 - ${{ parameters.Dynamics365EnvironmentParameter }}'
- name: SolutionVersion
value: 1.0.$(version).0
- name: BranchName
value: '${{ parameters.WorkTypeParameter }}/dynamics365/$(WorkItemNumber)'
- name: UnpackedSolutionFolder
value: 'Solutions'
- name: DeploymentSettingsFolder
value: 'Configurations\DeploymentSettings\'
- name: BuildConfiguration
value: 'Release'
- name: BuildPlatform
value: 'Any CPU'
- name: D365DevURL
value: 'https://dharmicrm10-dev.crm8.dynamics.com/'
# Definition of the Build.BuildNumber variable value
name: ${{ variables.SolutionVersion }}
pool:
vmImage: windows-latest
steps:
# Install the Power Platform Build Tools
- task: PowerPlatformToolInstaller@2
displayName: 'Install Power Platform Build Tools'
inputs:
DefaultVersion: true
# "Microsoft.PowerApps.CLI" setup
- task: PowerShell@2
displayName: 'PowerApps CLI setup'
inputs:
targetType: 'inline'
script: |
Write-Host 'Get Microsoft.PowerApps.CLI nugget package'
$nugetPackage = 'Microsoft.PowerApps.CLI'
$outFolder = 'pac'
nuget install $nugetPackage -OutputDirectory $outFolder
$pacNugetFolder = Get-ChildItem $outFolder | Where-Object {$_.Name -match $nugetPackage + '.'}
$pacPath = $pacNugetFolder.FullName + '/tools'
echo "##vso[task.setvariable variable=powerAppsCliPath]$pacPath"
# Update the version of the solution
- ${{ each solution in parameters.Dynamics365Solutions }}:
- task: PowerPlatformSetSolutionVersion@2
displayName: 'Set version on ${{ solution }}'
inputs:
authenticationType: 'PowerPlatformSPN'
PowerPlatformSPN: '$(PowerPlatformSPN)'
SolutionName: ${{ solution }}
SolutionVersionNumber: ${{ variables.SolutionVersion }}
# Publish customizations
- task: PowerPlatformPublishCustomizations@2
inputs:
authenticationType: 'PowerPlatformSPN'
PowerPlatformSPN: '$(PowerPlatformSPN)'
- task: PowerShell@2
displayName: 'Checkout $(BranchName) branch'
inputs:
targetType: 'inline'
script: |
git config user.email '[email protected]'
git config user.name 'Automatic Build'
$branchFullName = 'origin/$(BranchName)'
Write-Host 'List remote branches'
git pull
$remotebranches = git branch -r
Write-Host 'Search for the following branch: $branchFullName'
$branchExists = $remotebranches | where { $_.Replace(' ', '') -eq $branchFullName }
Write-Host 'Create or checkout considered branch'
# Create branch if does not exist
if (!$branchExists) {
Write-Host 'Create branch because it does not exist:'
git checkout -b $(BranchName)
}
# Checkout branch if it exists
else {
Write-Host 'Checkout branch because it exists:'
git checkout --track $branchFullName
}
Write-Host 'Verify the checkout branch:'
git branch
- ${{ each solution in parameters.Dynamics365Solutions }}:
# Export considered solution as unmanaged
- task: PowerPlatformExportSolution@2
displayName: 'Export ${{ solution }} solution (Unmanaged)'
inputs:
authenticationType: 'PowerPlatformSPN'
PowerPlatformSPN: '$(PowerPlatformSPN)'
SolutionName: '${{ solution }}'
SolutionOutputFile: '$(Build.ArtifactStagingDirectory)\${{ solution }}.zip'
AsyncOperation: true
MaxAsyncWaitTime: '60'
# Export considered solution as managed
- task: PowerPlatformExportSolution@2
displayName: 'Export ${{ solution }} solution (Managed)'
inputs:
authenticationType: 'PowerPlatformSPN'
PowerPlatformSPN: '$(PowerPlatformSPN)'
SolutionName: '${{ solution }}'
SolutionOutputFile: '$(Build.ArtifactStagingDirectory)\${{ solution }}_managed.zip'
Managed: true
AsyncOperation: true
MaxAsyncWaitTime: '60'
# "Microsoft.PowerApps.CLI" setup
- task: PowerShell@2
displayName: 'Generate deployment settings file for ${{ solution }}'
inputs:
targetType: 'inline'
script: |
Write-Host 'Generate deployment settings file'
$env:PATH = $env:PATH + ';' + '$(powerAppsCliPath)'
pac solution create-settings --solution-zip '$(Build.ArtifactStagingDirectory)\${{ solution }}.zip' --settings-file $(DeploymentSettingsFolder)\${{ solution }}\DeploymentSettings-dev.json
# Unpack both exported solutions (unmanaged and managed)
- task: PowerPlatformUnpackSolution@2
displayName: 'Unpack ${{ solution }} solution (Both)'
inputs:
SolutionInputFile: '$(Build.ArtifactStagingDirectory)\${{ solution }}.zip'
SolutionTargetFolder: '$(UnpackedSolutionFolder)\${{ solution }}'
SolutionType: 'Both'
# Publish Artifacts
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact - Solutions'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'Solutions'
publishLocation: 'Container'
# Push new version of the unpacked exported solution
- task: PowerShell@2
displayName: 'Push changes on Dynamics Solutions to remote'
inputs:
targetType: 'inline'
script: |
Write-Host 'Commit all changes in the Dynamics Solutions'
git add --all
git commit -m 'Dynamics Solutions - ${{ variables.SolutionVersion }} - $(CommitMessage)'
Write-Host 'Push all changes
While Running the Pipeline, give the required Parameters.
The Sample Pipeline Output will be.
Advantages of using this YAML pipeline for Dynamics 365 solution export
- Efficient Bulk Export: Export multiple solutions simultaneously for improved productivity.
- Dynamic Environment Selection: Seamlessly export solutions from different Dynamics 365 environments.
- Flexible Branch Management: Create or switch branches based on work item numbers and types for better organization.
- Automated Versioning: Automatically set solution versions for consistent tracking and management.
- Integrated PowerApps CLI: Execute Power Platform tasks seamlessly within the pipeline.
- Accessible Artifact Publishing: Share exported solutions easily with team members.
- Automated Git Operations: Commit and push changes to the repository automatically for streamlined version control.
- Customizable Parameters: Tailor pipeline execution to project needs with flexible parameterization.
In essence, this YAML pipeline simplifies Dynamics 365 solution export, offering efficiency, flexibility, and automation to development workflows.