Version Control PowerShell Scripts with Visual Studio and Visual Studio Team Services

Posted by Graham Smith on January 6, 20163 Comments (click here to comment)

It's a new year and whilst I'm not a big fan of New Year's resolutions I do try and use this time of year to have a bit of a tidy-up of my working environments and adopt some better ways of working. Despite being a developer who's used version control for years to manage application source code one thing I've been guilty of for some time now is not version controlling my PowerShell code scripts. Shock, horror I know -- but I'm pretty sure I'm not alone. In this post I'll be sharing how I solved this, but first let's take a quick look at the problem.

The Problem

Unless you are a heavyweight PowerShell user and have adopted a specialist editing tool, chances are that you are using the PowerShell ISE (Integrated Script Editor) that comes with Windows for editing and running your scripts. Whilst it's a reasonably capable editor it doesn't have integration points to any version control technologies. Consequently, if you want version control and you want to continue using the ISE you'll need to manage version control from outside the ISE -- which in my book isn't the seamless experience I'm used to. No matter, if you can live without a seamless experience the next question in this scenario is what version control technologies can be used? Probably quite a few, but since Git is the hot topic of the day how about GitHub -- the hosted version of Git that's free for public repositories? Ideal since it's hosted for you and there's the rather nice GitHub Desktop to make things slightly less seamless. Hang on though -- if you are like me you probably have all sorts of stuff in your PowerShells that you don't want being publicly available on GitHub. Not passwords or anything like that, just inner workings that I'd rather keep private. Okay, so not GitHub. How about running your own version of Git server? Nah...

A Solution

If you are a Visual Studio developer then tools you are already likely using offer one solution to this problem. And if you aren't a Visual Studio developer then the same tools can still be used -- very possibly for free. As you've probably already guessed from the blog title, the tools I'm suggesting are Visual Studio (2015, for the script editing experience) and Visual Studio Team Services (VSTS, for version control). Whoa -- Visual Studio supports PowerShell as a language? Since when did that happen? Since Adam Driscoll created the PowerShell Tools for Visual Studio extension is since when.

The aim of this post is to explain how to use Visual Studio and VSTS to version control PowerShell scripts rather than understand how to start using those tools, so if you need a primer then good starting points are here for Visual Studio and here for VSTS. The great thing is that both these tools are free for small teams. If you want to learn about PowerShell Tools for Visual Studio I have a Getting Started blog post with a collection of useful links here. In my implementation below I'm using Git as the version control technology, so please amend accordingly if you are using TFVC.

Implementing the Solution

Now we know that our PowerShell scripts are going to be version controlled by VSTS the next thing to decide is where in VSTS you want them to reside. VSTS is based around team projects, and the key decision is whether you want your scripts located together in one team project or whether you want scripts to live in different team projects -- perhaps because they naturally belong there. It's horses for courses so I'll show both ways.

If you want your scripts to live in associated team projects then you'll want to create a dedicated Git repository to hold the Visual Studio solution. Navigate to the team project in VSTS and then to the Code tab. Click on the down arrow next to the currently selected repository and in the popup that appears click on New repository:

vsts-create-new-git-repo

A Create a new repository dialogue will appear -- I created a new Git repository called PowerShellScripts. You can ignore the Add some code! call to action as we'll address this from Visual Studio.

Alternatively, if you want to go down the route of having all your scripts in one team project then you can simply create a new team project based on Git -- called PowerShellScripts for example. The newly created project will contain a repository of the same name putting you in the same position as above.

The next step is to switch to Visual Studio and ensure you have the PowerShell Tolls for Visual Studio 2015 extension installed. It's possible you do since it can be installed as part of the Visual Studio installation routine, although I can't remember whether it's selected be default. To check if it's installed navigate to Tools > Extensions and Updates > Installed > All and scroll down:

visual-studio-extensions-and-updates-powershell-tools

If you don't see the extension you can install it from Online > Visual Studio Gallery.

With that done it's time to connect to the team project. Still within Visual Studio, from Team Explorer choose the green Plug icon on the menu bar and then Manage Connections, and then Connect to Team Project:

visual-studio-manage-connections

This brings up the Connect to Team Foundation Server dialog which (via the Servers button) allows you to register your VSTS subscription as a ‘server' (the format is https://yoursubscriptionname.visualstudio.com). Once connected you will be able to select your Team Project.

