Build and deploy a PCF control using Azure DevOps

Image of the author

Ryan Spain

Cover image for the article.

Overview

In this post, Iā€™ll describe how you can use Azure DevOps build and release pipelines to build your PCF control from source control and deploy it to a Power Apps environment. Iā€™ll be building a single PCF control and only deploying to one environment, but this process can be expanded to handle multiple PCF controls and deploy across many environments
Todo

Creating the build pipeline

From the pipelines area of your Azure DevOps project, select theĀ Create pipelineĀ button. Iā€™m not a fan of using YAML so I choose to clickĀ Use the classic editorĀ at the bottom of the page.
Next, let the pipeline know where your PCF control source is - my control source code is in GitHub so Iā€™ve provided an existing connection, specified the repository, and branch. On the next step, select theĀ Empty jobĀ link instead of using one of the suggested templates.
Todo
Feel free to forkĀ the same repositoryĀ if your following along. It was the result ofĀ thisĀ blog post.

Adding build tasks

The idea here is that we are going to add tasks to our empty agent pool that simulate actual tasks that you (a human), would perform to build the source code locally on your machine.

1. Install required NPM packages

This task should be familiar for most (as should allā€¦ Iā€™ll say no more). On your PC you runĀ npm installĀ from your projectsĀ package.jsonĀ directory to download the required node modules into theĀ šŸ“node_modulesĀ folder. We;ll use theĀ npmĀ task for this and target the šŸ“src/project.
Todo
Task:Ā npm
Command:Ā install
Working folder that contains package.json:Ā src/project

2. Build the solution

Awesomely, Power Apps Component Framework controls can be packaged into a Power Apps solution using MSBuild. We just need to target theĀ cdsprojĀ file which references our PCF controls. Weā€™ll use the MSBuild pipeline task.
Todo
Task:Ā MSBuildProject:Ā **/*.cdsprojĀ 1
MSBuild Arguments:Ā /t:build /restore /p:configuration=ReleaseĀ 2
Diana Birkelbach does a good solution size comparison overĀ hereĀ on her blog.

3. Install Power DevOps Tool Installer

I useĀ Power DevOpsĀ tools by Wael Hamze for Power Apps related ALM. Make sure you have that extension installed in your Azure DevOps organization, then add the below task to the agent pool. No properties need to be set for this task.
Todo
Task:Ā Power DevOps Tool Installer

4. Extract the solution

We need to extract the contents of the solution we built using MSBuild so we can perform some actions on it. For this weā€™ll use theĀ Extract SolutionĀ task provided by the extension installed previously. We let this task know what solution ZIP file we want to extract, and where we want it extracted.
Todo
Task:Ā Extract Solution
Unpacked Files Folder:Ā $(Build.ArtifactStagingDirectory)/SolutionExtracted
Solution File:Ā src/solution/bin/Release/solution.zip

5. Set the solution version

Weā€™ll use the build number to set the solution version for the unpacked solution files. Again, using a task provided by Power DevOps, namedĀ Set Version.
Todo
Task:Ā Set Version
Target:Ā Unpacked Solution Customizations
Unpacked Files Folder:Ā $(Build.ArtifactStagingDirectory)/SolutionExtractedĀ 
Version Number:Ā 1.0.0.$(Build.BuildNumber)

6. Set the PCF control version

This is a little tricky as there is no Azure DevOps task as of yet to update the version attribute on the PCF control node of the manifest file. I settled on writing my own PowerShell function to accomplish this. It set the build number portion of the controls version to the current build number of the pipeline.
function PCF-IncreaseControlBuildNumber($manifestFilePath){

	# Read in XML file
	$xml = [xml](Get-Content $manifestFilePath)
	
	# Get current control version
	$controlVersion = [version]$xml.SelectSingleNode("/manifest/control").version
	
	# Build the new control version
	$newControlVersion = "{0}.{1}.{2}" -f $controlVersion.Major, $controlVersion.Minor, $(Build.BuildNumber)
	
	# Set the new control version
	$xml.SelectSingleNode("/manifest/control").version = $newControlVersion
	
	# Save the updated XML
	$xml.Save($manifestFilePath)
}
PCF-IncreaseControlBuildNumber("$(Build.ArtifactStagingDirectory)/SolutionExtracted/Controls/rsnet_RyanSpain.NET.TextInputControl/ControlManifest.xml")
Todo
Task:Ā PowerShell
Type:Ā Inline
Script:Ā As above and ensure you update with the path your your manifest file

7. Pack the solution

With the solution and PCF control versions set, we can pack the solutions contents using theĀ Pack SolutionĀ task. Weā€™ll tell this task where the solution contents are, and where to place the packed solution ZIP once finished.
Todo
Task:Ā Pack Solution
Unpacked Files Folder:Ā $(Build.ArtifactStagingDirectory)/SolutionExtracted
Package Type:Ā Unmanaged
Output Path:Ā $(Build.ArtifactStagingDirectory)/SolutionPacked

8. Publish solution artifact

In order for the release pipeline to have something to release, we need to publish our packed solution ZIP as a build artifact.
Todo
Task:Ā Publish build artifacts
Path to publish:Ā $(Build.ArtifactStagingDirectory)/SolutionPacked
Artifact name:Ā Solution

šŸ§Ŗ Test the build pipeline

Queue the build pipeline, resolve any errors, and wait for it to complete. It should take about 2 minutes and the resulting build artifact should resemble the below.
Todo

Creating the release pipeline

FromĀ Pipelines > Releases, create a new pipeline using theĀ Empty jobĀ template. Give the default stage a name like development or build. Again, Iā€™ll only be deploying to one environment so there will only be one stage in this release pipeline.
Next, use theĀ Add an artifactĀ card and select the build pipeline as theĀ Source. I like to update theĀ Source aliasĀ too while Iā€™m here - I set it toĀ _Build. Finally, give your release pipeline a meaningful name.
Todo
Artifact Source:Ā Build pipeline from
Default version:Ā Latest
Artifact Source alias:Ā _Build

Adding release tasks

This is as simple as just importing the solution ZIP from our build pipeline artifact. Again, weā€™ll being using the Power DevOps tools so make sure you have that installed in your organization.

1. Install Power DevOps Tool Installer

Open out the stage tasks and add theĀ Power DevOps Tool InstallerĀ to the agent pool. There is no configuration required here.
Todo
Task:Ā Power DevOps Tool Installer

2. Import solution

Finally, we use theĀ Import SolutionĀ task to import the build solution into our Power Apps environment. We just need to provide a connection string and the location of our solution ZIP file.
Todo
Task:Ā Import Solution
Connection String:Ā Using your preferred authentication type
Solution File:Ā $(Release.PrimaryArtifactSourceAlias)\Solution\TextInputControl.zip

šŸ§Ŗ Test the release pipeline

Save your release pipeline and create a new release based on the successful build pipeline. Wait for the release tasks to complete, and once successful, the solution file will have imported into the target environment.
Todo

Variables

Throughout this guide, I reused the same string configuration properties for some of the build and release tasks. Some if not all of these string properties are excellent candidates for pipeline variables. In the interest of keeping things clear (I hope), I didnā€™t create any custom variables. The variable structure Iā€™ve used for my past 3 PCF controls has evolved into the below.
Todo
As you can probably tell, there is little duplication in strings. However one could argue it can be a little hard to follow, or update!