TFS 2015 Update 2 RC1 Available – With VS Release Management vNext

Today Brian Harry announced that the first release of TFS 2015 Update 2 is available. It is an RC with a go-live license, which means that Microsoft will support you if you install it in production, and it will be a direct supported upgrade to RTM once it is released.

Read the full release notes for Update 2 RC1 here: https://www.visualstudio.com/en-us/news/tfs2015-update2-vs

 

One huge thing with the release is that Update 2 includes the new Release Management vNext feature that has up until now only been available in the service (although you can use that for on premise TFS and deployments). But now you don’t have to rely on VSTS for hosting the service, it is now part of TFS 2015 Update 2!

 

And of course, if you want to learn (a lot) more about hwo to implement continuous delivery using TFS 2015, with the new build and release management features, grab a copy of our latest book on the topic, Continuous Delivery with Visual Studio ALM 2015:

 

book

Deploy Azure Web Apps with Parameterization

I have blogged before about how to deploy an Azure Web App using the new build system in TFS 2015/Visual Studio Team Services. In addition to configure an Azure service endpoint, it is really only a matter of using the built-in Azure Web App Deployment task.

However, in many cases I have decided not to use this task myself since it has been lacking a key feature: Applying deployment parameters using the SetParameter.xml file.

As I have mentioned a gazillion times, building your binaries once and only once is a key principle when implementing continuous delivery. If you are using web deploy for deploying web applications (and you should), you must then use Web Deploy parameters to apply the correct configuration values at deployment time.

 

Under the hood the Azure Web App Deployment  task uses the Publish-AzureWebsiteProject cmdlet that uses web deploy to publish a web deploy package to Microsoft Azure. Up until recently, this cmdlet did not support web deploy parameters, the only thing that you could substitute was the connecting string, like so:

Publish-AzureWebsiteProject -Name site1 -Package package.zip -ConnectionString @{ DefaultConnection = "my connection string" }

However, it is actually possible to specify the path to the SetParameter.xml file that is generated together with the web deploy package. To do this, you can use the –SetParametersFile parameter, like so:

Publish-AzureWebsiteProject -Name Site1 -Package package.zip -SetParametersFile package.SetParameters.xml

When using the Azure Web App Deployment task, there is no separate parameter for this but you can use the Additional Arguments parameter to pass this information in:

image

Note: In this case, I am using the Azure Web App Deployment task as part of a release definition in Visual Studio Release Management, but you can also use it in a regular build definition.

This will apply the parameter values defined in the QBox.Web.SetParameters.xml file when deploying the package to the Azure Web App.

If you are interested, here is the pull request that implemented support for SetParameters files: https://github.com/Azure/azure-powershell/pull/316

Downloading Build Artifacts in TFS Build vNext

Since a couple of months back, Microsoft new Release Management service is available in public preview in Visual Studio Team Services. According to the current time plan, it will be released for on-premise TFS in the next update (Update 2).

Using a tool like release management allows you to implement a deployment pipeline by grabbing the binaries and any other artifacts from your release build, and then deploy them across different environments with the proper configuration and approval workflow. Building your binaries once and only once is a fundamental principal of implementing continuous delivery, too much can go wrong if you build your application every time you deploy it into a new environment.

 

However, sometimes you might not have the opportunity to setup a release management tool like VSTS or Octopus Deploy, but you still want to be able to build your binaries once and deploy them. Well, you can still implement your deployment using TFS Build, but instead of building your source code during every build we download the artifacts from another build that already has completed.

Let’s look at how we can implement this using PowerShell and the REST API in TFS/VSTS.In this sample we will execute this script as part of a TFS build, in order to create a “poor mans” deployment pipeline. If you want to use the script outside of TFS Build, you need to replace some environment variables that are used in the script below.

Downloading Build Artifacts using PowerShell and the REST API

First of all, to learn about the REST API and other ways to integrate and extend Visual Studio, TFS and Visual Studio Team Services, take a look at https://www.visualstudio.com/integrate. This is a great landing page that aggregate a lot of information about extensibility.

Here is a PowerShell script that implements this functionality, as well as a few other things that is handy if you implement a deployment pipeline from a build definition.

