How to extend MSBuild to execute Unicorn Sync action.

This article is a part of MSBuild series. Here is a list of all articles in this series:

  1. MSBuild basics for Sitecore devs
  2. MSBuild extension points
  3. MSBuild Build and Publish pipelines
  4. How to extend MSBuild publish pipeline to copy content files from all Helix modules to the output.
  5. How to extend MSBuild publish pipeline to apply transform files.
  6. How to extend MSBuild to execute Unicorn Sync action.
  7. VIDEO: Speed comparison of gulp vs MSBuild build & publish.
  8. How to extend MSBuild to copy indirect references.
  9. VIDEO: How to configure local development environment step by step
  10. VIDEO: How to set up Build & Release pipelines on VSTS step by step (the easiest way)
  11. How to extend MSDeploy with custom providers for Unicorn and Transform Files
  12. VIDEO: How to set up Build & Release pipelines on VSTS step by step (to generate WDP package, apply transform files and sync unicorn by MSDeploy)
  13. Helix Publishing Pipeline by Richard Szalay

After Build and Publish it's time to sync items with Unicorn. MSBuild can do that as well and extension is quite simple. Gulps script in Habitat repository, under the hood, executes the power shell script to sync items. The power shell contains a .NET code. We can write a custom Task that executes the same .NET code and new targets file that tells MSBuild how to use it.

I put that Task and targets file into the Unicorn.MSBuild nuget package. When we install it in our WebRoot project, MSBuild automatically imports targets file from a package (similar like with the SlowCheetah in the previous article).

I also wrote the Visual Studio plugin that adds Sync Unicorn button to the Build menu in Visual Studio. Thanks to this you can execute Sync with just two clicks.

Source code for both: the NuGet package and the VS plugin is on my GitHub repositories: Unicorn.MSBuild and SyncUnicorn.

The implementation

Let's create a new ClassLibrary project and then create a new SyncUnicorn class that inherits from Task class (or ToolTask class if you prefer, which is more advanced):  

public class SyncUnicorn : Task
public string ControlPanelUrl { get; set; }

public string SharedSecret { get; set; }

public override bool Execute()

The class has two properties with the Required attribute: ControlPanelUrl and SharedSecret. Our task needs these two properties in order to execute Sync action. The Required attribute makes sure that if we do not provide it, the MSBuild will throw an error. You can see the full source code of SyncUnicorn class here.

Build a project to generate an Unicorn.MSBuild.dll, then create a new Unicorn.MSBuild.targets file and paste the following code:

<Project xmlns="">
<!--Main sync task-->
<UsingTask TaskName="SyncUnicorn" AssemblyFile="$(UnicornMSBuildTaskPath)Unicorn.MSBuild.dll"/> <Target Name="SyncUnicorn">
<SyncUnicorn ControlPanelUrl="$(UnicornControlPanelUrl)" SharedSecret="$(UnicornSharedSecret)" />
</Target> </Project>

It's copied from a NuGet package, that's why the UnicornMSBuildTaskPath property points to a tools folder, inside the package, that holds the Unicorn.MSBuild.dll

Next, there is a UsingTask statement which tells MSBuild what is the class name of the task and what is the path to the assembly. 

The last thing is the definition of a new target named SyncUnicorn. Inside we call our custom task (that has the same name). The values for ControlPanelUrl and SharedSecret are provided from UnicornControlPanelUrl and UnicornSharedSecret properties. We can define values for these properties somewhere in our project, for example in publishing profile, but the most convenient place I think is the WebRoot.wpp.targets file, because it's loaded for each publishing profiles.

<!-- Unicorn Settings -->

How to use it?

If you installed the Visual Studio plugin, then just right click on the WebRoot project and click Sync Unicorn. You can also execute it from a command line like this:

msbuild WebRoot.csproj /t:SyncUnicorn /p:UnicornControlPanelUrl= /p:UnicornSharedSecret=zUcdjtAKn21fEXIqFnrSzUcdjtAKn21fEXIqFnrSzUcdjtAKn21fEXIqFnrS