Using the Power Platform Build Tools w/Azure Pipelines


I was called the other day by someone I know who works with Dynamics 365 (who is not a dev) and wanted to know if they could do some deployment automation by uploading the solution export (.zip) to a Git repository. Not all projects have budgeted to build pipelines for their Dynamics CRM and so just export and import of the solutions manually from one environment to another is usually the process that is adopted.

Power Apps | Solutions | Export this solution
Export this solution

This is not really the best method for managing your custom solutions. Luckily the Power Platform team has created a ton of guidance which you can review here.

This blog post aims to share how you can go from shipping your solutions manually to using Azure DevOps, store your solutions in Git and leverage Azure Pipelines to manage your solution and deploy them to a testing environment. Once approved, the solution can be deployed to production for your users.

If your Microsoft 365 user account/tenant requires two factor authentication (2FA) then you will have to perform a few extra steps as you will not be able to use a username/password combination when connecting to Dynamics from the Azure Pipeline. In this case we will use an App Registration.

You will need the following to continue:

  • Azure DevOps
  • Azure Application Registration
  • Common Data Service environments (Power Apps)
    • Developer Environment
    • Just-In-Time (JIT) Build Environment
    • Production Environment
  • Power Platform Build Tools

Azure DevOps

If you do not have an Azure DevOps account you can sign up for free here. If you already have an account then click on the Sign in to Azure DevOps available on that same page.

In Azure DevOps we’ll assume you have a Team Project with a Git repository. If this is not the case you can follow the steps here to add a Git repository.

The reason we’re asking for a Git repository is because one of the Azure Pipelines we’ll create will extract the solution and put the source into Git.

If you want to commit the extracted source of a solution package from within an Azure Pipeline you will have to enable contribute permissions to the project build service user by changing the setting from Not set to Allow. More information is available here.

Repositories Permissions

Azure Application Registration

Please follow the steps in this article to create your application registration in Azure AD.

Azure AD | application registration | Overview

Once you have your application registration, you must also add it as an Application User by following the steps in this article. Make sure you assign the System Administrator role to this account.

Application User

In the example above I am adding the user to my Developer environment (sandbox) but you need to do this to every environment that Azure DevOps will have a service connection and its matching Application User.

Power Platform Service Connections

Here are the three (3) service connections I’ve configured in my demo environment which will be used in the various pipeline flows.

Power Platform Service Connections

The service connection requires the following bits of information

  • Server Url
  • Tenant ID
  • Application ID
  • Client Secret
  • Service Connection Name

Azure Pipeline (YAML)

I think we’re ready to build our first Azure Pipeline using YAML to Create an export from Dev and Commit to our repository. In the example below my app is named SampleApp.

SampleApp is the solution we’re extracting

# Starter pipeline
# Create Export from Dev

trigger:
- main

pool:
  vmImage: 'windows-latest'

variables:
  GIT_REDIRECT_STDERR: 2>&1
  Version.Revision: $[counter(format('{0:yyyyMMdd}', pipeline.startTime), 0)]
  BuildPlatform: 'Any CPU'
  BuildConfiguration: 'Release'
  MajorVersion: 1
  MinorVersion: 0
  PatchVersion: 0

name: '$(Build.DefinitionName) $(MajorVersion).$(MinorVersion).$(PatchVersion).$(Date:yy)$(DayOfYear)$(Version.Revision)'

steps:
- checkout: self
  clean: true
  persistCredentials: true

      
- task: PowerPlatformToolInstaller@0
  inputs:
    DefaultVersion: true

- task: PowerPlatformPublishCustomizations@0
  inputs:
    authenticationType: 'PowerPlatformSPN'
    PowerPlatformSPN: 'like10-dev'
- task: PowerPlatformExportSolution@0
  inputs:
    authenticationType: 'PowerPlatformSPN'
    PowerPlatformSPN: 'like10-dev'
    SolutionName: 'SampleApp'
    SolutionOutputFile: '$(Pipeline.Workspace)\Zips\SampleApp.zip'

- task: PowerPlatformUnpackSolution@0
  inputs:
    SolutionInputFile: '$(Pipeline.Workspace)/Zips/SampleApp.zip'
    SolutionTargetFolder: '$(Build.SourcesDirectory)/Solution'

- pwsh: |
   write-host "commit all changes"
   git config user.email "hosted.agent@dev.azure.com"
   git config user.name "Azure Pipeline"
   git checkout $env:Build_SourceBranchName --
   git add --all
   git commit -m "solution source updated by $env:BUILD_BUILDNUMBER [skip ci]"
   write-host "push code to repo"
   git push origin $env:Build_SourceBranchName
  displayName: "Commit changes to Git repo"
  

If you want to see the pipeline you can head over to this public project hosted in Azure DevOps. I have some other pipeline samples in that project also.

The next pipeline which is important is to build a managed solution from the source that is stored in the repository, this one is packaged as an unmanaged solution first and imported into a Just-In-Time build environment, it is then extracted as a managed solution ready for deployment to your UAT, Pre-Prod and Production environments.

  
# Build managed solution from git repository
# requires a Just-In-Time (JIT) environment in Power Apps
# umanaged solution is imported and a managed solution
# is exported
# The managed solution is saved as a pipeline artifact
#

trigger:
  - main
  - develop

pool:
  vmImage: 'windows-latest'

variables:
  # Solution Details
  Solution.Name: 'SampleApp'
  Solution.Path: '$(Pipeline.Workspace)/s/Solution'

steps:

- task: PowerPlatformToolInstaller@0
  displayName: 'Power Platform Tool Installer'
  inputs:
    DefaultVersion: true

- task: PowerPlatformPackSolution@0
  displayName: 'Pack Solution from Repository'
  inputs:
    SolutionSourceFolder: '$(Solution.Path)'
    SolutionOutputFile: '$(Build.ArtifactStagingDirectory)\$(Solution.Name).zip'

- task: PowerPlatformImportSolution@0
  displayName: 'Import Solution to JIT Build Environment'
  inputs:
    authenticationType: 'PowerPlatformSPN'
    PowerPlatformSPN: 'like10-jit'
    SolutionInputFile: '$(Build.ArtifactStagingDirectory)\$(Solution.Name).zip'
    AsyncOperation: true
    MaxAsyncWaitTime: '240'

- task: PowerPlatformExportSolution@0
  displayName: 'Export Managed Solution'
  inputs:
    authenticationType: 'PowerPlatformSPN'
    PowerPlatformSPN: 'like10-jit'
    SolutionName: '$(Solution.Name)'
    SolutionOutputFile: '$(Build.ArtifactStagingDirectory)\$(Solution.Name)_managed.zip'
    Managed: true

- task: PublishPipelineArtifact@1
  displayName: 'Publish Artifacts managed and unmanaged solutions'
  inputs:
    targetPath: '$(Build.ArtifactStagingDirectory)\'
    artifact: 'PowerAppSolutions'
    publishLocation: 'pipeline'

Some steps you may want to include during this pipeline execution is to *version* the managed solution, Power Platform Build tools has a task which can put your version string on the app prior to the export.

Hopefully you find this helpful, if you have any questions or I’ve missed something please feel free to leave a comment below.

About Wes MacDonald

Wes MacDonald is a DevOps Consultant for LIKE 10 INC., a DevOps Consulting firm providing premium support, guidance and services for Azure, Office 365 and Azure DevOps.

No comments yet... Be the first to leave a reply!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: