Craftsman – Automated Plugin Deployment for Power Platform with Azure DevOps

For the Arctic Cloud Developer Challenge, we implemented a fully automated CI/CD pipeline that builds, tests, and deploys our 404ACDC Plugin to Power Platform without any manual intervention. This eliminates the traditional pain points of plugin deployment—no more opening the Plugin Registration Tool, manually uploading DLLs, or risking configuration drift between environments.

Pipeline Architecture

Our pipeline consists of three sequential stages, each depending on the successful completion of the previous one.

The Build Stage restores NuGet packages (including the Dataverse SDK), compiles the solution in Release configuration, runs unit tests, and publishes the plugin assembly as a build artifact. The pipeline triggers automatically whenever code changes are pushed to the main branch in the plugin or test project directories.

As shown in our pipeline configuration, we have set up smart triggering that only runs the pipeline when relevant files change:

trigger:
  branches:
    include:
    - master
    - main
  paths:
    include:
    - 404ACDC_Plugin/**
    - PluginTests/**

The Deploy Stage downloads the build artifacts and uses Microsoft’s official Power Platform Build Tools to push the updated assembly to Dataverse. Before deployment, we run a WhoAmI check to verify our service connection is valid. Here is the core deployment configuration from our pipeline:

- task: PowerPlatformWhoAmI@2
displayName: 'Verify Power Platform Connection'
inputs:
authenticationType: 'PowerPlatformSPN'
PowerPlatformSPN: '$(ServiceConnectionName)'

- task: PowerPlatformUpdatePluginAssembly@2
displayName: 'Update Plugin Assembly'
inputs:
authenticationType: 'PowerPlatformSPN'
PowerPlatformSPN: '$(ServiceConnectionName)'
AssemblyPath: '$(Pipeline.Workspace)/drop/plugin/404ACDC_Plugin.dll'
UpdateAssemblyVersion: true

The Register Steps Stage uses PowerShell and the Microsoft.Xrm.Data.PowerShell module to register or update plugin steps, wiring our code to the appropriate Dataverse messages and entities.

Security Approach

We never store credentials in our pipeline YAML. Instead, we use an Azure DevOps variable group that contains our environment configuration, as referenced in the pipeline:

variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
pluginProjectPath: '404ACDC_Plugin/404ACDC_Plugin.csproj'

- group: PowerPlatform-Variables # Contains ServiceConnectionName, EnvironmentUrl, etc.

The service principal credentials are stored as encrypted secret variables, masked in all pipeline logs. The service principal itself has only the minimum permissions needed to register plugins.

Build and Test Configuration

Our build stage ensures code quality by compiling and running tests before any deployment occurs:

- task: VSBuild@1
displayName: 'Build Solution'
inputs:
solution: '$(solution)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
msbuildArgs: '/p:DeployOnBuild=false'

- task: VSTest@2
displayName: 'Run Unit Tests'
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
testSelector: 'testAssemblies'
testAssemblyVer2: |
**\*test*.dll
!**\*TestAdapter.dll
!**\obj\**

Why This Matters

This approach gives us repeatability (every deployment follows the identical process), auditability (complete history of every pipeline run), speed (deployments that took 15-20 minutes manually now complete in a few minutes), and safety (no exposed credentials, no deploying broken builds).

How we did it

The pipeline YAML in our repository is the actual configuration driving our deployments. Our Azure DevOps project contains the corresponding service connection, variable group, and deployment environment (PowerPlatform-Production) referenced in the pipeline. The stage dependencies ensure we never deploy untested code:

- stage: Deploy
displayName: 'Deploy to Power Platform'
dependsOn: Build
condition: succeeded()

This automated deployment foundation demonstrates that we have applied professional DevOps practices to our Power Platform solution, ensuring reliable and consistent deployments throughout the challenge.