Next up is cloning the repository that will hold the Visual Studio solution. If you are using a dedicated team project with just one Git repository you can just click the Home icon on the Team Explorer menu bar to get the cloning link on the Home panel:

visual-studio-clone-this-repository

If you have created an additional repository in an existing team project you will need to expand the list of repositories and double-click the one you previously created:

visual-studio-select-repository

This will take you directly to the cloning link on the Home panel -- no need to click the Home icon. Whichever way you get there, clicking the link opens up the settings to clone the repository to your local machine. If you are happy with the settings click Clone and you're done.

Solutions, Projects and Files

At the moment we are connected to a blank local repository, and the almost final push is to get our PowerShell scripts added. These will be contained in Visual Studio Projects that in turn are contained in a Visual Studio Solution. I'm a bit fussy about how I organise my projects and solutions -- I'll show you my way but feel free to do whatever makes you happy.

At the bottom of the Home tab click the New link, which brings up the New Project dialog. Navigate to Installed > Templates > Other Project Types > Visual Studio Solutions. I want to create a Blank Solution that is the same name as the repository, but I don't want a folder of the same name to be created which Visual Studio gives me no choice about. A sneaky trick is to provide the Name but delete the folder (of the same name) from the Location text box:

visual-studio-create-blank-solution

Take that Visual Studio! PowerShellScripts.sln now appears in the Solutions list of the Home tab and I can double-click it to open it, although you will need to manually switch to the Solution Explorer window to see the opened solution:

visual-studio-solution-explorer

The solution has no projects so right-click it and choose Add > New Project from the popup menu. This is the same dialog as above and you need to navigate to Installed > Templates > Other Languages > PowerShell and select PowerShell Script Project. At this point it's worth having a think about how you want to organise things. You could have all your scripts in one project, but since a solution can contain many projects you'll probably want to group related scripts in to their own project. I have a few scripts that deal with authorisation to Azure so I gave my first project the name Authorisation.Azure. Additional projects I might need are things like DSC.Azure and ARM.Azure. It's up to you and it can all be changed later of course.

The new project is created with a blank Script.ps1 file -- I usually delete this. There are several ways to get your scripts in -- probably the easiest is to move your existing ps1 scripts in to the project's folder in Windows Explorer, make sure they have the file names you want and then back in Visual Studio right-click the project and choose Add > Existing Item. You should see your script files and be able to select them all for inclusion in the project.

Don't Forget about Version Control!

We're now at the point where we can start to version control our PowerShell scripts. This is a whole topic in itself however you can get much of what you need to know from my Git with Visual Studio 2015 and TFS 2015 blog post and if you want to know more about Git I have a Getting Started post here. For now though the next steps are as follows:

  • In Team Explorer click on the home button then click Changes. Everything we added should be listed under Included Changes, plus a couple of Git helper files.
  • Add a commit comment and then from the Commit dropdown choose Commit and Sync:
    visual-studio-team-explorer-changes
  • This has the effect of committing your changes to the local repository and then syncing them with VSTS. You can confirm that from VSTS by navigating to the Code tab and selecting the repository. You should see the newly added files!

Broadly speaking the previous steps are the ones you'll use to check in any new changes that you make, either newly added files or amendments to scripts. Of course the beauty of Git is that if for whatever reason you don't have access to VSTS you can continue to work locally, committing your changes just to the local repository as frequently as makes sense. When you next have access to VSTS you can sync all the changes as a batch.

Finally, don't loose sight of the fact that as well as well as providing version control capabilities Visual Studio allows you to run and debug your scripts courtesy of the PowerShell Tolls for Visual Studio 2015 extension. Do be sure to check out my blog post that contains links to help you get working with this great tool.

Cheers -- Graham

Getting Started with PowerShell Tools for Visual Studio

Posted by Graham Smith on January 5, 2016No Comments (click here to comment)

If you are still using the PowerShell ISE to edit your PowerShell scripts than there may be a better way, particularly if you are already a Visual Studio user. Adam Driscoll's PowerShell Tools for Visual Studio extension has been around for some time now and is even better in Visual Studio 2015. Here is my pick of the best links to help you get started with this great tool:

Don't forget, if you don't already have access to Visual Studio you can download the community edition from here.

Cheers -- Graham

Git with Visual Studio 2015 and TFS 2015

Posted by Graham Smith on September 8, 20154 Comments (click here to comment)

