Use a PowerShell script to customize your pipeline
TFS 2018
Note
Microsoft Visual Studio Team Foundation Server 2018 and earlier versions have the following differences in naming:
- Pipelines for build and release are called definitions
- Runs are called builds
- Service connections are called service endpoints
- Stages are called environments
- Jobs are called phases
When you're ready to move beyond the basics of compiling and testing your code, use a PowerShell script to add your team's business logic to your build pipeline. You can run Windows PowerShell on a Windows build agent. PowerShell Core runs on any platform.
You can run Windows PowerShell Script on a Windows build agent.
Push your script into your repo.
Add a PowerShell build task.
Drag the build task where you want it to run.
Specify the name of the script.
Example PowerShell script: version assemblies
Here's an example script to version your assemblies. For the script to run successfully, you'll need to update your build number to use a format with four periods (example: $(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)
). Build number can also be referred to as run number.
You can customize your build number within a YAML pipeline with the name
property.
name: $(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)
pool:
vmImage: windows-latest
steps:
- pwsh: echo $(Build.BuildNumber) //output updated build number
# If found use it to version the assemblies.
#
# For example, if the 'Build number format' build pipeline parameter
# $(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)
# then your build numbers come out like this:
# "Build HelloWorld_2013.07.19.1"
# This script would then apply version 2013.07.19.1 to your assemblies.
# Enable -Verbose option
[CmdletBinding()]
# Regular expression pattern to find the version in the build number
# and then apply it to the assemblies
$VersionRegex = "\d+\.\d+\.\d+\.\d+"
# If this script is not running on a build server, remind user to
# set environment variables so that this script can be debugged
if(-not ($Env:BUILD_SOURCESDIRECTORY -and $Env:BUILD_BUILDNUMBER))
{
Write-Error "You must set the following environment variables"
Write-Error "to test this script interactively."
Write-Host '$Env:BUILD_SOURCESDIRECTORY - For example, enter something like:'
Write-Host '$Env:BUILD_SOURCESDIRECTORY = "C:\code\FabrikamTFVC\HelloWorld"'
Write-Host '$Env:BUILD_BUILDNUMBER - For example, enter something like:'
Write-Host '$Env:BUILD_BUILDNUMBER = "Build HelloWorld_0000.00.00.0"'
exit 1
}
# Make sure path to source code directory is available
if (-not $Env:BUILD_SOURCESDIRECTORY)
{
Write-Error ("BUILD_SOURCESDIRECTORY environment variable is missing.")
exit 1
}
elseif (-not (Test-Path $Env:BUILD_SOURCESDIRECTORY))
{
Write-Error "BUILD_SOURCESDIRECTORY does not exist: $Env:BUILD_SOURCESDIRECTORY"
exit 1
}
Write-Verbose "BUILD_SOURCESDIRECTORY: $Env:BUILD_SOURCESDIRECTORY"
# Make sure there is a build number
if (-not $Env:BUILD_BUILDNUMBER)
{
Write-Error ("BUILD_BUILDNUMBER environment variable is missing.")
exit 1
}
Write-Verbose "BUILD_BUILDNUMBER: $Env:BUILD_BUILDNUMBER"
# Get and validate the version data
$VersionData = [regex]::matches($Env:BUILD_BUILDNUMBER,$VersionRegex)
switch($VersionData.Count)
{
0
{
Write-Error "Could not find version number data in BUILD_BUILDNUMBER."
exit 1
}
1 {}
default
{
Write-Warning "Found more than instance of version data in BUILD_BUILDNUMBER."
Write-Warning "Will assume first instance is version."
}
}
$NewVersion = $VersionData[0]
Write-Verbose "Version: $NewVersion"
# Apply the version to the assembly property files
$files = gci $Env:BUILD_SOURCESDIRECTORY -recurse -include "*Properties*","My Project" |
?{ $_.PSIsContainer } |
foreach { gci -Path $_.FullName -Recurse -include AssemblyInfo.* }
if($files)
{
Write-Verbose "Will apply $NewVersion to $($files.count) files."
foreach ($file in $files) {
$filecontent = Get-Content($file)
attrib $file -r
$filecontent -replace $VersionRegex, $NewVersion | Out-File $file
Write-Verbose "$file.FullName - version applied"
}
}
else
{
Write-Warning "Found no files."
}
Example PowerShell script: access REST API
In this example, you'll use the SYSTEM_ACCESSTOKEN
variable to access the Azure Pipelines REST API.
You can use $env:SYSTEM_ACCESSTOKEN
in your script in a YAML pipeline to access the OAuth token.
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/definitions/$($env:SYSTEM_DEFINITIONID)?api-version=5.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers @{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
FAQ
What variables are available for me to use in my scripts?
You can use predefined variables in your scripts. For more information on available variables and how to use them, see Use predefined variables.
How do I set a variable so that it can be read by subsequent scripts and tasks?
To learn more about defining build variables in a script, see Define and modify your build variables in a script.
To learn more about defining release variables in a script, see Define and modify your release variables in a script
Which branch of the script does the build run?
The build will use the active branch of your code. If your pipeline run uses the main
branch, your script will also use the main
branch.
What kinds of parameters can I use?
You can use named parameters. Other kinds of parameters, such as switch parameters, aren't supported. You'll see errors if you try to use switch parameters.
I use TFS on-premises and I don't see some of these features. Why not?
Some of these features are available only on Azure Pipelines and not yet available on-premises. Some features are available on-premises if you have upgraded to the latest version of TFS.