Last Updated: 5 February 2020
The build pipeline can be greatly enhanced and customized to your organization's needs. Your custom tasks can be as simple as a few lines of Powershell script, or more complicated by creating your own command line utility.
The aim of creating custom build tasks is modularity and re-usability. Breaking up your pipeline like this makes things less fragile, too - perhaps compared to one large mega script.
This demo will show you how to create a custom build task, which uses a Powershell script to call a custom command line utility. The CLI utility gives us great flexibility, but if you can achieve what you need purely with Powershell, then it isn't necessary.
Create the following folder structure:
First task is to create the package definition metadata file task.json, which goes in the Task folder. A good place to start is our full downloadable example. For more info about task.json, check out the task.json schema on Microsoft's GitHub.
You can also add a 32 x 32 png icon in the root of your task folder, which should be named icon.png.
To get the parameters set by the user (as defined in the 'inputs' section is Task.json above), add this snippet to the top of your powershell script. This script also goes in the Task folder, with the same filename set in the 'Execution' property of your task.json file.
param(
[string] $someString,
[string] $anotherString
)
Here is a complete example of a Powershell script that calls the custom CLI tool we are going to write, with the 'someString' and 'anotherString' values:
We are going to create a custom command line tool, which is called by the Powershell script above. The Visual Studio solution file goes in the Command folder, with the rest of the source code and .csproj file in the MyCustomTaskCLI folder underneath.
The first step is to create a .Net console app. You can read the arguments passed in from the Powershell script by parsing the 'args' collection passed into the Main() method. This code snippet will tell you what has been passed in:
static void Main(string[] args)
{
foreach(var arg in args)
{
Console.WriteLine(arg);
}
}
Anything you write to the Console window will end up in the TFS build logs. To ensure TFS can identify if the tool exited correctly, or encountered an error, you need to exit the program with the correct code. This is just a matter of calling Environment.Exit with zero or one, for success or failure respectively.
When you have finished writing your custom CLI tool, build it in Release mode, and copy the contents of the /bin/Release folder to MyCustomTask -> Task -> MyCustomTask folder. This will make sure it gets zipped up along with your task.json and other task artifacts before uploading it to your TFS or DevOps server.
Lots of blogs recommend using TFX to upload your task, however I find it much easier to simply use this UploadBuildTask.ps1 script to upload it directly using the TFS API. The path is that of your task.json file.
.\UploadBuildTask.ps1 "C:\Temp\MyCustomTask\Task" http://your-tfs-server:port/tfs/default
Your new custom build task should now be available to add to your build pipelines. If you need to update the task, don't forget to tick up the version number in task.json. You can download the full example here.
If you or your organization requires assistance with your devops function, including build and deploy with on-premise TFS or Azure DevOps, don't hesitate to contact us.