Autoincrementing and Deploying Dataverse Plugin Package
How to Automate Incrementing and Deploying Dataverse Plugin Packages
First things first, this isn’t an article for how to setup an ALM process. It’s for local dev, when you want to quickly build and deploy change with the minimal clicks possible. With that out of the way, lets get started:
Microsoft recently introduced the ability to create Dataverse Plugin Packages that allow for including dependent assemblies. This can cause some annoyances when having to deploy changes to dev for testing, because each time the plugin package nuget file is built, it gets a new assembly version in the name, and uploading it to Dataverse via the Plugin Registration Tool, requires that the package be selected to upload. This causes quite a few extra clicks which can be removed by this semi-hacky work around.
How It Works
- In Visual Studio, the process is started by triggering the building of Plugin project in DevDeploy mode
- Via a property, the csproj skips generating a the nuget package
- An MS Build Target parses the FileVersion property, incrementing the in-memory revision of the version of the property by one ie <FileVersion>1.5.12.24</FileVersion> is updated to <FileVersion>1.5.12.25</FileVersion>. This does not actually update the file csproj file itself though, which is handled by the next step
- A Post-Build Event runs that:
- Calls an exe to update the FileVersion in the csproj file
- Deletes old nupkg files
- Runs dotnet pack in the to create the nuget package, and since the csproj FileVersion has been updated, it will get the correct version
- Runs the PAC CLI to select the correct Auth for the Org
- Runs The PAC CLI to push the plugin
How to Implement
Prerequisites:
- Visual Studio contains a Plugin Project using the newer "Microsoft.NET.Sdk" csproj format that successfully builds a Plugin Package nupkg file.
- The PAC CLI has been installed, and the PAC AUTH has been run to create an Auth Connection, and a Name has been assigned.
- The Plugin Package has already been built and deployed to the Dataverse Instance, and the PackageId has been recorded
- Downloaded, unblocked, and extracted the VersionUpdater to a “VersionUpdater” folder in the directory of the solution (Changes to where this is located will result in changes in the Post Build script in Step 4). This tool will accept a command line argument of the csproj path so it can find the file version and update it.
Step 1: Create DevDeploy Build Configuration
- Right click on the solution file.
- Select Properties
- Click the Configuration Button
- In the “Active solution configuration” drop down select <New>
- Enter a name of DevDeploy
- Select to “Copy settings from” Release
- Ensure “Create new project configurations” is checked.
- Click OK to create the new DevDeploy solution build configuratoin
Step 2: Edit the Plugin’s csproj file
Add a Property group in the Plugin’s csproj (Prerequisite 1) with the following values:
- DeploymentConfigurationName: The Solution configuration to use to build the plugin that gets deployed.
- DeploymentOutDir: The project relative path to the Deploymnet Configuration’s output directory. Should always be bin\$(DeploymentConfigurationName)\
- DeploymentPacAuthName: The name of the deployment Auth to use (Prerequisite 2)
- GeneratePackageOnBuild: Set to false. Prevents the default building of the Nuget Plugin Package until after the version has been incremented. This should also increase build times
- PluginPackageId: The GUID of the plugin package (Prerequisite 3)
Add a Target to Update the value of FileVersion so the plugin assembly is built with the new version. The end result should be the following items added to the csproj:
<!-- Plugin Package Deployment Settings -->
<PropertyGroup>
<DeploymentConfigurationName>Release</DeploymentConfigurationName>
<DeploymentOutDir>bin\$(DeploymentConfigurationName)\</DeploymentOutDir>
<DeploymentPacAuthName>Acme Dev</DeploymentPacAuthName>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<PluginPackageId>2b66504a-f03e-ef11-8409-7c1e520b27e1</PluginPackageId>
</PropertyGroup>
<!-- Updates the File Version in memory so that the plugin dll is built with the correct version. Apparently msBuild already has an in memory version of the cs proj, and updating the file as a pre build won't update the assembly version -->
<Target Name="IncrementFileVersion" BeforeTargets="PrepareForBuild" Condition="'$(Configuration)' == 'DevDeploy'">
<PropertyGroup>
<FileVersionRevisionNext>$([MSBuild]::Add($([System.String]::Copy($(FileVersion)).Split('.')[3]), 1))</FileVersionRevisionNext>
<FileVersion>$([System.String]::Copy($(FileVersion)).Split('.')[0]).$([System.String]::Copy($(FileVersion)).Split('.')[1]).$([System.String]::Copy($(FileVersion)).Split('.')[2]).$(FileVersionRevisionNext)</FileVersion>
</PropertyGroup>
<Message Text="Setting Plugin Assembly FileVersion to: $(FileVersion) " Importance="high" />
</Target>
Step 3 Set the Post Build Script
- Right click on the Plugin’s csproj file in Visual Studio
- Select Properties
- Copy and paste the following build text into the “Post-build event” script
if $(ConfigurationName) == DevDeploy (
echo Incrementing Version '$(SolutionDir)VersionUpdater\VersionUpdater.exe Increment --project $(ProjectPath)'
"$(SolutionDir)VersionUpdater\VersionUpdater.exe" Increment --project "$(ProjectPath)"
echo Deleting old nupkg file del "$(ProjectDir)$(DeploymentOutDir)*.nupkg" /q
del "$(ProjectDir)$(DeploymentOutDir)*.nupkg" /q
echo dotnet pack $(ProjectPath) --configuration $(DeploymentConfigurationName) --output "$(ProjectDir)$(DeploymentOutDir)"
dotnet pack $(ProjectPath) --configuration $(DeploymentConfigurationName) --output "$(ProjectDir)$(DeploymentOutDir)"
echo Switching To "$(DeploymentPacAuthName)" Auth Connection
PAC auth select -n "$(DeploymentPacAuthName)"
echo *** Pushing Plugin ***
echo PAC plugin push -id $(PluginPackageId) -pf "$(ProjectDir)$(DeploymentOutDir)$(TargetName).$(FileVersion).nupkg"
PAC plugin push -id $(PluginPackageId) -pf "$(ProjectDir)$(DeploymentOutDir)$(TargetName).$(FileVersion).nupkg"
)
Step 4 Deploy!
- Select the Visual Studio Build Configuration of DevDeploy.
- Build the Plugin Project
- Watch the Build Output for any errors or a successful deployment message:
Build started at 11:30 AM...
1>------ Build started: Project: Acme.Dataverse.Plugin, Configuration: DevDeploy Any CPU ------
1>Setting Plugin Assembly FileVersion to: 1.0.1.79
1>Acme.Dataverse.Plugin -> C:\_dev\Acme\Acme.Dataverse.Plugin\bin\DevDeploy\Acme.Dataverse.Plugin.dll
1>Incrementing Version 'C:\_dev\Acme\CodeGeneration\VersionUpdater.exe Increment --project C:\_dev\Acme\Acme.Dataverse.Plugin\Acme.Dataverse.Plugin.csproj'
1>Updating Version from 1.0.1.78 to 1.0.1.79.
1>Deleting old nupkg file del "C:\_dev\Acme\Acme.Dataverse.Plugin\bin\Release\*.nupkg" /q
1>dotnet pack C:\_dev\Acme\Acme.Dataverse.Plugin\Acme.Dataverse.Plugin.csproj --configuration Release --output "C:\_dev\Acme\Acme.Dataverse.Plugin\bin\Release\"
1>MSBuild version 17.9.8+610b4d3b5 for .NET
1> Determining projects to restore...
1> Restored C:\_dev\Acme\Acme.Dataverse.Plugin\Acme.Dataverse.Plugin.csproj (in 564 ms).
1> 1 of 2 projects are up-to-date for restore.
1> Acme.Dataverse -> C:\_dev\Acme\Acme.Dataverse\bin\Release\Acme.Dataverse.dll
1> Acme.Dataverse.Plugin -> C:\_dev\Acme\Acme.Dataverse.Plugin\bin\Release\Acme.Dataverse.Plugin.dll
1> Acme.Dataverse.Plugin -> C:\_dev\Acme\Acme.Dataverse.Plugin\bin\Release\publish\
1> The package Acme.Dataverse.Plugin.1.0.1.79 is missing a readme. Go to https://aka.ms/nuget/authoring-best-practices/readme to learn why package readmes are important.
1> Successfully created package 'C:\_dev\Acme\Acme.Dataverse.Plugin\bin\Release\Acme.Dataverse.Plugin.1.0.1.79.nupkg'.
1>Switching To "Acme Dev" Auth Connection
1>New default profile:
1> * UNIVERSAL Acme Dev : [email protected] Public https://acme-dev.crm.dynamics.com/
1>
1>*** Pushing Plugin ***
1>PAC plugin push -id 2b66504a-f03e-ef11-8409-7c1e520b27e1 -pf "C:\_dev\Acme\Acme.Dataverse.Plugin\bin\Release\Acme.Dataverse.Plugin.1.0.1.79.nupkg"
1>Connected as [email protected]
1>Connected to... Acme Dev
1>
1>Updating plug-in package C:\_dev\Acme\Acme.Dataverse.Plugin\bin\Release\Acme.Dataverse.Plugin.1.0.1.79.nupkg
1>
1>Plug-in package was updated successfully
1>Acme.Dataverse.Plugin -> C:\_dev\Acme\Acme.Dataverse.Plugin\bin\DevDeploy\publish\
1>Done building project "Acme.Dataverse.Plugin.csproj".
========== Build: 1 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
========== Build completed at 11:31 AM and took 22.547 seconds ==========
Enjoy not having to manually deploy!
Published on:
Learn moreRelated posts
PowerFx Formatting If Statement Idiosyncrasies
Disclaimer: This entire blog is an opinion, and opinions are like butts, we all have one. This is not doctrinal truth that must be obser...
Separating Plugin Logic: A Guide to Testing Dataverse Plugins with IOC
I’m not a pure TDD developer. I frequently take my best guess at a Dataverse plugin, then apply TDD until everything works. This c...
How to Filter Dates in Canvas Apps Using Greater Than/Less Than Operators
Defining the ProblemRecently I was attempting to filter an on-premise SQL table by a DateTime field using a “greater than” operator, and displ...
Enabling or Disabling All Plugin Steps In Dataverse
If you are facing an issue with a recent bug in PowerPlatform.BuildTools version 0.0.81 that caused your plugin steps to become disabled, fret...
There And Back Again, A Tale Of Three Jobs, Six Months, And Never Leaving The Building
This post is about a person's experience of changing jobs three times over six months without physically leaving the building, which started w...
GetClientContext Is Not Defined When Navigating Back To WebResource Html File
If you are experiencing "GetClientContext is not defined" error when navigating back to a custom WebResource in CRM Entity, then this tutorial...
Pick a Mountain, Any Mountain
Mountains may seem like just larger-than-average piles of dirt and rock, but they can do extraordinary things in an individual's life. In this...
How to Add a Spacer to a CRM Business Process Flow
If you're working with CRM Business Process Flows and have been searching for a way to include blank spaces, this tutorial has got you covered...
An Evening with Me and #XRMToolbox Development
If you're interested in XrmToolBox development, you might enjoy joining "An Evening with Me and #XRMToolbox Development." This is a virtual ev...
Learn All the Shortcuts!!!
If you're a Visual Studio user, you might want to check out the Learn the Shortcut extension by Mads Kristensen. It's a simple tool that outpu...