1

I would like to perform the following steps in the TFS build process:

  • do post build event that will copy some files from my compiled projects to another predefined directory, I'd like that directory path to include the branch name.
  • I'd like to be able to refer to the branch name inside my xaml workflow template as well.
jessehouwing
  • 106,458
  • 22
  • 256
  • 341
MOses
  • 71
  • 9
  • 1
    TFVC or Git? Which TFS version? Which Team Build version? – jessehouwing Jun 14 '15 at 13:10
  • You tagged MsBuild, but I suspect that's not what you want based on your actual question. Just to be sure, do you want to solve this in the Build workflow or as a post-build action in your project file? – jessehouwing Jun 14 '15 at 13:21
  • 1. TFVC 2013. actually we're using both capabilities. we have our post build events written in most of our projects, and we also use some workflow activities when server build is performed. what i'm looking after is simple: i'd like to be able to use $(branchName) in my post build event in visual studio just to include the branch within the folder name. then, from the workflow side, i need to create this directory in the server. – MOses Jun 15 '15 at 05:56

1 Answers1

2

The first one is rather simple. When you're using the new TFS 2013 build server and process template, you can simply add a post-build powershell script in the Build Definition Configuration, check in the script and run it during the build.

The second one is dependent on whether you're using TFVC or Git, in the first case, use the VersionControlServer class to query the BranchObjects, then check which one is the root for your working folder. Be aware though, that in TFVC multiple branches can be referenced in one workspace, so there may be multiple answers to this query, depending on which file you use the find the branchroot. A custom CodeActivity would do the trick, similar to this check in a custom checkin policy.

The code will be similar to:

 IBuildDetail buildDetail = context.GetExtension<IBuildDetail>();

 var workspace = buildDetail.BuildDefinition.Workspace;
 var versionControlServer = buildDetail.BuildServer.TeamProjectCollection.GetService<VersionControlServer>();

 var branches = versionControlServer.QueryRootBranchObjects(RecursionType.Full);
 var referencedBranches = listOfFilePaths.GroupBy(
                file =>
                branches.SingleOrDefault(
                     branch => file.ServerItem.StartsWith(branch.Properties.RootItem.Item)
                )
            ).Where(group => group.Key != null);

To get a list of all items in yo workspace, you can use Workspace.GetItems.

In case you're using Git, you have a few options as well. The simplest is to invoke the command line:

 git symbolic-ref --short HEAD   

or dive into LibGit2Sharp and use it to find the branch name based on the current working folder from a custom activity.

If you want to include this in an MsBuild task, this may well be possible as well. It goes a bit far for this answer to completely outline the steps required, but it's not that hard once you know what to do.

Create a custom MsBuild task that invokes the same snippet of code above, though instead of getting access to the workspace through BuildDetail.BuildDefinition.Workspace, but through the WorkStation class:

Workstation workstation = Workstation.Current;
WorkspaceInfo info = workstation.GetLocalWorkspaceInfo(path);
TfsTeamProjectCollection collection = new TfsTeamProjectCollection(info.ServerUri);
Workspace workspace = info.GetWorkspace(collection);
VersionControlServer versionControlServer = collection.GetService<VersionControlServer>();

Once the task has been created, you can create a custom .targets file that hooks into the MsBuild process by overriding certain variables or copying data when the build is finished. You can hook into multiple Targets and define whether you need to do something before or after them.

You can either <import> these into each of your projects, or you can place it in the ImportAfter or ImportBefore folder of your MsBuild version to make it load globally. You can find the folder here:

C:\Program Files (x86)\MSBuild\{MsBuild Version}\Microsoft.Common.Targets\ImportAfter
Community
  • 1
  • 1
jessehouwing
  • 106,458
  • 22
  • 256
  • 341
  • thanks. so in-order to include the branch name in the constructed folder path name i need a different script? and how do i centralize each post build event (for each project in my solution) to one file? cos each one uses different paths to copy from/to dll's.... seems a bit complicated.. – MOses Jun 15 '15 at 06:05
  • Mate I have to create a script that creates a tag on the built git repository, i.e. : If the build runs, it tags the commit with the version. I think I can use a post-build script but not sure how to use your advice above! – Hangarter Jun 19 '15 at 10:16
  • @jessehouwing , thx so much for your detailed information. sadly, i'm not sure that this targets what i'm looking for. so i'll try again : As i explained in the original post, my goal is to include the current branch name within my projects post build event actions. e.g - a post build event that will copy all binaries. (xcopy c:\workspace\$(branchName)\$(projectName)\*.* )c:\targetFolder. can you please help me figure this out? – MOses Jul 22 '15 at 06:24
  • You'll have to do some figuring out for yourself on this. Copying files is very easy using MsBuild tasks, you don't need Xcopy for it. (https://msdn.microsoft.com/en-us/library/3e54c37h.aspx) and I've already shown you how to extract the branch name and pointed to how to wrap that in a custom MsBuild task. Combining the two by calling the custom task to get the name and then the Copy task to copy the files is the easiest part of the problem. – jessehouwing Jul 22 '15 at 08:02
  • Try to build what you need given the information I've already given you and ask new questions, or update this question with more specific questions. Don't ask us to do your work for you. – jessehouwing Jul 22 '15 at 08:03