How to deploy Power Apps Portals using Azure Pipelines

Niels Swimberghe

Niels Swimberghe - - Dynamics

Follow me on Twitter, buy me a coffee

Azure Pipelines and Power Apps logo next to title: How to deploy Power Apps Portals using Azure Pipelines

You can manually download Power Apps portals from one environment and upload them to another environment, but you can also automate this using Azure Pipelines and the Microsoft Power Platform CLI.
In this tutorial, you will take the following steps to set up automated portal deployments:

  1. Create an Azure Active Directory (AAD) App Registration with access to your Dataverse
  2. Create a system user in Dataverse linked to your AAD App Registration
  3. Create an Azure Pipeline that installs the Microsoft Power Platform CLI to upload your portal

Create an Azure Active Directory (AAD) App Registration with access to your Dataverse #

To access your Azure Active Directory, you can go straight to the Azure Portal and look up "Azure Active Directory" in the search bar at the top. Click on the Azure Active Directory link listed under services.

There's also a shortcut in the admin center. Browse to admin.microsoft.com, and in the side-navigation click on Show all. Now, all available admin centers are listed. Click on the Azure Active Directory link under Admin centers. This will take you to a specific Azure dashboard for Azure Active Directory.

Click on Azure Active Directory in the side navigation and then click on App Registrations. Click on the New registration button.

Screenshot of Azure Active Directory App Registration screen. Cursor clicks on the "New registration" button.

Give your app a name (fe. AdoToDataverse) and click on Register.

Screen to register an application in Azure Active Directory.

Navigate to your App registration when it is created. On the overview page, take note of the Application (client) ID and the Directory (tenant) ID. You will need these later!

Overview page of the AAD app registration with the Application ID and Directory ID circled in red.

Navigate to the API permissions screen and click on Add permission.

AAD App Registration API Permissions Screen with cursor clicking on the "Add a permission" button.

Click on the APIs my organization uses and search for Dataverse. Click on the Dataverse item.

Screen to add new permissions to AAD app registration and the Dataverse permission is selected.

On the next screen click on the Delegated permissions box and check the box for user_impersionation.
Click on Add permissions.

Details screen for request Dataverse permission for AAD App Registration

While you are still on the API permission screen, click on Grant admin consent for your_tenant_name.

Grant AAD App Registration admin consent

Navigate to the Certificates & secrets screen and click on New client secret.

AAD App Registration screen to add new client secret

Enter a description that will help you identify what this secret is for in the future. For example Client secret for Azure DevOps.
Select when the secret expires. When the secret expires, you can create a new client secret and stop using the old one.

Screenshot of the new client secret entry in AAD App registration

Make sure you copy the secret "Value". You will need this secret and it will never be shown again.

Create a system user in Dataverse linked to your AAD App Registration #

Browse to the Power Platform admin center and click on your environment. 
In your environment settings, click on the See all link for Users.

Power Platform Admin center with the cursor clicking on See all users link

On the Users screen, click on the Manage users in Dynamics 365 button.

Power Platform Admin Center screen to manage users, but the cursor is clicking on "Manager users in Dynamics 365" button.

Switch to the Application Users view and click on the New button.

Dynamics 365 user management view, but the cursor is swapping to the "Application Users" view.

This will open a new window with a form to create the user.

Image of two screens, before and after creating the new application user.

Make sure you are on the Application User form. If not, switch to the Application User form.
Past in the App Registration Application ID from Azure Active Directory into the Application ID field and click on Save.

It takes a second to save, but once saved, the other fields will automatically populate as you can see in the screenshot above on the right side.

Go back to the Application Users view and select your new user using the checkbox at the beginning of the row. 
While the user is selected, click on Manage Roles and give the user the necessary role to upload portals. If you don't have a role specifically for those permissions, you can use System Administrator role for now.

Modal to manage user roles

Create an Azure Pipeline that installs the Microsoft Power Platform CLI to upload your portal #

Microsoft has an extension called "Power Platform Build Tools" for Azure DevOps in the Visual Studio marketplace. You can perform a lot of administrative tasks using those tools including many of the tasks you can perform using the Power Platform CLI. Unfortunately, the Power Platform Build Tools extension does not have any support for download or uploading portals yet.
Luckily, you can still take advantage of the portal capabilities inside of the Power Platform CLI and integrate those into your Azure Pipelines.

Navigate to your Azure DevOps project, or create a new one if you don't have any. 

Navigate to the Pipelines > Pipelines section of your project, and click on the New pipeline button. Azure DevOps will now ask where your code is hosted. You could host your code in any source control server (git, TFVC, or SVN) and integrate it using Azure Pipelines. You will have to set up your own source control and use the Power Platform CLI to download the portal and track the portal files using your source control. This tutorial assumes you have already done this.

Since you're already in Azure DevOps, let's assume you use Azure Repos Git.

Select your git repository with which tracks your unpacked Power Apps portals.

Click on Starter pipeline.

In the last step, replace the YAML code with the following YAML.

