Trigger a vNext Release from build in TFS 2013/2015 on premise

I always had a lot of problems triggering a release from a build (Vnext or Xaml) on premise if I work with agentless deployments. In the cloud this works like a charm – but on premise it never worked for me. I tried it with the blog post on msdn – but no success.

Today I started to use Fiddler to monitor the api calls that the Release Management Client makes. (BTW: I know now, why the app is so slow if you have limited network bandwidth. The client is really chatty!).

With Fiddler and the Invoke-RestMethod commandlet its quite easy to make the same calls as the client does. If you want to get the id of a releasePath you can execute

$releasePaths = Invoke-RestMethod "$releaseManagementService/ReleaseDefinitionService/ListReleaseDefinitions?api-version=$ApiVersion" -UseDefaultCredentials -Method Post

The result is a XMLDocument that is pretty easy to parse in PowerShell.

$releasePathId = $releasePaths.ApplicationVersionList.ApplicationVersion | ? { $_.Name -eq $ReleasePathName } | % { $_.ReleasePathId }

The most difficult part is to build the property bag for “InitiateRelease”. You can use [URI]::UnescapeDataString() to extract the json from the encoded string.

I’ve build up a script that accepts ReleaseDefinition, ReleasePath and TargetStage as parameters. This is only tested with one solution. You might have to adjust the property bag to your need – especially when you have more components. You can download the script directly from github.

<#
.Synopsis
   Triggers a release from a build for Visual Studio Release Management 2015 on premises
.DESCRIPTION
   Use this script in your builds to trigger a release in Visual Studio Release Management 2015 on premises. 
.EXAMPLE
   .\Start-Release.ps1 -ReleaseDefinition MyReleaseDefinition -ReleasePath MyPath -TargetStage Dev
.EXAMPLE
   .\Start-Release.ps1 -ReleaseDefinition MyReleaseDefinition -ReleasePath MyPath
#>
[CmdletBinding()]
[OutputType([int])]
Param (
        # The name of the release definition
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateNotNullOrEmpty()]
        [string]$ReleaseDefinition,

        # The name of the release path
        [Parameter(Mandatory=$true, Position=1)]
        [ValidateNotNullOrEmpty()]
        [string]$ReleasePathName,

        # The build number. This is automatically set by the build.
        [Parameter(Mandatory=$false, Position=2)]
        [ValidateNotNullOrEmpty()]
        [string]$BuildNumber = $env:TF_BUILD_BUILDNUMBER,

        # The target stage. Adjust the validation set acording to your values 
        # from the Administration / Manage Picklist / Stage Type in RM Client...
        [Parameter(Mandatory=$false, Position=2)]
        [ValidateSet("Dev", "Test", "QA", "Prod", "Last")]
        [string]$TargetStage = "Last",

        # The api version of the rest api. This might change with later updates.
        # Use fiddler to check the version that is used by rm client.
        [string]$ApiVersion = "6.0"
)

# Set the name of your release management server and the port (default 1000)
$serverName = "<your server fqdn>:1000"
$releaseManagementService = "http://$serverName/account/releaseManagementService/_apis/releaseManagement"
    
# Get the ReleasePathId 
$releasePaths = Invoke-RestMethod "$releaseManagementService/ReleaseDefinitionService/ListReleaseDefinitions?api-version=$ApiVersion" -UseDefaultCredentials -Method Post
$releasePathId = $releasePaths.ApplicationVersionList.ApplicationVersion | ? { $_.Name -eq $ReleasePathName } | % { $_.ReleasePathId }
    
# Get the TargetStageId
$releasePath = Invoke-RestMethod "$releaseManagementService/ConfigurationService/GetReleasePath?id=$releasePathId&api-version=$ApiVersion" -UseDefaultCredentials -Method Post
$stages = $releasePath.ReleasePath.Stages.Stage

if ($TargetStage -ne "Last") {
    $targetStageId = $stages | ? { $_.StageTypeName -eq "Dev" } | % { $_.Id }
}else {
    $targetStageId = $stages | Select-Object -Last 1 | % { $_.Id }
}
    
# Create the release name
$releaseName = "Release: $(Get-Date -Format G)"

# Create the property bag
$deploymentPropertyBag = "{""ReleaseName"" : ""$releaseName"",""ReleaseBuild"": ""$BuildNumber"",""ReleaseBuildChangeset"" : """",""TargetStageId"": ""$targetStageId"",""ProviderHostedApp:Build"" : """",""ProviderHostedApp:BuildChangesetRange"" : ""-1,-1""}"
$propertyBag = [System.Uri]::EscapeDataString($deploymentPropertyBag)

$uri = "$releaseManagementService/OrchestratorService/InitiateRelease?releaseTemplateName=$releaseDefinition&deploymentPropertyBag=$propertyBag&api-version=6.0"
    
$result = Invoke-RestMethod -Uri $uri -Method Post -UseDefaultCredentials

if ($result.ErrorMessage) {
    throw $result.ErrorMessage
}

return $result

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s