Naeem Sarfraz

Blogging about Enterprise Architecture, ALM, DevOps & happy times coding in .Net

Release Management 2015: Copying Failed for Robocopy, Component Name Must Match Artifact Name

Overnight we upgraded our on-premise TFS 2015 installation applying Update 3 and this morning I came in to find all our overnight builds failed. Our overnight CI builds, trigger a release in Release Management deploying the latest version of our applications to our dev environment. The problem lay with the Release Management upgrade (Release Management Client for Visual Studio 2015 Update 3).

Release Management reported the following error.

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> Microsoft.TeamFoundation.Release.Common.Helpers.OperationFailedException: Deployment started on
target machine...

System.AggregateException: Failed to execute the powershell script. Consult the logs below for
details of the error.
Copying failed. Consult the robocopy logs for more details. ---> System.Management.Automation.RuntimeException:
Copying failed. Consult the robocopy logs for more details. ---> System.Management.Automation.RuntimeException:
Copying failed. Consult the robocopy logs for more details.

2016/07/01 05:03:53 ERROR 2 (0x00000002) Accessing Source Directory \\SERVER\Builds\APPLICATION\1683\Web\Web\
The system cannot find the file specified.

Back to Basics

We have a convention for our TFS builds where using the Publish Artifact Task we’ll organise the contents of the build Artifacts in folders: Web, SQL or App.

image

Each folder in the TFS Build Artifacts will have a one-to-one mapping to a Release Management component similar to this.

image

The Path to package normally points to the root of the TFS Build Artifacts folder and we add the word Web so that the component will look for the deployable bits in this folder. This is the only bit I could link back to the error as I saw robocopy was attempting to copy from a folder path that ended with ..\Web\Web. I quickly setup a new component and played around to come across this error.

ERROR: 0 artifact(s) found corresponding to the name 'vNext-Deploy-DEBUG' for BuildId: 1693.
Rename the component such that it matches uniquely with any of the available artifacts of the
build : SQL, Web.

Fix

Aha. The last error pointed to the fact that your published artifact (top level folders in your TFS Build Artifacts) must match the name of the component defined in Release Management. In fact I found that it doesn’t have to match the name exactly but the component should contain the name of the artifact. A typical example of the name we use is vNext-DeploySalesApp-WebApp. 

The word Web in the Path to package field would explain why it tried to copy files from ..\Web\Web. Now this box cannot be left empty so we replaced it with .\ and normal service is resumed.

P.S. Very soon we’ll be glad to see the back of Release Management in its WPF client form and move all our releases to the new version which runs out of the TFS site. Can’t wait.

Trigger an Agent Release from TFS 2013 Build

You’re using TFS 2013 to build your application continuously, or on a schedule or both giving you feedback on how good your team are doing at integrating their work with one another. Using Release Management (RM) you can deploy your application into your Dev environment, then UAT and finally Production all at the click of a button. This post describes how you can trigger that build from a TFS 2013 build.

How could you use this and why? A product team wants to deploy to a Dev environment on every commit to the central repository. This environment is used by the developers to test the integration of all of the different components of a product before releasing into UAT. This can be described as Continuous Deployment. If the product has many components to it you may not want to deploy on every commit instead you could deploy daily as a result of a scheduled build e.g. a nightly build.

You can do this by triggering a release from a TFS build by modifying the build process template, used by your build definition, of which there are several:

  • DefaultTemplate.xaml
  • GitTemplate.xaml
  • TfvcTemplate.xaml
  • UpgradeTemplate.xaml

Installing the new build process template

Install RM and new versions of the above templates are installed on your server for you to use. On the server where you have installed RM Server go to C:\Program Files (x86)\ Microsoft Visual Studio 12.0\ReleaseManagement\bin\ where you’ll find the following files:

  • ReleaseDefaultTemplate.xaml – TFS 2010
  • ReleaseDefaultTemplate.11.1.xaml – TFS 2012
  • ReleaseGitTemplate.12.xaml – TFS 2013
  • ReleaseTfvcTemplate.12.xaml – TFS 2013
  • ReleaseUpgradeTemplate.xaml – TFS 2010

You can also find these files on a machine where you have installed the RM client application, the location is C:\Program Files (x86)\Microsoft Visual Studio 12.0\Release Management\Client\bin (just be aware that some have reported the templates in the RM Client directory might not work). The RM client can be downloaded from your MSDN subscription or from here which is a limited trial version. Now add these files to source control by creating a folder called BuildProcessTemplates at the root of your Team Project repository and drop these files into there and commit (or checkin) so the path looks something like (for TFSVS) $/MyTeamProject/BuildProcessTemplates/ReleaseTfvcTemplate.12.xaml.

Capture

Configure your build

Create your new build and select one of the new templates:

image

You’ll want to take note of the following RM-specific properties:

image

  • Configuration to Release – String array, normally set to Any CPU|Release
  • Release Build – Boolean value (true or false), true if you want to trigger the release
  • Release Target Stage – String value, if you set this to the name of one of your RM stages e.g. DEV, PROD if you want to deploy into that enviornment only otheriwse leave blank

The new release process templates trigger RM by making a call to ReleaseManagementBuild.exe, which you’ll get when you install the RM client. This means wherever you have a TFS Build agent installed you will need to have the RM client also installed on that machine.

Trigger a new build and confirm that your release was created and then triggered ReleaseManagementBuild.exe. Using the RM client you should see a new release created.

Modifying an existing build process template

You may have modified one of the default templates or created your own version of it in which case you will want to add the RM capabilities to it. There is a post over at MSDN on the Visual Studio ALM blog that details exactly how to do this.

Runtime Variables in TFS 2015 Build

Following my previous post here is a script which writes out all the TFS 2015 Build variables. These variables are documented here however as you’ll see the names are not quite correct so you should find this script useful.

The end of the script will also dump out all variables (undocumented ones) to the logs too.

Organising your TFS Build Output with GenerateProjectSpecificOutputFolder

When you set TFS to compile your project it will deliver the output of the build into a builds folder. You have three options as to how the output is organised and this is controlled by the Output location option located in your Build process parameters.

  • SingleFolder (default) – All binaries from the build are copied to the specific build folder.
  • PerProject – For each project/solution (and yes you can specify more than one project to build) you’ll find a folder matching the name of the project/solution and all of the binaries for that solution inside that folder.
  • AsConfigured – no binaries are copied therefore you’ll have to use a post build script to copy the files.

Your solution will typically contain more than one project and you might expect choosing PerProject will create a set of directories that match your projects. Not quite.

To rectify this you need to add /p:GenerateProjectSpecificOutputFolder=true to the MSBuild arguments (available in .Net 4.5). Output location should be set to SingleFolder or PerProject, I prefer the latter in case you select a second project in the same build.

Capture

For each project you’ll now see a separate folder like so: {drop number} \ {project name} \ *.dll | *.exe | *.pdb