It really comes handy when you can build your own build tasks. Either for encapsulation, re-usability, or just to look clean in your build definitions (or even as part of Low-Code movement).
You can find some references from Microsoft here. But that’s for VSTS. Here I am going to provide a simple example for TFS on-premises.
First, you need some TFS build modules. Download them from GitHub’s Microsoft/vsts-task-lib
Second, need the command line tool for uploading the package to your TFS server. You can download and install from
npm i -g tfx-cli
Third, create the actual build script file, the one you want this custom task to execute during the build. You can specify parameters which will be passed through the task interface.
[CmdletBinding()]param()
Trace-VstsEnteringInvocation $MyInvocationtry { Import-VstsLocStrings “$PSScriptRoot\Task.json” Import-Module -Name “$PSScriptRoot\ps_modules\Invoke-MsBuild\Invoke-MsBuild.psm1” Import-Module -Name “$PSScriptRoot\ps_modules\MSBuildHelpers\MSBuildHelpers.psm1”
[string] $ProjectFile = Get-VstsInput -Name ProjectFile -Require [string] $OutputPath = Get-VstsInput -Name OutputPath -Require [string] $MSBuildParameters = Get-VstsInput -Name MSBuildParameters [string] $UseDataScripts = Get-VstsInput -Name MSBuildParameters Write-Host “ProjectFile:***$ProjectFile***” Write-Host “OutputPath:***$OutputPath***” Write-Host “MSBuildParameters:***$MSBuildParameters***” $MSBuildParameters = $MSBuildParameters + ” /p:OutputPath=$OutputPath” $SourceDir = (Get-Item $ProjectFile).Directory.FullName Write-Host “SourceDir:***$SourceDir***” ### Build Project file ### if ((Invoke-MsBuild -Path “$ProjectFile” -MsBuildParameters “$MsBuildParameters” -ShowBuildOutputInCurrentWindow).BuildSucceeded -ne $true) { Write-Error “*** ERROR – Build did NOT complete successfully! – $ProjectFile ***” } else { Write-Warning “*** Build completed successfully! – $ProjectFile ***” } ### Copy hand-picked predeploy scripts to BuildOutput folder based on PreDeploy.txt $ScriptDirName = “Scripts\Pre-Deploy” $PreDeployFilename = “$SourceDir\$ScriptDirName\Pre-Deploy.txt” Write-Output “PreDeployFilename:***$PreDeployFilename***” [System.IO.File]::ReadLines($PreDeployFilename) | %{$src=”$SourceDir\$ScriptDirName\$_”; $des=”$OutputPath\$ScriptDirName\$_”; New-Item “$des” -ItemType File -Force; Write-Output “Copy $src”; Copy-Item “$src” “$des” -Force -Recurse} | Out-String | Write-Warning
### Copy hand-picked predeploy scripts to BuildOutput folder based on PostDeploy.txt $ScriptDirName = “Scripts\Post-Deploy” $PostDeployFilename = “$SourceDir\$ScriptDirName\Post-Deploy.txt” Write-Output “PostDeployFilename:***$PostDeployFilename***” [System.IO.File]::ReadLines($PostDeployFilename) | %{$src=”$SourceDir\$ScriptDirName\$_”; $des=”$OutputPath\$ScriptDirName\$_”; New-Item “$des” -ItemType File -Force; Write-Output “Copy $src”; Copy-Item “$src” “$des” -Force -Recurse} | Out-String | Write-Warning } finally { Trace-VstsLeavingInvocation $MyInvocation }
Forth, create a task.json file to define the new custom task.
{
“id”: “XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX”,
“name”: “BuildDatabase”,
“friendlyName”: “Build Database”,
“description”: “Build Database”,
“author”: “My Name”,
“helpMarkDown”: “Build Database”,
“category”: “Build”,
“visibility”: [
“Build”
],
“demands”: [],
“version”: {
“Major”: “0”,
“Minor”: “1”,
“Patch”: “1”
},
“minimumAgentVersion”: “1.95.0”,
“instanceNameFormat”: “Build Database $(message)”,
“inputs”: [
{
“name”: “ProjectFile”,
“type”: “filePath”,
“label”: “Project File”,
“defaultValue”: “”,
“required”: true,
“helpMarkDown”: “Relative path from repo root of the project file.”
},
{
“name”: “OutputPath”,
“type”: “string”,
“label”: “Output Path”,
“defaultValue”: “”,
“required”: true,
“helpMarkDown”: “Path of the Output directory.”
},
{
“name”: “MSBuildParameters”,
“type”: “string”,
“label”: “MSBuild Arguments”,
“defaultValue”: “”,
“required”: false,
“helpMarkDown”: “Additional arguments passed to MSBuild.”
},
{
“name”: “DeployScripts”,
“type”: “string”,
“label”: “Include Pre/Post-Deploy Scripts”,
“defaultValue”: “false”,
“required”: false,
“helpMarkDown”: “If to run pre/post deploy scripts manually without using build action.”
}
],
“execution”: {
“PowerShell3”: {
“target”: “BuildDatabase.ps1”
}
}
}
Fifth (optional), prepare a icon file for showing up on the Build Task list.
Sixth, upload to the server
tfx build tasks upload –task-path .\BuildDatabase –auth-type basic –username <domain\username> –password <password> –service-url http://<tfsserver>:8080/tfs
That’s it. You will then see your custom tasks showing up on the available task list when you try to add build step.
And you can see how the parameters in your build scripts look like at the front end.