Initiating vNext Releases in Release Management 2015 from TFS Build 2015

Image

March 1, 2023

TFS 2015 has been recently released and it comes with a number of new features including the new build system. If you are not already familiar with the new build system, take a look at some of my previous posts on Introducing TFS Build 2015 and Building Websites in TFS Build 2015. These two posts should get you to the point where you can build your website with TFS Build 2015, but the next question is, how to get it deployed especially where there are multiple environments? For this, Release Management 2015 is the perfect tool.

Release Management 2015 (RM) is a full feature release tool that provides rich integration with TFS 2015. I'll talk about Release Management tool in a number of upcoming posts but for the sake of this post, we are going to talk about the initiating of a release in Release Management. Additionally, Release Management supports two different types of release templates, agent based and vNext. vNext templates utilize PowerShell/DSC instead of a RM Agent. This example is going to focus on initiating a vNext release. There are two primary trigger mechanisms for initiating a release with vNext templates. The first method, "Initiate Release", is for a release from a system other than TFS such as Jenkins . The second method is initiating the release from a TFS build called "Initiate Release from Build".

tfs2015_jenkins_initiaterelease.png

In TFS 2015, XAML build definitions and Build 2015 build definitions are both supported to trigger the release. The XAML builds have out of the box support but are considered legacy builds now. I prefer to use the new build system in TFS 2015. This is task based and includes a number of tasks to perform cross platform builds. Furthermore, the new release management service in VSO will be based on the same task based technology.

PowerShell Script

Even though there are number of tasks in TFS 2015, there isn't an out of the box task for calling RM 2015. However, this can be achieved by calling a simple PowerShell script. The article, Trigger Release from build with Release Management for Visual Studio 2013 Update 3, provided a starting point for my PowerShell script and I have only modified a few areas. Let's take a look at some of the highlights from the file.

The first important section is how the script can retrieve important information about the build from the TFS agent by retrieving the following environment variables. A list of all of the predefined variables can be found here.

$teamFoundationServerUrl = $env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI
$buildDefinition = $env:BUILD_DEFINITIONNAME
$buildNumber = $env:BUILD_BUILDNUMBER
$droplocation = $env:BUILD_DROPLOCATION

These variables are going to be passed to RM 2015 through a URL as query parameters, so any non-supported characters are properly escaped.

$server = [System.Uri]::EscapeDataString($teamFoundationServerUrl)
$project = [System.Uri]::EscapeDataString($teamProject)
$definition = [System.Uri]::EscapeDataString($buildDefinition)
$build = [System.Uri]::EscapeDataString($buildNumber)
$targetStage = [System.Uri]::EscapeDataString($targetStageName)

The Uri is constructed to communicate to RM using the correct port, server, and other parameters.

$serverName = $rmserver ":" $port

$orchestratorService = "http://$serverName/account/releaseManagementService/_apis/releaseManagement/OrchestratorService"

$uri = "$orchestratorService/InitiateReleaseFromBuild?teamFoundationServerUrl=$server&teamProject=$project&buildDefinition=$definition&buildNumber=$build&targetStageName=$targetStage"
"Executing the following API call:`n`n$uri"

The script calls the Orchestration service with the appropriate credentials. The script originally would continue to check the service until the release completed, however, for multistage release pipelines with manual checkpoints, the build would continue to run until it is deployed to all stages, which could be days or longer. I removed this step so it requires monitoring the release through RM.

$wc.Credentials = new-object System.Net.NetworkCredential($username, $password, $domain)

try
{
$releaseId = $wc.DownloadString($uri)

$url = "$orchestratorService/ReleaseStatus?releaseId=$releaseId"

$releaseStatus = $wc.DownloadString($url)

Write-Host -NoNewline "Submitted Release..."

}

Download the full InitiateReleaseFromBuild script.

Add Script to Build Definition

Assuming we have an existing build definition that compiles and packages the website. Edit the build definition and add a PowerShell task to the build definition.

add_powershell_task.png

The PowerShell task asks for two pieces of information, the path and filename to the PowerShell script and any arguments that the script requires.

Script Name = $/Enterprise/BuildTemplates/InitiateReleaseFromBuild.ps1

Arguments = rm2015 1000 Enterprise Test $(deployuser) $(deploypassword) $(deploydomain)

I'll cover setting up a release pipeline with Release Management in a future post. However, there is one thing that we need to configure specifically when using TFS Build 2015 are the Components in Release Management. The artifact name in the TFS Build Definition needs to match the component name in RM 2015 as highlighted below.

artifact_path.png
component_webappdrop.png

Also I found if you repeat the name in the path to package setting, it prevent creating a duplicate local folder and the need to include the name in any of your DSC scripts.

If your artifact name and component name do not match, you will receive a similar error to this. The WebsiteComponents and BuildId will be specific to your configuration.

Message: ERROR: 0 artifact(s) found corresponding to the name 'WebsiteComponents' for BuildId: 168: \r\n\r\n at Microsoft.TeamFoundation.Release.Builds.TfsOnPrem.TfsOnPremBuildSystem.GetBuild(Uri buildSystemUri, String teamProjectName, String buildDefinitionName, String buildNumber, String buildArtifactName) at Microsoft.TeamFoundation.Release.ArtifactRepository.TfsOnPrem.ArtifactRootLocation.TfsBuildOutputArtifactRootLocation.b__1() at Microsoft.TeamFoundation.DevOps.Diagnostics.DiagnosticsPolicyExecutor.Execute[T](Func`1 func, String methodName)

Execute Build to Trigger Release

With everything configured, we can initiate the build form Web Access, watch it compile the application and trigger the release. From within Release Manager, we can verify that that the release was successful.