Application Lifecycle Management for the Power Platform using Azure DevOps
Updated: Mar 3
Hey!
How are you all recovered from the UK heat this week? Crikey, that was a hot one! In this blog post I will be talking about how you can use Azure DevOps to build and release Power Platform solutions. Special thanks to Sammy Hassan for showing me the light!

Update 1
I have put all of this into a YouTube video if you would rather check that out instead, it's kind of meant to be there in parallel with this blog post:
Update 2
I have added a further reading section, which may or may not grow over time. The first link is one to a blog post by Benedikt Bergmann on moving environment variables over with Azure DevOps.
Update 3
I have added another Step, Step 10, which talks about moving environment variables between environments using a Replace Token step.
Contents
Introduction
Prerequisites
Step 1: Create an app registration in your Azure AD environment
Step 2: Give Power App Management Permission to your App
Step 3: Install Azure DevOps extensions
Step 4: Create a Main branch repository
Step 5: Create a pipeline to import solution
Step 6: Create an App registration for the target environment
Step 7: Create app users in your Dataverse environments
Step 8: Run the Pipeline to create the build artifact
Step 9: Create a release
Tips and tricks
Step 10: Configuring Variable groups for transfer of environment variables
Introduction
Application Lifecycle Management or ALM is a practice that has been around for a long time, it is an integrated system of tools, people and processes that help to streamline the build and release of software components from Development > UAT > Production. It can also be extended to incorporate automated testing, providing results back to the development team for further continuous improvement and then to repeat the process again.
A solid Power Platform environment strategy will include a minimum of a development, UAT and production environment, as well as a potential staging environment that is a copy of UAT for any additional testing by other teams that might be required.
Now with Azure DevOps it is possible to utilise the power of this tool, to automate the build and release of solutions from one environment to another, cross tenancy. For example, you may do development in your own Development environment, but then need to push those changes to a client's UAT/Production environment, this is possible with the ALM Accelerator for the Power Platform. Below, I am going to guide you through what you need to do to set this up.
Note: The ALM Accelerator is in public preview. For more information on the current status of the public preview of the ALM Accelerator, please click here.
This blog post is going to cover build pipelines and a standard release.
Prerequisites
The ALM Accelerator for the Power Platform needs to be installed in an environment that has a Dataverse database. From here, the accelerator can only be used to deploy solutions to other environments which also have a Dataverse database to deploy your solutions to.
Along with the above, the following are required:
A licensed Azure user with permission to create and view Azure AD groups, create app registrations, and grant admin consent to app registrations in Azure AD.
A licensed Azure DevOps user with permissions to create and manage pipelines, service connections (requires Creator rights or above), repos, and extensions.
A licensed Microsoft Power Platform user with permission to create application users and grant administrative permissions to the application user.
Step 1: Create an app registration in your Azure AD environment
Sign in to the Azure Portal:

Search for App Registrations:

Click on New Registration:

Give the App a name, leave everything else as default and click Register:

Take a copy of the Application (client) ID and Directory (tenant) ID, save these in a notepad, we will need them later:

Under the manage section on the left-hand side navigation, click on API permissions:

Click on Add permission, and then choose the Dynamics CRM item on the right -hand side

Choose the user_impersonation permission and click Add permissions:

Add another permission, this time, we need to click on APIs my organization uses and search for the PowerApps-Advisor API:

Choose Delegated permissions and choose the Analysis.All permission and click Add permissions:

Finally add another permission and select the Azure DevOps API, which is inside the Microsoft APIs tab and click on the user_impersonation permission:

After adding all of these permissions, click on the Grant admin consent button as shown below:

At this point, you may get an error, I received this:
Could not grant admin consent. Your organization does not have a subscription (or service principal) for the following API(s): Azure DevOps
I solved this problem by signing up for an Azure free subscription and made sure I was the owner of the subscription and then also made sure I had created an Azure DevOps project, by signing up to Azure DevOps here.
Next, we need to new client secret, we can do this by clicking on the Certificates & secrets in the left-hand navigation and then click on "New client secret", as shown below:

Give it a name, leave the expiry as it is and click Add:

We have just created a client secret, IMPORTANT we need to take a copy of the Value and store this in our notepad for later:

Click on Overview in the left-hand navigation and click on Add a Redirect URI:

Click on Add a platform, click on Web and then add the URL (https://global.consent.azure-apim.net/redirect) into the redirect URI field and click Configure:

Step 2: Give Power App Management Permission to your App
So that the Azure pipelines can perform actions in the environment inside your Power Platform tenant, we need to grant Power App Management permissions to the App registration we created above in Azure.
To do this, we need to open Windows PowerShell ISE as an Administrator and run a PowerShell command. Once run, the command gives permissions to the Service Principal to be able to execute environment functions.
To do this you will need the Application (client) ID we created earlier, and also to open Windows PowerShell ISE as an Administrator
Install-Module -Name Microsoft.PowerApps.Administration.PowerShell
Install-Module -Name Microsoft.PowerApps.PowerShell -AllowClobber
New-PowerAppManagementApp -ApplicationId [the Application (client) ID you copied when creating your app registration]
You will be asked to update the NuGet package, click Yes to this. You will also be asked to trust modules to be installed from PSGallery, we can click Yes to All for this.
Step 3: Install Azure DevOps extensions
We now need to install some Azure DevOps extensions. These are third-party extensions that are available in the DevOps market place.
Install the following extensions:
Power Platform Build Tools - https://marketplace.visualstudio.com/items?itemName=microsoft-IsvExpTools.PowerPlatform-BuildTools
Replace tokens - https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens
SARIF SAST Scans Tab - https://marketplace.visualstudio.com/items?itemName=sariftools.scans
For each link click on the green "Get it Free" button, choose your organisation from the drop down and click install.
Step 4: Create a Main branch repository
We need somewhere to store our solution, to do this we need to create a repository, or a repo. Go to https://dev.azure.com/ and choose Repos from the left-hand navigation and click on Initialize as shown in the screenshot below:

Step 5: Create a pipeline to import solution
We are now going to jump into Azure DevOps into the Pipelines section. What we are going to do here is create a pipeline, also known as a build, that will export a solution for us and save it in the cloud so that we can then release it to our target environment at a subsequent step.
Go to https://dev.azure.com/ and choose your Project.
Click on Pipelines on the left-hand navigation and click Create Pipeline.
Choose the "Other GIT" option for Where is your code? :

Select Azure Repos Git and choose the branch you created above and click continue

Scroll down to the bottom of the Select a template list and choose Empty Pipeline.
We are taken to the build pipeline page; it is here that we are going to create a build pipeline profile which will use various Power Platform tasks so that we can export our solution and store it in the main branch ready for a release later on.
Click on the plus (+) icon next to the Agent job 1 section:

Search for Power Platform and all the relevant tasks will appear:

Click on each one of these in order, and click the Add button:
Power Platform Tool Installer
Power Platform Who Am I
Power Platform Publish Customizations
Power Platform Export Solution (we will rename this to Power Platform Export Managed Solution)
Power Platform Export Solution (we will rename this to Power Platform Export Unmanaged Solution)
Power Platform Unpack Solution
Then finally search for Publish Build Artifact and add this as the 7th and final step.
We now have our first Build pipeline:

As you can see, some of the steps say they need attention. Let's look at the Power Platform Who Am I step first.
We need to create a service connection to our Dataverse environment to be able to identify who is trying to access our environment. To do this, first click the Service Principal/client secret click on Manage, you will be taken to another page where you can click on Create service connection:

In the New service connection section, choose Power Platform and click Next. This is where your notepad you have stored all the IDs are going to come in handy.
Head over to the Power Platform Admin Centre - https://admin.powerplatform.microsoft.com/ and click on Environments, and choose the environment you are going to be exporting a solution from and copy the environment URL, place this in the Server URL field inside the New Power Platform Service connection section.
For Tenant ID, copy and paste that in and do the same for Application ID and Client secret:

Now go back to the tab where we were creating the Build Pipeline and click on the refresh icon and choose the Service Connection we have just created.

Follow exactly the same as above for the Power Platform Publish Customizations step.
For the Power Platform Export Solution step, first we are going to rename it to Power Platform Export Managed Solution
We then need to head to our Solutions area in the Source environment and take a copy of the Name value:

We can add the name value into the Solution Name field and then for the Solution Output File, use the following $(Build.ArtifactStagingDirectory)\Solution_Name_managed.zip and check the "Export as Managed solution" check box as I have done below:

Repeat the same for the next Power Platform Export Solution step, but remember to change the solution output file to unmanaged and ensure the "Export as Managed Solution" is unchecked:

Next go to the Power Platform Unpack Solution step, for the Solution Input file, copy that over from the previous step, and for the Target Folder to Unpack Solution paste in $(Build.ArtifactStagingDirectory)\Solution_Name, as I have done below:

The final"P ublish artifacts" step can be left as is.
Click Save under the Save and Queue drop down.
Step 6: Create an App registration for the target environment
Please follow the steps in Step 1, but create this app registration in the target environment.
Step 7: Create app users in your Dataverse environments
For the source and target environment, we need to create an Application User and link this to the App Registration we created.
Source environment:
Head to the Power Platform admin centre and click on the source environment and then click on See all under Users:

Click on the app users list:

Then click on Setup app user, choose the business unit from the drop down and then click on Add an app