If you work in an organisation that has a longstanding investment in TFS chances are that you haven't done much with Git. This is because when you create a new team project in TFS you have to choose the version control system you want to use and once chosen that's it -- no changing your mind. (This was correct when I first started writing this post but things are changing as I mention later.) If your projects were created a few years ago either Git wasn't an option back then since it only became available in early 2013 or you may have thought it was just too new and shiny to consider for use with TFS, and very likely these projects use Team Foundation Version Control (TFVC).

That has all changed now and Git is firmly embedded in TFS. In fact Git seems to be firmly embedded everywhere, not least at Microsoft where open source projects are being hosted on GitHub and internal teams are using Git via Visual Studio and TFS. Keen to understand what all the fuss is about I've been learning about and using Git over the past few months and the recent release of Visual Studio 2015 and TFS 2015 seemed like a good time to share some of my experiences. As always when learning something new I recommend taking some time to do some training and to that end I have a Getting Started blog post here where I've compiled what I think are the most useful resources for Visual Studio developers.

The Bigger Picture

Before getting in to the tooling I want to take a step back and say a few words about the big picture because if you want to start using Git and already have a team project based on TFVC you have some thinking to do. When I first started writing this post moving to Git would have meant creating a new Team Project based on Git and either starting from scratch or importing history and / or work items from the TFVC-based project. There are some resources that offer help in this regard and I've compiled a short list to help anyone contemplating a migration understand what's involved:

I haven't tried to perform a migration and with luck I won't have to, since Microsoft recently announced support for creating a Git repo in a TFVC project. It looks like this will ship with TFS 2015.1 although quite what we'll get in practice remains to be seen. If you want to know more there is some commentary here.

Trying this at Home

For this post I used TFS 2015.RTM and Visual Studio 2015.RTM. If you don't have access to TFS 2015 then you can follow along using VSO since features in TFS tend to appear first in VSO, although some of the screenshots in this post may be slightly different. If you are new to VSO I have a Getting Started post here, however be aware that a key difference compared with TFS is that you create a new team project in the VSO web portal.

Whilst writing this post I encountered what seemed to be a bug in Visual Studio and in my description of how I fixed it I talk about dropping to the command line. For this you'll need to have Git installed and the easiest route is probably to get it from Chocolatey. The Install and Configure Git video in this MVA series has a step-by-step walkthrough.

Getting Started

The first step to working with Git in TFS is to create a new Team Project based on Git. In Visual Studio connect to the Team Collection where you want to create the new project and in Team Explorer navigate to Home and then click on Home (or use the down arrow button) to display the Home menu. The ability to create a New Team Project is available under Projects and My Teams:

visual-studio-create-new-team-project

Navigate through the wizard and ensure you choose Git at the Specify Source Control Settings page:

visual-studio-create-new-team-project-specify-git

With the new project created (I called mine ContosoUniversity and used the Scrum process template) you will need to clone the repository before you can do much else. Team Explorer helpfully prompts you to do this:

visual-studio-clone repository

Some people like to clone to a folder created off the root of a drive (possibly to avoid maximum path length issues?) but I accepted the offered default of C:\Users\Graham.ALM\Source\Repos\ContosoUniversity. If you examine the folder that is created you'll see that it is empty, although in reality there is a hidden .git folder. I don't like placing code files in my repo until it contains the .gitignore and .gitattributes files and Visual Studio has a neat feature for adding these. In Team Explorer navigate to Home and then choose Settings. In the lower Git panel choose Repository Settings. This pane allows you to add the the .gitignore and .gitattributes files as well as alter other aspects of the repo (not all details shown):

visual-studio-add gitignore-and-gitattributes-files

The great thing about the .gitignore file that Visual Studio adds is that it's tuned for Visual Studio development. It's the small things...

This is a good time perform a commit, so choose Changes from the Team Explorer menu bar and notice that you are requested to Configure your user name and email address before committing changes. Defaults are taken from the current TFS connection -- edit as required, optionally choose to Enable download of author images from 3rd party source and click Update. Now head back to Changes, enter a commit message and click Commit.

visual-studio-initial-commit

Bear in mind that at the moment we have only committed locally and the TFS knows nothing about the changes. Before pushing any changes to TFS let's get a Visual Studio solution added. I used my ContosoUniversity solution which you can download here. After unblocking and unzipping it copy the contents of the folder that contains the solution file and project folders to the root of your repo. Switching back to Visual Studio and the Team Explorer Home panel and you should see that the Contoso University solution file is listed under Solutions:

visual-studio-team-explorer-solutions

Now navigate to the Changes panel and notice that there are Untracked Files:

visual-studio-team-explorer-changes-untracked-files

Click on Add All to move these files to Included Changes, add a suitable comment and Commit the change. Back at the Home panel you can now open the solution. If you are opening the solution on a machine with only Visual Studio 2015 installed you might get a warning about LocalDB versions. You can ignore this but if you want to run the application do update the connection strings in CU-DEV.publish.xml in ContoUniversity.Database and Web.config in ContosoUniversity.Web with (localdb)\MSSQLLocalDB as per this post.

Whilst editing CU-DEV.publish.xml you will likely see that it is being ignored by Git. We do want this file to be included in version control as it's how new developers can quickly publish the database to LocalDB. Right-clicking the file shows Add Ignored File to Source Control which looks promising so let's try that. Navigating to Team Explorer -- Changes you'll see that there is a change and you can add a commit message and commit the change. Except you can't, or at least I couldn't:

visual-studio-team-explorer-changes-nothing-to-commit

The situation here seems to be a standoff between .gitignore which is indicating that CU-DEV.publish.xml should be ignored and Visual Studio which is honoring our desire to add the file. The fix was to drop to the command line and to open a command prompt at the root of the repo and run git add ContosoUniversity.Database\CU-DEV.publish.xml -f. This forces the file to be added against .gitignore's wishes. Presumably the problem is that Visual Studio is not using the -f switch. One to report...

The final task for this section is to publish the local changes to TFS. If you want proof that no code has been pushed to TFS yet you can open the project in the TFS Web Portal and navigate to the Code tab. You'll see something like this:

tfs-web-portal-code-new-repo

In Visual Studio Team Explorer -- Synchronization you use the Push link to publish Outgoing Commits to TFS:

visual-studio-team-explorer-synchronization-push

I've not shown it here but refreshing the Code tab of the TFS Web Portal will now display your code along with the latest comment for each file and folder.

Pull Request Workflow

One aspect of the Git integration with Visual Studio and TFS that I particularly like is the pull request workflow since it lends itself very well for code reviews. To evaluate this for yourself the first step is to set up a branch policy to ensure that the pull request workflow cannot be circumvented. From the TFS Web Portal make sure you are somewhere in your team project and open the Control Panel (cog icon on the right of the blue bar). Navigate to the Version Control tab and then in the Git repositories panel expand the tree until the required branch is highlighted -- master in my case. Now click on Branch Policies in the right-hand panel and as a minimum check Require code reviews using pull request. You'll probably also want to check Allow users to approve their own changes if you are only using one account for the evaluation.

tfs-web-portal-branch-policies

As you can see from the screenshot there are more options and you can find details here. I'm keeping things simple and with the changes saved it's time to head back to Visual Studio to see what's different. As a quick test, make a simple change to a file and commit to master (remember this is just your local copy). Now try and push the change to TFS. You should get an Errors encountered during push. See the Output window for details. message. In the Output window you should see a The following errors were reported during push: refs/heads/master, TF402455: Pushes to this branch are not permitted; you must use pull requests to commit changes. message.

The starting point to create a pull request is to create a branch from master. In Team Explorer -- Branches right click master and select New Local Branch From. In the panel that is now displayed type a name for the branch and click Create Branch.

This new branch is now shown in bold and is considered checked out. Make another simple change to a file and commit it and then in Team Explorer -- Synchronization click Publish to publish the branch and push both the change that was just made to the new branch and the earlier change to master.

The workflow now switches back to TFS Web Portal and in either Code > Explorer or Code > Pull Requests there should be a button to Create Pull Request:

tfs-web-portal-create-pull-request

Slightly confusingly this button doesn't do what it says but rather displays the Pull Requests panel with options to configure aspects of this pull request. In particular there is a more options link that does give you more options:

tfs-web-portal-configure-pull-request

The changes you can make are all fairly obvious although I didn't make any. (Do note the existence of the New Pull Request link which allows you to configure your own pull request.) From this panel the Create Pull Request link does what you expect it to do.

The pull request as created above will sit in the Assigned to the team list of pull requests:

tfs-web-portal-pull-request-assigned-to-team

When a particular pull request is selected the panel allows comments to be made as a Discussion, right in the Files that have changed or against Commits. It's quite a busy window and there's a lot going on since it's also the place where Reviewers are selected and can indicate their approval decision:

tfs-web-portal-pull-request-comments-and-review-approvals

In my case above there were no merge conflicts so once I'd marked my approval I could click the Complete pull request button. This then morphs in to a Delete source branch button to allow you to get rid of the source branch which for most teams is probably the right thing to do since you want these to be short lived.

Back in Visual Studio and your local repo, master hasn't got the latest changes and the short-lived branch created for the pull request is still hanging around. To fix all this up, in Team Explorer -- Branches double-click master so it's checked-out. Then navigate to Team Explorer -- Synchronization and use the Pull link to bring the changes to down to master. Finally back in Team Explorer -- Branches right-click the short-lived branch and delete it.

Tour Finishes Here

That's as far as I'm planning to cover in this post but obviously there's lots more I could have covered -- resolving merge conflicts for example. Whilst I like the pull request workflow a colleague pointed out that it could lead to Scrum team members working in silos and a presentation at this year's Agile on the Beach conference made the point that pull request workflows can have a negative effect on effective continuous integration. Whilst important and valid points these are probably people and process problems and if they are going to happen with Git they are probably already happening with TFVC shelvesets.

Cheers -- Graham

Getting Started with Git for Visual Studio Developers

Posted by Graham Smith on September 8, 2015No Comments (click here to comment)

If you are just getting started with learning Git it's important to distinguish between Git the actual version control technology and services that use Git such as GitHub and TFS / VSO / Visual Studio. The resources below are the ones I think will provide a good starting point for the Visual Studio developer wishing to use Git in conjunction with repositories hosted in GitHub, TFS or VSO.

The integration of Git with TFS / Visual Studio dates back to early 2013 and in mid 2015 now feels particularly mature. Additionally there is the fairly recent announcement of the GitHub extension for Visual Studio 2015. Despite all the great integration with Visual Studio it's worth remembering that sometimes you may need to drop down to the command line to perform some Git operations. This is where having spent some time learning the Git basics will pay off. The MVA jump start course above covers Git basics and a web search will provide numerous other sources.

Cheers -- Graham

Upgrading a TFS 2013 Continuous Delivery Platform to TFS 2015

Posted by Graham Smith on August 25, 2015No Comments (click here to comment)

In a previous post I described the high-level process for upgrading the continuous delivery platform I've been using for my Continuous Delivery with TFS blog post series to TFS 2013 Update 5. With the release of TFS 2015 on 6 August 2015 it's now time to upgrade this platform to the brand new version. See my previous post for the list of servers that participate in my continuous delivery platform, and as with the upgrade to TFS 2013 Update 5 all servers had been patched with the latest Windows Updates.

Team Foundation Server

There is a wealth of advice for upgrading to TFS 2015 and if you are upgrading a production instance you'll probably want to do some research. A good starting point is the ALM Rangers' TFS Upgrade -- New Elements of TFS 2015 that influence an upgrade. I can also recommend listening to Radio TFS episode 95 -- Out and About with TFS 2015, and don't forget to check out the show links.

Since I was upgrading a non-production instance I dove straight in, mounted the iso and started the setup routine. After installing the bits the Upgrade Wizard started automatically and as with previous upgrades each page of the wizard was straightforward.

tfs-upgrade-wizard

One addition to the wizard is a page to configure the new Team Foundation Build. Although in the fullness of time anyone upgrading will want to move to the new build system it is quite likely that you will need to keep existing XAML builds running as you gradually move over. This is fully supported but you will need to enable this from the Team Foundation Server Administration Console under Additional Tools and Components > XAML Build Configuration. The good news is that settings from the previous version of TFS are remembered. You can read the release notes for TFS 2015 here and the list of known issues here.

Visual Studio

Although TFS 2015 is backwards compatible with some prior versions of Visual Studio many teams are likely to want to move to Visual Studio 2015 at the same time as moving to TFS 2015. Visual Studio 2015 installs side-by-side with previous versions and whilst the installation process is straightforward there are some other things to consider since the installation routine now offers third party products as well as the ability to select just the Microsoft components you require. I chose to keep things light but did take the opportunity to install PowerShell and Git-based components as they are areas I want to explore for future blogs.

visual-studio-enterprise-install

