Build and deploy a PCF control using Azure DevOps
Ryan Spain
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
ā¹ļø Note
Iāll be using an unmanaged solution package type throughout the build pipeline. This is because the resulting solution will only ever be installed in my development/build environment. From there, the PCF controls within can be added to another solution to be exported as managed for deployment to downstream environments.
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.
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.
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.
Task:Ā MSBuildProject:Ā **/*.cdsprojĀ 1
ā¹ļø Note
We are using a wildcard to find ourĀ cdsprojĀ file - my source control only contains one.
MSBuild Arguments:Ā /t:build /restore /p:configuration=ReleaseĀ 2
ā¹ļø Note
TheĀ /restoreĀ argument makes sure the required NuGet packages are fetched whileĀ /p:configuration=ReleaseĀ instructs webpack to run in production mode, reducing the file size of theĀ bundle.js.
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.
Task:Ā Power DevOps Tool Installer
ā¹ļø Note
We could use MicrosoftāsĀ Power Apps build tools for Azure DevOps, however, Iām in favor of Power DevOps simply because its more mature and has support for using a connection string in the tasks.
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.
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.
Task:Ā Set Version
Target:Ā Unpacked Solution Customizations
Unpacked Files Folder:Ā $(Build.ArtifactStagingDirectory)/SolutionExtractedĀ
ā¹ļø Note
Notice we are using the same directory path again. We should probably use variables for this! More on this a little later.
Version Number:Ā 1.0.0.$(Build.BuildNumber)
ā¹ļø Note
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.
Task:Ā PowerShell
Type:Ā Inline
Script:Ā As above and ensure you update with the path your your manifest file
ā¹ļø Note
The initial draft of this post included a reference to a PowerShell function I found overĀ here. However I found an issue with that (that took 2 hours of my life to figure out), and decided to have a go at this myself, without regular expressions! You can check out my pull request on the original sourceĀ hereĀ if your interested.
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.
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.
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.
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.
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.
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.
Task:Ā Import Solution
Connection String:Ā Using your preferred authentication type
Solution File:Ā $(Release.PrimaryArtifactSourceAlias)\Solution\TextInputControl.zip
ā¹ļø Note
SolutionĀ is the name given to the artifact we published in the build pipeline whileĀ TextInputControl.zipĀ is derived from the name I gave my solution in theĀ Solution.xmlĀ in source control.
š§Ŗ 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.
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.
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!