trigger: none
  vmImage: windows-latest
  - task: ArchiveFiles@2
      rootFolderOrFile: 'your-portal'
      includeRootFolder: false
      archiveType: 'zip'
      archiveFile: 'your-portal.zip'
      replaceExistingArchive: true
  - task: PublishPipelineArtifact@1
      targetPath: 'your-portal.zip'
      artifact: 'Power Apps Portal archive'
      publishLocation: 'pipeline'
  - task: PowerShell@2
      targetType: 'inline'
      script: |
        Invoke-WebRequest https://aka.ms/PowerAppsCLI -OutFile pac.msi
        msiexec /i pac.msi /quiet /norestart
  - task: PowerShell@2
      PowerPlatformAadApplicationSecret: $(PowerPlatformAadApplicationSecret)
      targetType: 'inline'
      script: |
        # refresh path to make pac available
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") 
        pac install latest
        pac auth create --name ${env:PacAuthProfileName} `
          --url ${env:PowerPlatformInstanceUrl} `
          --tenant ${env:PowerPlatformAadDirectoryId} `
          --applicationId ${env:PowerPlatformAadApplicationId} `
          --clientSecret ${env:PowerPlatformAadApplicationSecret}
        pac org who
        pac paportal upload --path your-portal

The YAML pipeline will do the following:

  • The pipeline is not automatically triggered, which means you will have to trigger it manually
  • When it is triggered, the pipeline will use a Windows machine to do the following two steps:
    • The ArchiveFiles step will zip up all the files inside the 'your-portal' and create a zip-archive named 'your-portal.zip'. This tutorial assumes you are downloading your portal using the Power Platform CLI to the 'your-portal' folder and storing it in source control.
    • The PublishPipelineArtifact step will publish the zip file that was just created in the previous step. 
      This way you can download the ZIP file in the future in case you need to inspect it for some reason. 
    • The first PowerShell step will download the Power Platform CLI installer using Invoke-WebRequest and use msiexec command to install the pac.msi installer.
      When you normally install programs using Microsoft Installers (MSI), you need to click through a wizard, but with msiexec and the /quiet argument, you can install the MSI without the need for user interaction.
    • The second PowerShell step will
      • refresh the path environment variable which will make the pac command available which was installed in the previous step
      • run the pac install latest command to update the pac to the latest version if necessary.
      • the  pac auth create command will try to authenticate against a Power Apps environment. This command takes a bunch of parameters that will come from the environment variables.
        You will configure these environment variables in a moment.
      • the pac org who will print information about the current environment and currently authenticated user. This information is useful to verify the connection was successful.
      • lastly, the pac paportal upload command will upload your portal

Note: Microsoft Power Platform CLI is only supported on Windows.

Before saving, click on the Variables button and enter the following environment variables:

  • PacAuthProfileName: this environment variable doesn't really matter as it isn't used apart from creating the profile. Give this a meaningful name for your authentication profile.
  • PowerPlatformAadApplicationId: Enter the other ID you took note of earlier from your AAD App Registration that was labeled as Application (client) ID.
  • PowerPlatformAadApplicationSecret: Enter the Value from the client secret you created in your AAD App Registration.
    Make sure to check the "Keep this value secret" checkbox as you create this variable.
  • PowerPlatformAadDirectoryId: Enter the ID you took note of earlier from your AAD App Registration that was labeled as Directory (tenant) ID
  • PowerPlatformInstanceUrl: This is the URL of your Dynamics CRM instance. You can find this URL by going to your Power Apps environment and clicking on the settings cog. A pane on the right will appear where you can click on the Session details link.
    This will show a modal with details about your session including the Dynamics CRM URL which you can find after the label Instance url. Copy this URL and paste it into the Server URL back in Azure DevOps.
    Modal of the Power Apps Session details

Hit Save and run and verify everything is working as expected.

Summary #

In this tutorial, you learned how to 

  • Create an Azure Active Directory App Registration and linked it to a Dynamics CRM user.
  • Used the App Registration to allow Azure DevOps to connect to your Power Apps environment as the Dynamics CRM user you created.
  • Create an Azure pipeline to install the Power Platform CLI and then use the CLI to upload your portal. 

Of course, everyone's source control structure is different and your process for deploying portals to Power Apps may also be different.
Hopefully, this is a useful reference for you to build your own process.

Related Posts

Related Posts

Azure Pipelines and Power Apps logo

How to deploy Power Apps Solutions using Azure Pipelines

- Dynamics
Learn how to automatically deploy Power Apps solutions using the Power Platform Build Tools and Azure DevOps.
CRM and PowerShell logo

Use PowerShell to communicate with Dynamics CRM using the .NET XRM SDK

- Dynamics
If you've developed client applications or plugins for Dynamics CRM before, you are familiar with the CRM/XRM DLL's. You may have gotten those DLL's from the CRM installation, the SDK zip, or the NuGet package. Another way to interact with the CRM DLL's is through PowerShell. PowerShell is built upon .NET meaning you can call exactly the same CRM libraries from PowerShell as from .NET applications.
CRM and PowerShell logo

PowerShell snippet: Get optionset value/labels from Dynamics CRM Entity/Attribute

- Dynamics
Instead of having to use the CRM interface to copy all the labels and values manually, you can save yourself a lot of time using this PowerShell script. Using the following script file named "GetOptionSet.ps1", you can list all the value/label pairs for a given Entity + OptionSet-Attribute:
.NET Bot, Azure, and Discord are together in a Discord server

How to create a Discord Bot using the .NET worker template and host it on Azure Container Instances

- Azure
Learn how to develop a Discord bot using the .NET worker template, containerize it using Docker, push the container image to Azure Container Registry, and host it on Azure Container Instances.
MS Paint drawn Cloudflare logo

Setting up Cloudflare Full Universal SSL/TLS/HTTPS with an Azure App Services

- Azure
Using Cloudflare's Universal SSL/TLS service, we can provide our website over a safe HTTPS connection. This post walks you through setting up the SSL/TLS encrypted connection from client to Cloudflare, to your Azure Web Application using the Full (strict) option and Cloudflare's origin certificates.