As a test of Visual Studio 2015 I opened up my Contoso University sample application (previously created in Visual Studio 2013) and the only issue was with the SQL Server Database Project whose connection string was referring to a previous version of LocalDB. This was a quick fix as per Bill Wagner's post -- don't forget to update Web.config as well if this affects you. Whilst Contoso University worked fine locally, running an existing XAML build on the new TFS 2015 instance wasn't quite as successful and partially failed with TF900547: The directory containing the assemblies for the Visual Studio Test Runner is not valid ‘C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow'. I'd pretty much expected something like this since I hadn't installed Visual Studio 2015 yet on my all-in-one TFS machine which hosts the build agent, and performing the install (Microsoft components only) fixed this problem. (As an aside, I always make sure Visual Studio instances on a build agent server are registered with a licence key to avoid trial period expiry problems.) You can read the release notes for Visual Studio 2015 here and the list of known issues here.

Release Management

As discussed in my previous post there was no Update 5 to Release Management 2013 and instead Release Management 2015 was released and is backwards compatible with TFS 2013. Since I'd already upgraded to Release Management 2015 there was nothing much for me to do except test that the build definition that started my release pipeline still worked -- which it did! However, the automated web tests part of the pipeline (based on the MTM Automated Tests Manager tool) was still running against 2013 Agents and Microsoft Test Manager 2013 and naturally I wanted to get these components upgraded.

Microsoft Test Manager and Agents for Visual Studio

Microsoft Test Manager 2015 (aka Test Professional 2015) is installed as part of Visual Studio 2015 Enterprise however it is also available as a separate installation for testers who don't use Visual Studio or where it is needed to run the bundled tcm.exe. The latter scenario applies to me as I have a Windows 8.1 web client machine that runs automated web tests written using Selenium that require FireFox, Microsoft Test Manager and Agents for Visual Studio (Test Agent component) to be installed. I upgraded this machine (please keep reading as most of what I did was unnecessary) by first uninstalling Microsoft Test Manager 2013 and the Agents for Visual Studio 2013 and then installing and configuring the 2015 replacements. One key difference was that at the time of writing there was no upgrade to the Test Controller component of the Agents for Visual Studio 2015 so the Test Agent was shipping as a standalone exe. However, when I came to configure the Test Agent there was no Test Agent Configuration Tool for Agents for Visual Studio 2015. No matter since I knew it would be possible to partially configure the agent from Microsoft Test Manager 2015 (Lab Center > Environments and then choose to repair). However, all this did was install Agents for Visual Studio 2013. (Note that when it does this the service will run under Network Service. If you want to use a domain account you need to use the Test Agent Configuration Tool on the machine where the test agent is installed.) So a lot of work for nothing and it looks like we'll need to wait for a new Test Controller before the Test Agent can be upgraded.

Last Piece of the Puzzle