[CmdletBinding()] param( [Parameter(Mandatory=$True)] [string]$buildDefinitionName, [Parameter()] [string]$artifactDestinationFolder = $Env:BUILD_STAGINGDIRECTORY, [Parameter()] [switch]$appendBuildNumberVersion = $false ) Write-Verbose -Verbose ('buildDefinitionName: ' + $buildDefinitionName) Write-Verbose -Verbose ('artifactDestinationFolder: ' + $artifactDestinationFolder) Write-Verbose -Verbose ('appendBuildNumberVersion: ' + $appendBuildNumberVersion) $tfsUrl = $Env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI + $Env:SYSTEM_TEAMPROJECT $buildDefinitions = Invoke-RestMethod -Uri ($tfsURL + '/_apis/build/definitions?api-version=2.0&name=' + $buildDefinitionName) -Method GET -UseDefaultCredentials $buildDefinitionId = ($buildDefinitions.value).id; $tfsGetLatestCompletedBuildUrl = $tfsUrl + '/_apis/build/builds?definitions=' + $buildDefinitionId + '&statusFilter=completed&resultFilter=succeeded&$top=1&api-version=2.0' $builds = Invoke-RestMethod -Uri $tfsGetLatestCompletedBuildUrl -Method GET -UseDefaultCredentials $buildId = ($builds.value).id; if( $appendBuildNumberVersion) { $buildNumber = ($builds.value).buildNumber $versionRegex = "d+.d+.d+.d+" # Get and validate the version data $versionData = [regex]::matches($buildNumber,$versionRegex) switch($versionData.Count) { 0 { Write-Error "Could not find version number data in $buildNumber." exit 1 } 1 {} default { Write-Warning "Found more than instance of version data in buildNumber." Write-Warning "Will assume first instance is version." } } $buildVersionNumber = $versionData[0] $newBuildNumber = $Env:BUILD_BUILDNUMBER + $buildVersionNumber Write-Verbose -Verbose "Version: $newBuildNumber" Write-Verbose -Verbose "##vso[build.updatebuildnumber]$newBuildNumber" } $dropArchiveDestination = Join-path $artifactDestinationFolder "drop.zip" #build URI for buildNr $buildArtifactsURI = $tfsURL + '/_apis/build/builds/' + $buildId + '/artifacts?api-version=2.0' #get artifact downloadPath $artifactURI = (Invoke-RestMethod -Uri $buildArtifactsURI -Method GET -UseDefaultCredentials).Value.Resource.downloadUrl #download ZIP Invoke-WebRequest -uri $artifactURI -OutFile $dropArchiveDestination -UseDefaultCredentials #unzip Add-Type -assembly 'system.io.compression.filesystem' [io.compression.zipfile]::ExtractToDirectory($dropArchiveDestination, $artifactDestinationFolder) Write-Verbose -Verbose ('Build artifacts extracted into ' + $Env:BUILD_STAGINGDIRECTORY)

This script accepts three parameters:

buildDefinitionName
This is a mandatory parameter where you can specify the name of the build definition from which you want to download the artifacts from. This script assumes that the build definition is located in the same team project as the build definition in which this script is running. If this is not the case, you need to add a parameter for the team project.

artifactsDestinationFolder
This is an optional parameter that let’s you specify the folder where the artifacts should be downloaded to. If you leave it empty, it will be downloaded to the staging directory of the build (BUILD_STAGINGDIRECTORY)

appendBuildNumberVersion
A switch that indicates if you want to append the version number of the linked build to the build number of the running build. Since you are actually releasing the build version that you are downloading artifacts from, it often makes sense to use this version number for the deployment build. The script will extract a 4 digit version (x.x.x.x) from the build number and then append it to the build number of the running build.

As an example, if the latest release build has the build number MyApplication-1.2.3.4, the build will extract 1.2.3.4 and append this to the end of the build number of the running build.

 

Running the script in TFS Build

Running a PowerShell script in TFS Build is really easy, but I’ll include it here anyway. Typically you will run this script in the beginning of a build in order to get the build artifacts, and then add the tasks related to deploying the artifacts in whatever way that fits.

Add the script to source control and then add a PowerShell task to the build definition and select the script from the repository. Then specify the parameters of the tasks in the argument field

image

Here is a sample argument:

-buildDefinitionName MyApplication.Release –appendBuildNumberVersion

Where MyApplication.Release is the name of the build definition that have produced the build artifacts that we want to release.

Running this script as part of the build will not download the artifacts from the latest successful build of the linked build definition and place them in the staging directory. In addition it will append the version number of the linked build (x.x.x.x) to the end of the running build.

NB: You need to consider where to place this script. Often you’ll want to put this script together with the application that you are deploying, so that they can change and version together.

 

Hope you will find this script useful, le me know if you have any issues with it!

Happy building!


PS: If you want to learn more about implementing Continuous Delivery using Visual Studio Team Services and TFS, grab a copy of my and Mathias Olausson’s latest book “Continuous Delivery with Visual Studio ALM 2015