I wasn't done yet, since I upgraded Microsoft Test Manager on the web client and it turns out that the PowerShell script that forms part of the MTM Automated Tests Manager tool in Release Management 2015 hasn't been upgraded to work with the Visual Studio 2015 installation path. The proper way to fix this would be to create a new tool  in Release Management (since the built-in tools can't be edited) with an updated script that includes a reference to the VS140COMNTOOLS system environment variable which allows the script to locate tcm.exe. Since I'm due to retire my current continuous delivery infrastructure in the near future (as I prepare for a new blog post series based on TFS2015 Update 1 which should contain the new web-based Release Management) I opted for the quick and dirty trick of pointing the VS120COMNTOOLS system environment variable to C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\. Probably not something for a production environment but good enough to get my automated web tests working and showing green. Always a relief...

Cheers -- Graham

Continuous Delivery with TFS: Automatically Versioning Assemblies as Part of The Build

Posted by Graham Smith on February 27, 201514 Comments (click here to comment)

In a previous post in this series on implementing continuous delivery with TFS we looked at how some simple tweaks to the build process can help with the goal of baking quality in. This post continues in the vein of making improvements to the pipeline by addressing the issue of assembly versioning. What issue is that, I hear some of you asking? It's the situation where your Visual Studio solution contains many projects (maybe dozens) and you want all the projects to have same assembly versioning, ie the details you would traditionally set in AssemblyInfo.cs. A Google search will reveal several ways to accomplish this but most techniques involve some maintenance when a new project is added. In this post I explain how to make a publicly available low maintenance solution work with the Release Management build process template. I should point out that this issue won't affect everyone, and if you or your business don't care about this issue then do feel free to ignore. It is quite interesting though as it involves editing a build process template.

TFSVersioning on CodePlex

If assembly versioning is important to you and you use TFS there is a good chance you've seen the TFSVersioning solution available on CodePlex. It's a very nice piece of work that versions all of your solution's assemblies as part of the build process. If a new project is added it automatically gets included, so it's a low maintenance solution. There are essentially two ways to use TFSVersioning -- with the build process template that the project provides or with your own process template. This latter technique is a little involved as it requires editing your build template, but it's the technique we need to use here since we would like to use the ReleaseTfvcTemplate.12.xml build process template that ships with Release Management 2013.4. It turns out that editing this template is quite a job and I'm indebted to my good friend, colleague and TFS guru Bharath Sundaresan for figuring out all of the complicated details. An additional required hurdle is that the project hasn't been updated for TFS 2013 but fortunately it's not a lot of work to remedy this. The TFSVersioning deployment pack is available from the Downloads page and it has some great documentation which I recommend reading before you begin.

Update TFSVersioning for TFS2013

The core component that we need to update for TFS 2013 is TfsBuild.Versioning.Activities.dll. To accomplish this follow these steps:

  1. Download the latest source code for TFSVersioning from the Source Code page and unzip to somewhere convenient.
  2. Navigate to the latest version under Prod and open BuildVersioning.sln. Remove the TfsBuild.Versioning.Activities.Tests and TfsBuild.Versioning.Activities.Tests.Stubs projects as we don't need to amend them for what we are doing here.
  3. Expand the References node of the TfsBuild.Versioning.Activities project and notice that the Microsoft.TeamFoundation.* references are marked as missing:
    TfsBuild-Versioning-Activities-missing-references
  4. Remove these references and replace them with the 2013 versions from C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ReferenceAssemblies\v2.0.
  5. You shoud now be able to build a Release version of TfsBuild.Versioning.Activities.dll.

Once you have succesfully updated the project for TFS 2013 it's probably a good idea to make sure that a basic installation of TFSVersioning works. Follow these steps to verify this:

  1. Download and unzip the latest TFSVersioning deployment pack -- currently 2.0.1. Copy VersioningBuildTemplate20.xaml from the pack to the ContosoUniversity BuildProcessTemplates folder and check in to version control.
  2. Under ContosoUniversity create a new folder called CustomActivityStorage and copy over the new version of TfsBuild.Versioning.Activities.dll. Check in to version control.
  3. From Team Explorer in Visual Studio navigate to Builds > Actions > Manage Build Controllers.
  4. In Manage Build Controllers dialog choose Properties and in Manage Controller Properties set Version control path to custom assemblies to $/ContosoUniversity/CustomActivityStorage.
    Version-control-path-to-custom-assemblies
  5. Now create a test build definition, replacing the standard release template with VersioningBuildTemplate20.xaml and setting all required properties including the drop folder.
  6. Whilst editing the build definition set any properties under the Build Versioning and Build Versioning (Optional) sections as you wish. Refer to the documentation for TFSVersioning for details.
  7. Queue a manual build of the test build definition. Observe in the drops folder that the ContosoUniversity.* binaries all have the same File version.
Update the ReleaseTfvcTemplate.12 Release Template with the TFSVersioning Custom Activity

This process broadly follows the Harder Installation but More Instructive section of the TfsVersioning User and Development Guide however modifying ReleaseTfvcTemplate.12.xaml requires several more steps. Partly this is because TfsBuild.Versioning.Activities.dll contains more functionality that isn't referred to in the documentation and partly because ReleaseTfvcTemplate.12.xaml is missing some activities that (reading between the lines) were present in the template that was used by the TFSVersioning project.  In the instructions below I assume a degree of familiarity with editing release templates. If you need guidance take a look here for just one example of how to get started. You should be aware that there are two ways to edit templates: through the XAML designer and through notepad. The former is less prone to error but slow and the latter is much faster but with the distinct possibility of a copy and paste error. The technique I describe below also sets you up for relatively easy debugging of the process template since there is a good chance of not getting everything right first time.

  1. Install the updated TfsBuild.Versioning.Activities.dll to the Global Assembly Cache by opening a Visual Studio command prompt (from C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\Shortcuts if your shortcuts are missing in Windows 8.1) and issuing a command similar to gacutil -i "C:\Users\Graham\Downloads\tfsversioning-103318\Prod\V 2.0.1.0\Source\TfsBuild.Versioning.Activities\bin\Release\TfsBuild.Versioning.Activities.dll". 
  2. Copy C:\Program Files (x86)\Microsoft Visual Studio 12.0\Release Management\Client\bin\ReleaseTfvcTemplate.12.xaml to the ContosoUniversity BuildProcessTemplates folder and check in to version control. Chances are you already have a template with the same name so you'll probably want to change the name to ReleaseTfvcTemplate.12.Versioning.xaml or similar. Once checked in open this template in Visual Studio so it displays in the XAML editor.
  3. Set up the Visual Studio Toolbox to work with TfsBuild.Versioning.Activities.dll in a custom tab. You can reference the version in CustomActivityStorage. Note that you only need to add the VersionAssemblyInfoFiles item.
  4. Drag the VersionAssemblyInfoFiles activity from the toolbox to the workflow as the first item under Compile, Test and Publish. Feel free to give the activity a custom name. If you examine the properties of the activity you will see all the InArguments that need to be married up with either Variables or Arguments that do not yet exist in the process template:
    TfsBuild-Versioning-Activities-VersionAssemblyInfoFiles
  5. The arguments can be created as per the TfsVersioning User and Development Guide instructions using the Arguments editor but a faster way is to open the template in Notepad, copy the following values and append them to the <x:Members> section.
  6. The next step is to add the metatdata items that allow each of the above arguments to be set. Again, it's possible to use the Metadata editor but the faster Notepad way is to copy the following values and append them to the <mtbw:ProcessParameterMetadataCollection> section.
  7. Back in the XAML editor navigate to the Arguments editor and supply default values for some arguments as follows:
    1. AssemblyFileVersionPattern = "1.0.J.B"
    2. AssemblyInfoFilePattern = "AssemblyInfo.*"
    3. AssemblyVersionPattern = "1.0.0.0"
    4. BuildNumberPrefix = 0
    5. DoCheckinAssemblyInfoFiles = False
    6. ForceCreateVersion  = False
    7. UseVersionSeedFile = False
    8. VersionSeedFilePath= "TfsVersion\VersionSeed.xml"
  8. Navigate to the Variables editor and create the following variables (you may need to Browse for Types to get some of the variable types):
    1. Name = BuildAgent; Variable Type = Microsoft.TeamFoundation.Build.Client.iBuildAgent; Scope = Compile, Test and Publish
    2. Name = BuildDetail; Variable Type = Microsoft.TeamFoundation.Build.Client.iBuildDetail; Scope = Compile, Test and Publish
    3. Name = BuildDirectory; Variable Type = String; Scope = Compile, Test and Publish
    4. Name = Workspace, Variable Type = Microsoft.TeamFoundation.VersionControl.Client.Workspace; Scope = Compile, Test and Publish
  9. From Toolbox > Team Foundation Build Activities add the following activities to the top of  Compile, Test and Publish so they appear in the order listed:
    1. Activity = GetBuildAgent; Result = BuildAgent
    2. Activity = GetBuildDetail; Result = BuildDetail
    3. Activity = GetWorkspace; Name = String.Format("{0}_{1}_{2}", BuildDetail.BuildDefinition.Id, Microsoft.TeamFoundation.LinkingUtilities.DecodeUri(BuildAgent.Uri.AbsoluteUri).ToolSpecificId, BuildAgent.ServiceHost.Name); Result = Workspace
  10. Return to the properties of the VersionAssemblyInfoFiles activity and use the ellipsis at the end of each row to replace Enter a VB expression with the correct value. The result should be as follows:
    TfsBuild-Versioning-Activities-VersionAssemblyInfoFiles-complete
  11. As a final step in this section save all the changes and check them in to version control.
Testing the Updated ReleaseTfvcTemplate.12 Release Template

At long last we are in a position to test the new template. The easiest way is to edit the test build definition created above and replace VersioningBuildTemplate20.xaml with our updated ReleaseTfvcTemplate.12.xaml version. Set any properties as required and queue a new build. With luck you will have a successful build and a set of uniformly versioned assemblies!

If you are having difficulty in implementing the steps above the debugging process is reasonably straightforward. Once the build template has been added to the test build definition you can make changes to the template, save them and then check them in to version control. Simply queue a new build to check your changes.

The final piece of the jigsaw when everything is working is to edit ContosoUniversity_Main_Nightly to use the new version of the template. And to enjoy a well-deserved drink.

Cheers -- Graham