<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>ALM Adventures</title>
	
	<link>http://www.andygeldman.com</link>
	<description>Agile Development and Application Lifecycle Management</description>
	<lastBuildDate>Sat, 19 May 2012 12:23:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/AndyGeldman" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="andygeldman" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">AndyGeldman</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Fixing Drag and Drop Ranking in JIRA GreenHopper</title>
		<link>http://www.andygeldman.com/index.php/2012/05/fixing-drag-and-drop-ranking-in-jira-greenhopper/</link>
		<comments>http://www.andygeldman.com/index.php/2012/05/fixing-drag-and-drop-ranking-in-jira-greenhopper/#comments</comments>
		<pubDate>Sat, 19 May 2012 12:23:52 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[GreenHopper]]></category>
		<category><![CDATA[JIRA]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=1090</guid>
		<description><![CDATA[I hadn&#8217;t worked with JIRA until just a few weeks ago and, being very familiar with TFS, found it pretty painful to get started with. One thing it does have over TFS 2010 is the GreenHopper plugin, which provides a fairly nice Agile/Scrum task board (to be fair, Urban Turtle provides the same for TFS <a href='http://www.andygeldman.com/index.php/2012/05/fixing-drag-and-drop-ranking-in-jira-greenhopper/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>I hadn&#8217;t worked with JIRA until just a few weeks ago and, being very familiar with TFS, found it pretty painful to get started with. One thing it does have over TFS 2010 is the GreenHopper plugin, which provides a fairly nice Agile/Scrum task board (to be fair, <a href="http://urbanturtle.com/">Urban Turtle</a> provides the same for TFS 2010, and the forthcoming TFS 11 provides it out of the box with the new Agile Project Management feature).</p>
<p>My team is getting along fine with a physical task board for tracking during sprints, but I was looking forward to drop-and-drop Product Backlog prioritisation after using the awkward Rank field in TFS 2010. Alas, JIRA stubbornly refused to behave! It just didn&#8217;t react when I attempted to drag an item to a different position. After trying and failing to get it working with the my preferred &#8220;find out why it doesn&#8217;t work&#8221; approach, I found success down the traditional &#8220;trial and error config changes&#8221; route.</p>
<p>I can&#8217;t yet tell you exactly why this fixed it (presumably something to do with the centrally-administered permissions configuration) but it worked for me so there is probably someone else out there with the same problem. Here&#8217;s what I did:</p>
<ol>
<li>Go into the project&#8217;s GreenHopper configuration</li>
<li>Click the link to repair the ranking field (see screenshot)</li>
<li type="_moz">Under General Configuration, tick the box labelled Scheduling Permission (see screenshot)</li>
<li type="_moz">That&#8217;s it!</li>
</ol>
<p><em>Repair the ranking field:</em></p>
<p><a href="http://www.andygeldman.com/wp-content/uploads/2012/05/Repair-ranking.png"><img class="alignleft size-full wp-image-1092" title="Repair-ranking" src="http://www.andygeldman.com/wp-content/uploads/2012/05/Repair-ranking.png" alt="" width="535" height="129" /></a></p>
<p><em>Scheduling permission:</em></p>
<p><a href="http://www.andygeldman.com/wp-content/uploads/2012/05/Scheduling-permission.png"><img class="alignleft size-full wp-image-1093" title="Scheduling-permission" src="http://www.andygeldman.com/wp-content/uploads/2012/05/Scheduling-permission.png" alt="" width="1060" height="195" /></a></p>
<p>.</p>
<p>By the way, this is JIRA 4. Hope that helps!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/05/fixing-drag-and-drop-ranking-in-jira-greenhopper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finally on the TFS 11 Hosted Beta!</title>
		<link>http://www.andygeldman.com/index.php/2012/05/finally-on-the-tfs-11-hosted-beta/</link>
		<comments>http://www.andygeldman.com/index.php/2012/05/finally-on-the-tfs-11-hosted-beta/#comments</comments>
		<pubDate>Fri, 18 May 2012 14:23:33 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=1086</guid>
		<description><![CDATA[I was more than a little tardy signing up for the TFS 11 Hosted beta when it was announced but now have an invite code thanks to @DannyJessee! It looks great and I&#8217;m liking the message after creating a new Team Project:]]></description>
			<content:encoded><![CDATA[<p>I was more than a little tardy signing up for the <a href="http://tfspreview.com/">TFS 11 Hosted beta</a> when it was <a href="http://blogs.msdn.com/b/bharry/archive/2011/09/14/team-foundation-server-on-windows-azure.aspx">announced</a> but now have an invite code thanks to @DannyJessee!</p>
<p>It looks great and I&#8217;m liking the message after creating a new Team Project:</p>
<p><a href="http://www.andygeldman.com/wp-content/uploads/2012/05/18-05-2012-14-52-11.png"><img class="alignleft size-full wp-image-1087" title="18-05-2012 14-52-11" src="http://www.andygeldman.com/wp-content/uploads/2012/05/18-05-2012-14-52-11.png" alt="" width="572" height="410" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/05/finally-on-the-tfs-11-hosted-beta/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TFS Might Cost You Nothing!</title>
		<link>http://www.andygeldman.com/index.php/2012/05/tfs-might-cost-you-nothing/</link>
		<comments>http://www.andygeldman.com/index.php/2012/05/tfs-might-cost-you-nothing/#comments</comments>
		<pubDate>Sun, 13 May 2012 18:51:02 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=1070</guid>
		<description><![CDATA[As the central hub of Microsoft&#8217;s ALM suite, many people expect Team Foundation Server to be an expensive product, and a cursory search for pricing might back that preconception up &#8211; Amazon.co.uk lists the server software at £500 and one client access license (CAL) at £450. However, there are three factors that (for some companies) <a href='http://www.andygeldman.com/index.php/2012/05/tfs-might-cost-you-nothing/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>As the central hub of Microsoft&#8217;s ALM suite, many people expect Team Foundation Server to be an expensive product, and a cursory search for pricing might back that preconception up &#8211; Amazon.co.uk lists the server software at £500 and one client access license (CAL) at £450.</p>
<p>However, there are three factors that (for some companies) reduces the price of TFS to zero while allowing them to roll it out <em>to their entire organisation</em>. Yes, it sounds a little too good to be true. Here are the factors:</p>
<h4>MSDN Subscription</h4>
<p>Visual Studio MSDN subscriptions come with <a href="http://blogs.msdn.com/b/buckh/archive/2009/10/20/tfs-2010-server-licensing-it-s-included-in-msdn-subscriptions.aspx">one TFS server license</a> <em>for production use</em> and one CAL. So team members like developers and testers, who are often provided with MSDN subs, don&#8217;t need anything more to use TFS. If you don&#8217;t get MSDN subscriptions for developers I can heartily recommend it as pretty much the whole Microsoft stack of OS, server tools, and development tools is included &#8211; upgrades and all &#8211; for development and testing purposes. Bear in mind that subscriptions can be cheaper (sometimes <em>much </em>cheaper) from a reseller. I can recommend <a href="http://www.parkway.co.uk/">Parkway Gordon</a>.</p>
<p>Note: MSDN subscriptions are <a href="http://msdn.microsoft.com/subscriptions/cc150618.aspx">per-user</a> not per-machine so a single subscription covers use at any location (office, home, customer sites) on any number of machines.</p>
<h4>Work Item Only View</h4>
<p>TFS users who only enter and edit their own work items, using TFS web access, don&#8217;t need a CAL. To make it easy to ensure users don&#8217;t overstep this provision, there is even a <a href="http://intovsts.net/2011/06/29/work-item-only-view-wiov-users-in-tfs-2010/">Work Item Only View</a> security group which includes the relevant permissions and no more. This means anyone in your organisation can submit requirements, changes and bugs without impacting TFS licensing.</p>
<h4>Reports</h4>
<p>A <a href="http://blogs.msdn.com/b/bharry/archive/2012/03/08/even-better-access-to-team-foundation-server.aspx">recent development</a> is that users do not need a CAL for accessing reports. So managers and other stakeholders can help themselves to project summary data and graphs without a license either.</p>
<h4>Other Free TFS Stuff</h4>
<ul>
<li>Team Explorer Everywhere (the Eclipse IDE plug-in) is free in itself, although a CAL is needed (Brian Harry&#8217;s <a href="http://blogs.msdn.com/b/bharry/archive/2012/03/08/even-better-access-to-team-foundation-server.aspx">blog</a> again)</li>
<li>Two system administrators can access a TFS instance for free (TFS licensing whitepaper)</li>
<li>Access via Microsoft System Center Operations Manager is free (ditto)</li>
<li>Static data from TFS can be distributed manually for free (ditto)</li>
<li>Five users don&#8217;t need a CAL when TFS server is bought at retail (ditto)</li>
<li><a href="http://www.microsoft.com/en-us/download/details.aspx?id=28987">TFS 11 Express</a> is completely free for up to 5 users (Brian Harry&#8217;s <a href="http://blogs.msdn.com/b/bharry/archive/2012/02/23/coming-soon-tfs-express.aspx">blog</a>)</li>
<li><a href="http://www.microsoft.com/en-us/download/details.aspx?id=329">Team Explorer</a> (Visual Studio Shell) is free, although you would need a CAL (or retail/express edition exemption) if you access more than reports</li>
</ul>
<h4>Summary</h4>
<p>A good understanding of Visual Studio and TFS licensing, canny use of security groups, and potentially free client tools (web access, Team Explorer, Visual Studio Express) can quite realistically reduce the price of TFS to zero.</p>
<p>If your development team have MSDN subscriptions (a good idea in any event) there might be no further cost to adopting TFS in the team, and even rolling it out to a much wider audience.</p>
<p>Final note: Don&#8217;t dive in based on this blog post alone &#8211; the licensing is complex so read the <a href="http://www.microsoft.com/en-us/download/details.aspx?id=13350">TFS licensing whitepaper</a> first and clear up any questions you have.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/05/tfs-might-cost-you-nothing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Organizational Impediments and the Marshall Model</title>
		<link>http://www.andygeldman.com/index.php/2012/03/organizational-impediments-and-the-marshall-model/</link>
		<comments>http://www.andygeldman.com/index.php/2012/03/organizational-impediments-and-the-marshall-model/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 20:09:14 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=1056</guid>
		<description><![CDATA[I attended a thought-provoking talk last week given by agile coach Bob Marshall which focused on his model of organisational effectiveness, which you can download a paper on here. His descriptions of organisations that were ad-hoc (reactive, unplanned) or analytic (bureaucratic, rigid) were very familiar to me and provided a good backdrop to thinking about <a href='http://www.andygeldman.com/index.php/2012/03/organizational-impediments-and-the-marshall-model/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>I attended a thought-provoking <a href="http://www.meetup.com/London-Scrum-User-Group/events/54155362/">talk</a> last week given by agile coach <a href="http://flowchainsensei.wordpress.com/">Bob Marshall</a> which focused on his model of organisational effectiveness, which you can download a paper on <a href="http://www.fallingblossoms.com/opinion/">here</a>.</p>
<p>His descriptions of organisations that were <em>ad-hoc</em> (reactive, unplanned) or <em>analytic</em> (bureaucratic, rigid) were very familiar to me and provided a good backdrop to thinking about what are known as <em>organisational impediments</em> in Scrum.</p>
<p>Organisational impediments block or slow progress &#8211; just like other impediments &#8211; but are very difficult to resolve because they are baked into the wider organisation&#8217;s structure and processes. There are good lists on the <a href="http://www.scrumalliance.org/articles/123-top-ten-organizational-impediments">Scrum Alliance</a> website and elsewhere but ones that chime with me include:</p>
<ul>
<li>Focusing on utilisation and ignoring productivity (an uncharitable but evocative term for this is <a href="http://davidhalluk.blogspot.co.uk/2010/11/busy-fools.html">busy fools</a>)</li>
<li>Unsuitable office accommodation discouraging collaboration and/or causing distraction</li>
<li>Lack of organisational drive and (perhaps as a result) individual enthusiasm for getting great at developing software</li>
</ul>
<p>Understanding what kind of organisation you are dealing with in terms of the Marshall Model categories (ad-hoc, analytic, synergistic, chaordic &#8211; or in transition from one to the other) is certainly not a silver bullet but it does help flesh out the business context. For example, an analytic organisation may have invested heavily in separate functions for business analysis, development, and testing and find the idea of cross-functional teams mystifying. Their whole mindset is reductionist &#8211; they believe that breaking things down into parts is the right way to make sense of them &#8211; so mixing it all up again can sound like heresy. Even suggesting that they try a different approach can run counter to the analytical idea that it is possible to solve an issue completely upfront by researching the problem, breaking it down, and designing the &#8220;perfect&#8221; solution.</p>
<p>There&#8217;s no easy way to break these organisational impediments down. I think the best approach is to go a little native &#8211; get inside the organisation, understand where it is coming from, and try to win hearts and minds. For example, in an analytical organisation, explain that the Agile approach is empirical rather than chaotic, its effectiveness is backed up by research and &#8211; above all &#8211; demonstrate that it works, even if at first that needs to be on a very small project. It is hard to argue with good results, and if you can carefully direct an organisation down the Agile path, remembering to inspect and adapt continuously, the payback in productivity, quality and morale should be plain to see.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/03/organizational-impediments-and-the-marshall-model/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>work4source: Visual Studio 2010 Extension</title>
		<link>http://www.andygeldman.com/index.php/2012/03/work4source-visual-studio-2010-extension/</link>
		<comments>http://www.andygeldman.com/index.php/2012/03/work4source-visual-studio-2010-extension/#comments</comments>
		<pubDate>Thu, 22 Mar 2012 15:54:17 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[TFS]]></category>
		<category><![CDATA[Work Items]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=1040</guid>
		<description><![CDATA[I have just published on Codeplex a new Visual Studio 2010 extension that provides a simple but very useful function: it quickly finds work items that have been linked to a selected source file or folder. You can find it at work4source.codeplex.com. This came about when I was rolling out TFS work items to a <a href='http://www.andygeldman.com/index.php/2012/03/work4source-visual-studio-2010-extension/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>I have just published on Codeplex a new Visual Studio 2010 extension that provides a simple but very useful function: it quickly finds work items that have been linked to a selected source file or folder. You can find it at <a href="http://work4source.codeplex.com/">work4source.codeplex.com</a>.</p>
<p>This came about when I was rolling out TFS work items to a team that had subject matter experts regularly changing specifications for complex business rules. Another team produced configuration files based on the specifications, and both files were kept in source control. The experts often needed to review the change history and could identify which source files were relevant. I knew that changeset comments, diff tools, and the annotate feature (aka &#8220;blame allocator&#8221;) do a great job of showing <em>what</em> has changed, but these users wanted to know <em>why</em> a change was made &#8211; a business-focused description and justification. This is the job of work items, but you can&#8217;t easily generate a list of work items from a specific source file or folder.</p>
<p>To be fair, Visual Studio does make this information available. But to see <strong>all</strong> work items that have been linked to a source file you need to open the history, then changeset details, then the work items channel&#8230; now make a note of any linked work items and <em>repeat for every changeset</em>. For a source file with thirty changes that could take ten minutes or more, so is impractical for regular use. The work4source extension replaces the process with one click, and the query is performed on a separate thread so you can continue working.</p>
<p>If you too have felt the pain of searching for work items from source items (or are just curious) please download the tool, try it out, and let me know what you think. I hope the community find it useful and welcome contributions to its development.</p>
<p>Credit: This extension was coded by a friend and colleague of mine Dijon Smit, so thanks to him for agreeing to add it to Codeplex.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/03/work4source-visual-studio-2010-extension/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ITKanban and the London Kanban Meetup Group</title>
		<link>http://www.andygeldman.com/index.php/2012/03/itkanban-and-the-london-kanban-meetup-group/</link>
		<comments>http://www.andygeldman.com/index.php/2012/03/itkanban-and-the-london-kanban-meetup-group/#comments</comments>
		<pubDate>Wed, 14 Mar 2012 13:18:11 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[ALM]]></category>
		<category><![CDATA[Kanban]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=1034</guid>
		<description><![CDATA[I attended the first IT Kanban London Meetup last night and enjoyed talking to other Agile practitioners there. The format was informal drinks, which was great to get the group started; future sessions will hopefully build on that and feature some compelling speakers. There was a good mix of seasoned Kanban practitioners and those just <a href='http://www.andygeldman.com/index.php/2012/03/itkanban-and-the-london-kanban-meetup-group/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>I attended the first <a href="http://www.meetup.com/ITKanban-London-UK/">IT Kanban London Meetup</a> last night and enjoyed talking to other Agile practitioners there. The format was informal drinks, which was great to get the group started; future sessions will hopefully build on that and feature some compelling speakers. There was a good mix of seasoned Kanban practitioners and those just starting or curious about the framework. If you are an Agile practitioner working in London I highly recommend you come along to the next one.</p>
<p>I discovered the <a href="http://itkanban.com/">IT Kanban</a> website from the Meetup and am impressed by the quality of the materials on the site. Together with books such as <a href="www.amazon.co.uk/Kanban-David-J-Anderson/dp/0984521402">David Anderson&#8217;s</a> and the recent <a href="http://vsarkanbanguide.codeplex.com/">ALM Rangers guidance</a> (including TFS 2010 and 11 process templates) the community support for Kanban is getting pretty strong.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/03/itkanban-and-the-london-kanban-meetup-group/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Clone a TFS 2010 Instance From DB Backups – Quick and Dirty</title>
		<link>http://www.andygeldman.com/index.php/2012/03/clone-a-tfs-2010-instance-from-db-backups-quick-and-dirty/</link>
		<comments>http://www.andygeldman.com/index.php/2012/03/clone-a-tfs-2010-instance-from-db-backups-quick-and-dirty/#comments</comments>
		<pubDate>Thu, 08 Mar 2012 15:57:05 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=1008</guid>
		<description><![CDATA[The official guide to Backing up and Restoring TFS 2010 is wonderfully comprehensive, but will make you very dizzy if just want to throw together a quick clone of a TFS instance from DB backups. Why would you want to clone a TFS instance? Well, it&#8217;s very useful for testing out changes in a realistic <a href='http://www.andygeldman.com/index.php/2012/03/clone-a-tfs-2010-instance-from-db-backups-quick-and-dirty/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>The official guide to <a href="http://msdn.microsoft.com/en-us/library/bb552295.aspx">Backing up and Restoring TFS 2010</a> is wonderfully comprehensive, but will make you very dizzy if just want to throw together a quick clone of a TFS instance from DB backups. Why would you want to clone a TFS instance? Well, it&#8217;s very useful for testing out changes in a realistic copy of your production system &#8211; you wouldn&#8217;t go straight to production with half-baked software changes so you shouldn&#8217;t with TFS changes either. Examples include a new branching strategy, significant source control restructuring, or experimentation with the build process.</p>
<p>If you are thinking that the TFS Power Tools Backup and Restore wizard does all this anyway, you would be right &#8211; but only if you are restoring back to the same machine that the backups came from. If you are restoring to a fresh TFS installation on a different operating system and AD domain it won&#8217;t be so simple.</p>
<p>A few caveats:</p>
<ul>
<li>This assumes you are have the source TFS instance database backups (e.g. created using the TFS Power Tools backup and restore wizard).</li>
<li>I have tried to get the process as quick as possible, but I can&#8217;t guarantee that it will produce an absolutely perfect working replica. It should however be good enough to play with source control, work items and build.</li>
<li>Your source and target machines will probably be configured differently from mine, so you may need to take some additional steps. I have included a few troubleshooting ideas at the end.</li>
<li>I have assumed you are cloning onto an existing standalone TFS installation &#8211; with the database and application tiers together on one machine and pre-existing databases. This process will replace the databases, so make sure you don&#8217;t want to keep the existing instance!</li>
<li>Some of the steps are quite hacky, so don&#8217;t be tempted to administer your production TFS instance this way!</li>
</ul>
<p>Here goes:</p>
<ol>
<li>Copy the database backups to local machine</li>
<li>Open a command prompt and issue:
<pre class="brush: bash; title: ; notranslate">cd C:\Program Files\Microsoft Team Foundation Server 2010\Tools
TFSServiceControl.exe quiesce</pre>
</li>
<li>Start SQL Server Management Studio
<ol>
<li>Note the physical location of the TFS databases e.g. <em>C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA</em></li>
<li>Detach all TFS databases:
<ol>
<li>TFS_*</li>
<li>ReportServer</li>
<li>ReportServer_TempDB</li>
<li>SharePoint_Config</li>
<li>WSS_Content</li>
</ol>
</li>
<li>Delete, rename or move the physical files for the TFS databases</li>
</ol>
</li>
<li>Start the TFS Admin Console
<ol>
<li>Click <em>Team Foundation Backups</em> on the left</li>
<li>Click <em>Restore Databases</em> on the right</li>
<li>Follow the Restore Wizard
<ol>
<li>Choose the Network Path to restore from</li>
<li>Modify the SQL server instance to <em>localhost</em></li>
</ol>
</li>
<li>Use SQL Server Management Studio to manually restore any failed databases</li>
</ol>
</li>
<li>Start SQL Server Management Studio
<ol>
<li>Locate the <em>Tfs_Configuration</em> database, right-click on it and select <em>Properties</em></li>
<li>Click <em>Extended Properties</em> on the left</li>
<li>On the right locate the row for <em>TFS_BACKUP_PLAN_CONTROLLER</em></li>
<li>Change the value to the new server name e.g. localhost</li>
<li>Locate the row for <em>TFS_INSTANCE</em></li>
<li>Make a note of the GUID value</li>
</ol>
</li>
<li>Repoint TFS web services to the new instance
<ol>
<li>Navigate to folder <em>C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services</em></li>
<li>Open <em>web.config</em> in a plain text editor</li>
<li>Locate the <em>applicationId</em> key</li>
<li>Change the value to the <em>TFS_INSTANCE </em>value noted in the step above</li>
</ol>
</li>
<li>Open a command prompt and issue:
<pre class="brush: bash; title: ; notranslate">cd C:\Program Files\Microsoft Team Foundation Server 2010\Tools
TFSServiceControl.exe unquiesce
TFSConfig remapdbs /databaseName:localhost;Tfs_Configuration /sqlInstances:localhost /continue
TFSConfig identities /change /fromdomain:{SourceDomain} /todomain:{TargetDomain} /account:{SourceAdminAccount} /toaccount:{TargetAdminAccount}</pre>
<p>The last command (<em>TFSConfig identities</em>) is intended to repoint an account with TFS administrative privileges on the source instance with an account that is accessible on the target machine (your own account is the obvious choice). Repeat it for any additional accounts which you want to use against the cloned instance. If the target machine is not in a domain, set {TargetDomain} to the machine name.</li>
<li>Start the TFS Admin Console
<ol>
<li>Click <em>Application Tier </em>on the left
<ol>
<li>Add a user account accessible on the target machine to Administration Console Users (e.g. your own account)</li>
<li>Click <em>Change URLs </em>on the right</li>
<li>Change the notification URL to <em>http://localhost:8080/tfs</em>, test, then click the <em>OK</em> button</li>
<li>Click <em>Reapply Account </em>on the right, enter the password, then click OK</li>
</ol>
</li>
<li>Click <em>Build Configuration </em>on the left
<ol>
<li>Reconfigure the build service as needed</li>
</ol>
</li>
</ol>
</li>
<li>Clear the TFS application tier cache by deleting the contents of <em>C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\_tfs_data</em></li>
<li>Clear the Visual Studio TFS cache by deleting the contents of <em>C:\Users\Andy\AppData\Local\Microsoft\Team Foundation\3.0\Cache</em></li>
<li>Start Visual Studio and connect to the cloned instance</li>
</ol>
<p>That should do it!</p>
<h4>Troubleshooting</h4>
<ul>
<li>The clone will have the same instance ID as the original instance, and if you are able to connect to both from the same machine you may notice some strange behaviour due to the cache not being able to differentiate between them. If this is a problem look into <em>TFSConfig changeserverid.</em></li>
<li>If the restore reports that it <em>failed to restore Reporting Services encryption key</em> it may be because the Reporting Services database is detached at that point. Use <em>rskeymgmt -a -f [KEYFILE] -p [PASSWORD]</em> or Reporting Services Configuration Manager to restore the key instead (if you want to use Reporting Services).</li>
<li>If you get a message saying that the service account does not have access to SQL Server, start SQL Server Management Studio and issue the SQL <em>grant connect sql to &#8220;domain\account&#8221;</em></li>
<li>If you get a message <em>Failed to add &#8216;AccountName&#8217; account to the TFSEXECROLE role on the Tfs_Warehouse relational database</em> follow the instructions at <a href="http://support.microsoft.com/kb/2025896">http://support.microsoft.com/kb/2025896</a></li>
<li>If you get <em>TF30040: The database is not correctly configured </em>when connecting from Visual Studio it may indicate that the service account does not have permission to access the database(s). Give the account permission or change the service account.</li>
<li>If you get <em>TF14061 Workspace does not exist</em> it might indicate that the user account which owns the workspace has been remapped. Use <em>tf workspace /newowner</em> or the workspaces GUI to remap the workspace.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/03/clone-a-tfs-2010-instance-from-db-backups-quick-and-dirty/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step by Step: Automatically Stamp Assemblies with the Build Number</title>
		<link>http://www.andygeldman.com/index.php/2012/02/step-by-step-automatically-stamp-assemblies-with-the-build-number/</link>
		<comments>http://www.andygeldman.com/index.php/2012/02/step-by-step-automatically-stamp-assemblies-with-the-build-number/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 22:23:41 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Build]]></category>
		<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=977</guid>
		<description><![CDATA[The TFS 2010 build system is very powerful but has a steep learning curve through build controllers, build agents, MSBuild, Windows Workflow Foundation, custom activities and more. With that in mind, I thought it would be helpful to explain a simple (but very useful) TFS 2010 build customisation from end to end. If you are <a href='http://www.andygeldman.com/index.php/2012/02/step-by-step-automatically-stamp-assemblies-with-the-build-number/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>The TFS 2010 build system is very powerful but has a steep learning curve through build controllers, build agents, MSBuild, Windows Workflow Foundation, custom activities and more. With that in mind, I thought it would be helpful to explain a simple (but very useful) TFS 2010 build customisation from end to end. If you are going to follow this process along I recommend you use a development machine or temporary VM so you can break things without consequences &#8211; it&#8217;s tough to learn if you are terrified of making mistakes!</p>
<h4>The Goal</h4>
<p>The aim here is to:</p>
<ol>
<li>Create a sample application</li>
<li>Create a build definition for the application</li>
<li>Customise the build process to stamp the application&#8217;s output assembly with the full build number, so you only need the assembly to trace right back to source code and work items</li>
</ol>
<p>The customisation also includes a common versioning approach, which is well documented in the <a href="http://vsarbuildguide.codeplex.com/">ALM Rangers Build Customisation Guide</a>. The ALM guide is targeted to intermediate to advanced users, whereas this is more of a tutorial for developers with little exposure to build.</p>
<p>I will assume you have already installed the build service and created a build controller and build agent.</p>
<h4>Sample Application</h4>
<p>This is going to be a console application that simply outputs the assembly properties we are interested in.</p>
<ol>
<li>Start Visual Studio and create a new C# Console Application called <em>SampleApplication</em> or similar (VB.NET would be fine, but the sample code below is C#). Tick the box to add it to source control.</li>
<li>Open the <em>AssemblyInfo.cs</em> file and add some text within the <em>AssemblyDescription</em> that you will recognise &#8211; anything will do. Delete the existing comment which has an <em>AssemblyVersion</em> example as it will confuse the versioning workflow that comes later.</li>
<li>Open the <em>Program.cs</em> file, paste in the code below, then run the application to see the output.</li>
<li>Check in to source control.</li>
</ol>
<pre class="brush: csharp; title: ; notranslate">

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics;

namespace AssemblyVersioning
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(&quot;AssemblyVersion: {0}&quot;,
Assembly.GetExecutingAssembly().GetName().Version.ToString());
Console.WriteLine(&quot;AssemblyFileVersion: {0}&quot;,
FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion.ToString());
Console.WriteLine(&quot;AssemblyDescription: {0}&quot;,
FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).Comments.ToString());

Console.ReadLine();
}
}
}
</pre>
<h4>Build Definition</h4>
<p>We will set up a build using the default template to make sure it works before we start changing things. Note that there are many other configuration options available, but those below are the minimum required for now.</p>
<ol>
<li>In Visual Studio open the Team Explorer panel.</li>
<li>Expand your Team Project, then right-click on Builds and select <em>New Build Definition&#8230;</em></li>
<li>Select <em>General</em> on the left. Give the definition a name.</li>
<li>Select <em>Trigger</em> on the left. Leave this as <em>Manual</em>.</li>
<li>Select <em>Workspace</em> on the left. Under the <em>Source Control Folder</em> heading modify the location to the folder containing the sample application solution file. The build system will get the latest version of everything under this folder (and it&#8217;s also the trigger folder for continuous integration builds).</li>
<li>Select <em>Build Defaults</em> on the left. Ensure the build controller is selected, then enter a folder in the drop location field. Under live use this would normally be a file share accessible to the team, but for this purpose could be local to the build machine. Note that even if it&#8217;s a local folder it needs to be in the <em>\\machinename\fileshare</em> format.</li>
<li>Select <em>Process</em> on the left. Expand <em>Items to Build </em>and set the <em>Projects to Build</em> to the sample application&#8217;s solution file. If the sample application is still open, this will have been populated for you.</li>
<li>Save the build definition.</li>
<li>In Team Explorer, right-click the new build definition and select <em>Queue New Build</em> then click the <em>Queue </em>button.</li>
<li>The Build Explorer will open and you can double-click the running build to see its progress.</li>
<li>Go to the drop location configured above and verify that the compiled application is present and runs OK.</li>
</ol>
<h4>Custom Build Activity</h4>
<p>The template changes depend on a custom build activity, so we will need to get that in place first.</p>
<ol>
<li>Create a new source control folder called <em>CustomActivities</em> (or similar). (A logical location would be under the <em>BuildProcessTemplates</em>, or you could make both &#8220;templates&#8221; and &#8220;activities&#8221; child folders of a new <em>BuildProcess</em> folder.)</li>
<li>Download the <a href="http://tfsbuildextensions.codeplex.com/">Community TFS Build Extensions</a>. Open the zip file, copy the contents of the Visual Studio 2010 folder into the new <em>CustomActivities</em> folder, then add the files to source control and check-in.</li>
<li>In Visual Studio open the Team Explorer panel.</li>
<li>Right-click on <em>Builds </em>and select <em>Manage Build Controllers&#8230;</em></li>
<li>Select your build controller then click the <em>Properties</em> button</li>
<li>Under <em>Version control path to custom assemblies&#8230;</em> enter the path to the <em>CustomActivities</em> folder</li>
<li>Click <em>OK</em></li>
<li>You will now be back at the <em>Manage Build Controllers</em> dialog and will see that the controller and agent are both offline. This happens while new build activities are being processed. After a short while the controller then the agent should come back online.</li>
</ol>
<h4>Process Template</h4>
<p>Now we will create a customised process template and add a custom versioning activity to it.</p>
<ol>
<li>Locate the build template <em>DefaultTemplate.xaml</em> in source control, by default this is under the <em>BuildProcessTemplates</em> folder.</li>
<li>Make a copy of the file and rename it to <em>CustomTemplate.xaml</em> (or similar). Add to source control but don&#8217;t check-in yet.</li>
<li>Create a new C# class library called <em>BuildTemplates</em> and put it under the <em>BuildProcessTemplates</em> folder. Tick the box to add it to source control.</li>
<li>Delete the <em>Class1.cs</em> file.</li>
<li>In Solution Explorer right-click the project and select <em>Add -&gt; Existing Item</em> then select the <em>CustomTemplate.xaml</em> file. Click the small downwards pointing triangle on the <em>Add</em> button  and select <em>Add As Link</em>.</li>
<li>Add references to all the DLLs in the <em>CustomActivities</em> folder.</li>
<li>Add references to the following assemblies on the .NET tab of the Add Reference dialog: System.Drawing, System.Xaml, Microsoft.TeamFoundation.Build.Client, Microsoft.TeamFoundation.VersionControl.Client, Microsoft.TeamFoundation.WorkItemTracking.Client</li>
<li>Add references to the following assemblies located in folder C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\: Microsoft.TeamFoundation.Build.Workflow, Microsoft.TeamFoundation.TestImpact.BuildIntegration</li>
<li>Add a reference to the following assembly located in folder C:\Windows\assembly\GAC_MSIL\Microsoft.TeamFoundation.TestImpact.Client\10.0.0.0__b03f5f7f11d50a3a\: Microsoft.TeamFoundation.TestImpact.Client</li>
<li>Double-click <em>CustomTemplate.xaml</em> to open the workflow editor.</li>
<li>Open the Toolbox panel. You should see many workflow activities organised into different tabs.</li>
<ol>
<li>Right-click within the Toolbox and select <em>Add Tab&#8230;</em> then name the tab <em>Community TFS Build Extensions<br />
</em></li>
<li>Right-click the new tab then select <em>Choose Items&#8230;<br />
</em></li>
<li><em></em>Click the <em>Browse </em>button and navigate to the <em>BuildActivities </em>folder.</li>
<li>Select <em>TfsBuildExtensions.Activities.dll</em> then click the <em>Open</em> button.</li>
<li>Click the <em>OK </em>button</li>
<li>Right-click the toolbox tab again and select <em>Sort Items Alphabetically </em>(recommended)<em></em></li>
</ol>
<li>You should now be back at <em>CustomTemplate.xaml</em> in the editor. Click the <em>Arguments </em>tab at the bottom.</li>
<li>Add three new arguments <em>VersioningFilespec</em>, <em>DisableVersioning</em> and <em>VersioningStartDate</em> with types and defaults as shown under the <em>Arguments</em> heading below.</li>
<li>Still in the list of arguments locate the <em>Metadata </em>entry and click the ellipsis button (three little dots) in the <em>Default value</em> column. Add three entries, one for each new argument, as shown under the <em>Metadata </em>heading below. In addition, set the <em>View this parameter when: </em>drop-down for all three to <em>Always show the parameter.</em></li>
<li>Now you need to edit the workflow.</li>
<ol>
<li>Locate the activity <em>Run On Agent </em>then expand it</li>
<li>Within <em>Run On </em>Agent locate <em>Initialize Workspace</em></li>
<li>From the <em>Control Flow</em> tab of the toolbox drag an <em>If</em> activity right after <em>Initialize Workspace </em>(before<em> If CreateLabel</em>)<em><br />
</em></li>
<li>Open the properties for the <em>If </em>activity and set the <em>DisplayName </em>to <em>If Versioning</em> and the <em>Condition</em> to <em>DisableVersioning = False</em></li>
<li>Expand the <em>If Versioning</em> activity so you can see the <em>Then </em>and <em>Else</em> boxes</li>
<li>From the <em>Control Flow</em> tab of the toolbox drag a <em>Sequence</em> activity into the <em>Then</em> box then set its <em>DisplayName</em> to <em>Versioning</em></li>
<li>This should have given you some understanding of how to modify the workflow, but it would be tortuous to continue this way so we will cut-and-paste to finish this work</li>
<li>Save and close <em>CustomTemplate.xaml</em> then right-click the file in Solution Explorer and select <em>View Code.</em></li>
<li>Locate the root <em>Activity </em>node and add a new namespace attribute as follows: <em>xmlns:tat=&#8221;clr-namespace:TfsBuildExtensions.Activities.TeamFoundationServer;assembly=TfsBuildExtensions.Activities&#8221;</em></li>
<li>Find the text <em>If Versioning</em> then replace the whole <em>If</em> element with the XML shown under the heading <em>Workflow XML</em> below.</li>
<li>New close the file and re-open in the Workflow editor again. The versioning workflow should look like the example under the <em>Workflow</em> heading below.</li>
<li>Check the template and project into source control.</li>
</ol>
</ol>
<p>Note: The forthcoming Windows Workflow Foundation 4.5 has a search function which will make finding your way around the workflow much easier</p>
<p><strong>Arguments</strong></p>
<p><a href="http://www.andygeldman.com/wp-content/uploads/2012/02/new.png"><img class="alignleft size-full wp-image-994" title="new" src="http://www.andygeldman.com/wp-content/uploads/2012/02/new.png" alt="" width="739" height="159" /></a></p>
<p>.</p>
<p><strong>Metadata</strong></p>
<table style="width: 100%;" border="0" cellspacing="3" align="left">
<tbody>
<tr>
<td><strong>Parameter Name</strong></td>
<td><strong>Display Name</strong></td>
<td><strong>Category</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>VersioningFilespec</td>
<td>Files to Version</td>
<td>Versioning</td>
<td>Enter search patterns for files where version info should be updated</td>
</tr>
<tr>
<td>DisableVersioning</td>
<td>Disable Versioning</td>
<td>Versioning</td>
<td>Specify True to skip versioning assemblies; False to version as defined by the Versioning settings</td>
</tr>
<tr>
<td>VersioningStartDate</td>
<td>Start Date</td>
<td>Versioning</td>
<td>Start date for calculating build element of version number</td>
</tr>
</tbody>
</table>
<p>.</p>
<p><strong>Workflow XML</strong></p>
<pre class="brush: xml; title: ; notranslate">

&lt;If Condition=&quot;[DisableVersioning = False]&quot; DisplayName=&quot;If Versioning&quot; sap:VirtualizedContainerService.HintSize=&quot;552,995&quot; mtbwt:BuildTrackingParticipant.Importance=&quot;Low&quot;&gt;
&lt;sap:WorkflowViewStateService.ViewState&gt;
&lt;scg:Dictionary x:TypeArguments=&quot;x:String, x:Object&quot;&gt;
&lt;x:Boolean x:Key=&quot;IsPinned&quot;&gt;True&lt;/x:Boolean&gt;
&lt;x:Boolean x:Key=&quot;IsExpanded&quot;&gt;True&lt;/x:Boolean&gt;
&lt;/scg:Dictionary&gt;
&lt;/sap:WorkflowViewStateService.ViewState&gt;
&lt;If.Then&gt;
&lt;Sequence DisplayName=&quot;Versioning&quot; sap:VirtualizedContainerService.HintSize=&quot;427,889&quot;&gt;
&lt;Sequence.Variables&gt;
&lt;Variable x:TypeArguments=&quot;scg:IEnumerable(x:String)&quot; Name=&quot;VersioningFiles&quot; /&gt;
&lt;Variable x:TypeArguments=&quot;x:String&quot; Name=&quot;major&quot; /&gt;
&lt;Variable x:TypeArguments=&quot;x:String&quot; Name=&quot;minor&quot; /&gt;
&lt;Variable x:TypeArguments=&quot;x:String&quot; Name=&quot;version&quot; /&gt;
&lt;Variable x:TypeArguments=&quot;x:String&quot; Name=&quot;filecontents&quot; /&gt;
&lt;/Sequence.Variables&gt;
&lt;sap:WorkflowViewStateService.ViewState&gt;
&lt;scg:Dictionary x:TypeArguments=&quot;x:String, x:Object&quot;&gt;
&lt;x:Boolean x:Key=&quot;IsExpanded&quot;&gt;True&lt;/x:Boolean&gt;
&lt;x:Boolean x:Key=&quot;IsPinned&quot;&gt;True&lt;/x:Boolean&gt;
&lt;/scg:Dictionary&gt;
&lt;/sap:WorkflowViewStateService.ViewState&gt;
&lt;mtbwa:FindMatchingFiles DisplayName=&quot;Find Versioning Files&quot; sap:VirtualizedContainerService.HintSize=&quot;405,22&quot; mtbwt:BuildTrackingParticipant.Importance=&quot;Low&quot; MatchPattern=&quot;[SourcesDirectory &amp;amp; String.Join(&amp;quot;;&amp;quot; &amp;amp; SourcesDirectory, VersioningFilespec)]&quot; Result=&quot;[VersioningFiles]&quot; /&gt;
&lt;ForEach x:TypeArguments=&quot;x:String&quot; DisplayName=&quot;For Each File&quot; sap:VirtualizedContainerService.HintSize=&quot;405,703&quot; mtbwt:BuildTrackingParticipant.Importance=&quot;Low&quot; Values=&quot;[VersioningFiles]&quot;&gt;
&lt;sap:WorkflowViewStateService.ViewState&gt;
&lt;scg:Dictionary x:TypeArguments=&quot;x:String, x:Object&quot;&gt;
&lt;x:Boolean x:Key=&quot;IsPinned&quot;&gt;True&lt;/x:Boolean&gt;
&lt;x:Boolean x:Key=&quot;IsExpanded&quot;&gt;True&lt;/x:Boolean&gt;
&lt;/scg:Dictionary&gt;
&lt;/sap:WorkflowViewStateService.ViewState&gt;
&lt;ActivityAction x:TypeArguments=&quot;x:String&quot;&gt;
&lt;ActivityAction.Argument&gt;
&lt;DelegateInArgument x:TypeArguments=&quot;x:String&quot; Name=&quot;file&quot; /&gt;
&lt;/ActivityAction.Argument&gt;
&lt;Sequence DisplayName=&quot;Version File&quot; sap:VirtualizedContainerService.HintSize=&quot;375,597&quot; mtbwt:BuildTrackingParticipant.Importance=&quot;Low&quot;&gt;
&lt;sap:WorkflowViewStateService.ViewState&gt;
&lt;scg:Dictionary x:TypeArguments=&quot;x:String, x:Object&quot;&gt;
&lt;x:Boolean x:Key=&quot;IsExpanded&quot;&gt;True&lt;/x:Boolean&gt;
&lt;x:Boolean x:Key=&quot;IsPinned&quot;&gt;True&lt;/x:Boolean&gt;
&lt;/scg:Dictionary&gt;
&lt;/sap:WorkflowViewStateService.ViewState&gt;
&lt;mtbwa:WriteBuildMessage sap:VirtualizedContainerService.HintSize=&quot;353,22&quot; Importance=&quot;[Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High]&quot; Message=&quot;[String.Format(&amp;quot;Versioning file {0}&amp;quot;, file)]&quot; mva:VisualBasic.Settings=&quot;Assembly references and imported namespaces serialized as XML namespaces&quot; /&gt;
&lt;Assign DisplayName=&quot;Read file contents&quot; sap:VirtualizedContainerService.HintSize=&quot;353,58&quot; mtbwt:BuildTrackingParticipant.Importance=&quot;Low&quot;&gt;
&lt;Assign.To&gt;
&lt;OutArgument x:TypeArguments=&quot;x:String&quot;&gt;[filecontents]&lt;/OutArgument&gt;
&lt;/Assign.To&gt;
&lt;Assign.Value&gt;
&lt;InArgument x:TypeArguments=&quot;x:String&quot;&gt;[System.IO.File.ReadAllText(file)]&lt;/InArgument&gt;
&lt;/Assign.Value&gt;
&lt;/Assign&gt;
&lt;Assign DisplayName=&quot;Get major version&quot; sap:VirtualizedContainerService.HintSize=&quot;353,58&quot; mtbwt:BuildTrackingParticipant.Importance=&quot;Low&quot;&gt;
&lt;Assign.To&gt;
&lt;OutArgument x:TypeArguments=&quot;x:String&quot;&gt;[major]&lt;/OutArgument&gt;
&lt;/Assign.To&gt;
&lt;Assign.Value&gt;
&lt;InArgument x:TypeArguments=&quot;x:String&quot;&gt;[New System.Text.RegularExpressions.Regex(&quot;.*?assembly: AssemblyVersion\(&quot;&quot;(?&amp;lt;major&amp;gt;[\d]*)\.(?&amp;lt;minor&amp;gt;[\d]*)&quot;).Match(filecontents).Groups(&quot;major&quot;).Value]&lt;/InArgument&gt;
&lt;/Assign.Value&gt;
&lt;/Assign&gt;
&lt;Assign DisplayName=&quot;Get minor version&quot; sap:VirtualizedContainerService.HintSize=&quot;353,58&quot; mtbwt:BuildTrackingParticipant.Importance=&quot;Low&quot;&gt;
&lt;Assign.To&gt;
&lt;OutArgument x:TypeArguments=&quot;x:String&quot;&gt;[minor]&lt;/OutArgument&gt;
&lt;/Assign.To&gt;
&lt;Assign.Value&gt;
&lt;InArgument x:TypeArguments=&quot;x:String&quot;&gt;[New System.Text.RegularExpressions.Regex(&quot;.*?assembly: AssemblyVersion\(&quot;&quot;(?&amp;lt;major&amp;gt;[\d]*)\.(?&amp;lt;minor&amp;gt;[\d]*)&quot;).Match(filecontents).Groups(&quot;minor&quot;).Value]&lt;/InArgument&gt;
&lt;/Assign.Value&gt;
&lt;/Assign&gt;
&lt;tat:TfsVersion AssemblyVersion=&quot;{x:Null}&quot; Build=&quot;{x:Null}&quot; DateFormat=&quot;{x:Null}&quot; FailBuildOnError=&quot;{x:Null}&quot; IgnoreExceptions=&quot;{x:Null}&quot; Revision=&quot;{x:Null}&quot; TextEncoding=&quot;{x:Null}&quot; TreatWarningsAsErrors=&quot;{x:Null}&quot; Action=&quot;GetAndSetVersion&quot; AssemblyDescription=&quot;[BuildDetail.BuildNumber]&quot; CombineBuildAndRevision=&quot;False&quot; Delimiter=&quot;.&quot; DisplayName=&quot;Set Version&quot; Files=&quot;[{file}]&quot; ForceSetVersion=&quot;False&quot; sap:VirtualizedContainerService.HintSize=&quot;242,22&quot; mtbwt:BuildTrackingParticipant.Importance=&quot;Low&quot; LogExceptionStack=&quot;True&quot; Major=&quot;[major]&quot; Minor=&quot;[minor]&quot; PaddingCount=&quot;0&quot; PaddingDigit=&quot;&quot; SetAssemblyDescription=&quot;True&quot; SetAssemblyFileVersion=&quot;True&quot; SetAssemblyVersion=&quot;False&quot; StartDate=&quot;[VersioningStartDate]&quot; UseUtcDate=&quot;False&quot; Version=&quot;[version]&quot; VersionFormat=&quot;Elapsed&quot; VersionTemplateFormat=&quot;0.0.0.0&quot; /&gt;
&lt;mtbwa:WriteBuildMessage sap:VirtualizedContainerService.HintSize=&quot;353,22&quot; Importance=&quot;[Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High]&quot; Message=&quot;[String.Format(&amp;quot;Version has been set to {0}&amp;quot;, version)]&quot; mva:VisualBasic.Settings=&quot;Assembly references and imported namespaces serialized as XML namespaces&quot; /&gt;
&lt;/Sequence&gt;
&lt;/ActivityAction&gt;
&lt;/ForEach&gt;
&lt;/Sequence&gt;
&lt;/If.Then&gt;
&lt;/If&gt;
</pre>
<p><strong>Workflow</strong><br />
<a href="http://www.andygeldman.com/wp-content/uploads/2012/02/wf1.png"><img class="alignleft size-full wp-image-1003" title="wf" src="http://www.andygeldman.com/wp-content/uploads/2012/02/wf1.png" alt="" width="739" height="972" /></a></p>
<h4>Update Build Definition</h4>
<p>Now we need to modify the build definition created earlier to use the customised template.</p>
<ol>
<li>Right-click the build definition created earlier and select <em>Edit Build Definition&#8230;</em></li>
<li>Select <em>Process</em> on the left. On the right under <em>Build process template </em>click <em>Show details.</em></li>
<li>Click the <em>New</em> button then choose the option to <em>Select an existing XAML file</em></li>
<li>Choose <em>CustomTemplate.xaml </em>then click the <em>OK </em>button</li>
<li>You will notice the new <em>Versioning </em>parameters but don&#8217;t need to edit them &#8211; the defaults will work fine.</li>
<li>Save the build definition.</li>
<li>Right-click the build definition and select <em>Queue New Build</em> the click the <em>Queue </em>button.</li>
<li>Once the build has finished:</li>
<ol>
<li>In the build output click <em>View Log </em>and find the message saying that the version has been set</li>
<li>Go to the drop location and check that the file version matches the one generated by the build.</li>
<li>Also check that the file comments contains the full build number. Prior to Windows 7 you could simply bring up the file properties to see this. In Windows 7 it is frustratingly not shown in Windows Explorer but can be displayed using Powershell &#8211; change the directory to the drop folder containing the executable then run <em>(dir &#8220;SampleApplication.exe&#8221;).VersionInfo.Comments</em></li>
</ol>
</ol>
<h4>How it Works</h4>
<p>After the build agent retrieves the latest files from source control, the process locates files matching the pattern specified and uses community build extension <em>TfsVersion</em> to do the rest &#8211; remove the read-only flag on the file, set the version and description, then put the read-only flag back on to avoid upsetting future <em>gets</em> from source control. Compilation then proceeds as normal, oblivious to the fact that something has been changed behind the scenes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/02/step-by-step-automatically-stamp-assemblies-with-the-build-number/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Technical Debt: Don’t Take it Too Literally!</title>
		<link>http://www.andygeldman.com/index.php/2012/02/technical-debt-dont-take-it-too-literally/</link>
		<comments>http://www.andygeldman.com/index.php/2012/02/technical-debt-dont-take-it-too-literally/#comments</comments>
		<pubDate>Fri, 17 Feb 2012 16:45:47 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[ALM]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=957</guid>
		<description><![CDATA[The concept of technical debt can be a great educational tool, because it helps describe in business-friendly terms why working software is not necessarily good software. The analogy of financial debt being like substandard code is compelling &#8211; it feels intuitively right &#8211; but like all analogies if you stretch it too far it will <a href='http://www.andygeldman.com/index.php/2012/02/technical-debt-dont-take-it-too-literally/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>The concept of <em>technical debt</em> can be a great educational tool, because it helps describe in business-friendly terms why working software is not necessarily good software. The analogy of financial debt being like substandard code is compelling &#8211; it feels intuitively right &#8211; but like all analogies if you stretch it too far it will break. Before going further into that, here&#8217;s a quick summary of the mainstream understanding of &#8220;technical debt&#8221;:</p>
<ul>
<li>When you cut corners in software development you accumulate a &#8220;debt&#8221;</li>
<li>The additional effort required to do the job right is the amount of the debt</li>
<li>&#8220;Interest&#8221; must be paid, in the form of additional resources needed to support and maintain the software</li>
</ul>
<p>Anyone who has coded for a while won&#8217;t need persuading that quick and dirty hacking is a false economy, but it is tough to explain a programmer&#8217;s gut feeling for good and bad code to those who shy away from Excel formulas. However, bring in the idea of technical debt and they should start to get it pretty quickly. I introduced the concept in a recent role and found it very useful &#8211; I circulated articles, banged on about it at the drinks machine, and invited the team to an online seminar by a leading expert. They were getting it.</p>
<p>But the online seminar concerned me. The presenter was talking about quantifying technical debt, making trade-offs, and strategic technical debt. The idea of technical debt doesn&#8217;t stand up to being stretched this far, and it is dangerous when it happens because the resulting decisions will be based on a broken model. Only luck will prevent those decisions from turning out bad. Here&#8217;s where I think the analogy breaks down:</p>
<table style="width: 100%;">
<tbody>
<tr>
<td><strong>Aspect</strong></td>
<td><strong>Financial Debt</strong></td>
<td><strong>Technical Debt</strong></td>
</tr>
<tr>
<td>Visibility</td>
<td>You can&#8217;t miss it &#8211; it&#8217;s on the balance sheet</td>
<td>Invisible</td>
</tr>
<tr>
<td>Quantifiability</td>
<td>Easy to quantify by definition</td>
<td>No dependable way to quantify</td>
</tr>
<tr>
<td>Who owes who?</td>
<td>You owe someone else</td>
<td>You owe yourself</td>
</tr>
<tr>
<td>Payback</td>
<td>You must make payments</td>
<td>You aren&#8217;t obliged to pay anything back, ever</td>
</tr>
<tr>
<td>Failing to pay</td>
<td>You go bankrupt</td>
<td>Your business can continue and be successful</td>
</tr>
</tbody>
</table>
<p>.<br />
Looking at it soberly, technical debt is not much like financial debt at all. It&#8217;s an enlightening metaphor, no more.</p>
<p>What we are really trying to get people to understand through technical debt is this: quality matters, ignore it and your software will rot. It will become unreliable, risky and expensive to support and maintain, difficult to extend, and demoralising to work with. You <em>might</em> be able to hide the symptoms from customers by pouring money into the problem, but if that becomes uneconomical the cracks will open up and your reputation may suffer. What business wants that?</p>
<p>* * * * *</p>
<p>While writing this I came across a recent <a href="http://www.xndev.com/downloads/10ThoughtsTechDebt.pdf">article on the topic</a> from <a href="http://www.stickyminds.com/BetterSoftware/magazine.asp">Better Software magazine</a> &#8211; which is excellent further reading.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/02/technical-debt-dont-take-it-too-literally/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Case Study: Automated Build &amp; Deployment of a Legacy Web App</title>
		<link>http://www.andygeldman.com/index.php/2012/02/case-study-automated-build-deployment-of-a-legacy-web-app/</link>
		<comments>http://www.andygeldman.com/index.php/2012/02/case-study-automated-build-deployment-of-a-legacy-web-app/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 18:54:37 +0000</pubDate>
		<dc:creator>Andy Geldman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Build]]></category>
		<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://www.andygeldman.com/?p=904</guid>
		<description><![CDATA[In a perfect world, we would all be working on high quality greenfield projects using all the latest technologies and development practices. But often (in my experience at least) we are called on to support applications that have grown uncontrollably for many years, carrying enough technical debt to make Greece blush. But even these monstrosities <a href='http://www.andygeldman.com/index.php/2012/02/case-study-automated-build-deployment-of-a-legacy-web-app/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>In a perfect world, we would all be working on high quality greenfield projects using all the latest technologies and development practices. But often (in my experience at least) we are called on to support applications that have grown uncontrollably for many years, carrying enough technical debt to make Greece blush.</p>
<p>But even these monstrosities can benefit from modern ALM practices such as automated build and deployment. So in this post I&#8217;m going to talk about automated deployment of a real-life legacy web application using scripting, Psexec and other command-line tools &#8211; all coordinated by TFS 2010.</p>
<h4>The Scenario</h4>
<p>The application had been developed chaotically by many people over a decade or more using every Microsoft technology you could name: C++, VB, VBScript, VBA, C#, .NET 1.1, .NET 2.0, ASP, ASP.NET&#8230; you name it, it was in there somewhere. There had never been a rewrite, re-architecting or even any hints of refactoring. Yet development on this key application continued, and while there was an appreciation that things needed to improve there was certainly no appetite for any major rework.</p>
<h4>The Challenge</h4>
<p>The goal was to improve quality and productivity, and reduce risk. I know it&#8217;s a cliché, but the way to eat an elephant is one bite at a time, and that is how I approached this problem. The steps below were taken to tame this beast, tentatively, over several months while development continued relatively uninterrupted:</p>
<ol>
<li>Migrated source control from Visual SourceSafe to TFS 2010 (there is plenty of documentation on this, just make sure you practice before doing the real migration).</li>
<li>Productised the application &#8211; defined the elements that it is (and isn&#8217;t) made of, and got them all organised in source control to establish a &#8220;single source of truth&#8221;.</li>
<li>Migrated issue tracking from a proprietary system to TFS 2010 Work Items so changes going forward are transparently tracked.</li>
<li>Got the application to compile with a minimal (but fully documented) set of components required to be installed. Later work cleaned up referenced dependencies, which were scattered and sometimes in conflict.</li>
<li>Introduced TFS automated builds, starting with continuous integration.</li>
</ol>
<p>So far, so good. By this point, we knew what we were dealing with and were building it on every check-in. There were even unit tests &#8211; which were patchy in coverage and quality, but much better than nothing.</p>
<p>The next step was to get this caged monster deploying to a test environment, fully automated, starting from a standard base configuration. The existing  process was documented as manual steps over dozens of pages, and it still wouldn&#8217;t work first time &#8211; days would be lost &#8220;setting it up&#8221; after following the install procedure. If you can&#8217;t easily deploy your application onto fresh hardware, then something is seriously wrong.</p>
<p>The benefits of a clean and endlessly repeatable deployment process are many, but getting there wouldn&#8217;t be easy.</p>
<h4>WebDeploy</h4>
<p>An early decision was made to restrict the deployment to a collection of ASP.NET web applications, as this was the more modern part of the app, and under constant development. The latest and greatest technology for this is the unimaginatively named <em>Web Deployment Tool</em>, also known as <em>WebDeploy</em> and <em>MSDeploy</em>, which is built on top of <em>MSBuild</em> &#8211; Microsoft&#8217;s core compilation technology.</p>
<p>We spent a good deal of time working with WebDeploy, but it turned into a battle. The constraints of old application and OS technology, and multiple web applications were a big headache and the pretty Visual Studio tooling soon fell short, leaving us working directly with MSBuild files.</p>
<p>Personally, I like the change of direction in TFS 2010 to restrict MSBuild to compilation, and use Windows Workflow for build &#8220;orchestration&#8221;. Once you go beyond compilation and directly related activities, changing XML-based MSBuild scripts feels awkward compared to the intuitive free-flow of WF (the abbreviation is not WWF &#8211; I think even Microsoft is <a href="http://news.bbc.co.uk/1/hi/uk/1974600.stm">scared of the World Wide Fund for Nature</a>). So we ditched WebDeploy and decided to roll our own TFS Build and scripting solution.</p>
<h4>The Solution</h4>
<p>I came across many issues as I put our deployment solution together, so I will set the whole process out here and pick out the problems.</p>
<h5>When to Deploy</h5>
<p>The default TFS build process template is necessarily complex, and I intuitively put an <em>Invoke Process</em> activity to start the deployment after the steps which compile and test the solution. However, our solution had functional tests (calling high-level methods which use web services and the database) so you would get test failures because the tests relied on the deployment itself. So I simply moved the deployment step before the tests, and ensured any parts which the tests depended on would run synchronously so they finished before the tests started (more on this later).</p>
<p>There is a potential downside to this, which is that the compile and test steps are within a for-each loop for each solution and configuration combination. If you compile more than one solution and/or configuration in your build definition (which I personally don&#8217;t like to do) it will get messy. The deployment would run multiple times, but if you added a condition of some sort to ensure it runs only after the last compilation, it might be too late for any tests which depend on it. I didn&#8217;t need to deal with this issue, but controlling the order of compilation and breaking up the deployment seems like a solution. Another option would be to have multiple builds, each with a single solution and configuration, and have one build trigger the next.</p>
<h5>Passing Parameters</h5>
<p>It is very useful to pass information from the build definition and build system through to the deployment scripts. To achieve this I created a handful of new arguments in a new &#8220;Deployment&#8221; category, including:</p>
<ul>
<li>An on/off toggle</li>
<li>Email addresses to notify of build completion</li>
<li>Processes to invoke to do the deployment</li>
<li>Text about the deployment to display in the build log</li>
</ul>
<p>The processes argument could include placeholders in curly braces, which the build template was customised to recognise and replace appropriately. For example, placeholders of {BUILDNUMBER} and {BUILDID} would be substituted by the actual build number and numeric build ID respectively. The scripts could use this information to stamp the website with a build number and send an email with a link to the TFS Web Access version of the build log. (Incidentally, it&#8217;s an annoyance for a pedant like me that the build number is not a number, that&#8217;s the build ID &#8211; am I alone in being bothered by that?)</p>
<p><a href="http://www.andygeldman.com/wp-content/uploads/2012/02/Snap-2012-02-16-at-16.58.59.png"><img class="alignleft size-full wp-image-922" title="Snap 2012-02-16 at 16.58.59" src="http://www.andygeldman.com/wp-content/uploads/2012/02/Snap-2012-02-16-at-16.58.59.png" alt="" width="678" height="282" /></a></p>
<p>.</p>
<h5>Strategy</h5>
<p>I settled on a fairly simple process that worked for the first application and all those it was extended to. It used a file share on the target server as a working folder, and went like this:</p>
<ol>
<li>Clear the file share on the target server</li>
<li>Copy the scripts and any other files to the file share on the target server</li>
<li>Repeat steps 1 and 2 if there are multiple servers in the deployment</li>
<li>Stop application websites and start the maintenance website on the remote server(s). I used Psexec for this initially but found it unreliable (more on that later) so switched to iisweb with much better results</li>
<li>Package the application into one or more zip files.</li>
<ol>
<li>I used the 7-Zip command line tool <em>7za.exe</em>, and a combination of copy and xcopy. Temporarily I used the incredibly flexible robocopy to deal with the horrible consequences of referencing different versions of the same assembly from different projects in the same solution &#8211; the application was fixed properly later.</li>
<li>Any web.config or app.config transforms will need to take place before this step. I posted <a href="http://www.andygeldman.com/index.php/2011/10/web-and-app-config-transformations-with-tfs-build/">previously</a> about how to trigger this without a full publish action.</li>
</ol>
<li>Copy the zip package(s) to the target server(s)</li>
<li>Run the deployment actions in an inside-out sequence. So in a three-tier architecture: database, then the application layer, then the UI layer.</li>
<ul>
<li>I used Psexec to asynchronously hand over the deployment to each target server. This takes the load off the build server and means the deployment runs as a process local to the server, which can be helpful for security and performance reasons.</li>
<li>If you want the build server to wait for the some or all of the deployment to finish, either run the deployment remotely from the build server or use a signal such as a &#8220;semaphore file&#8221; to tell the build server when the process is complete (see the ALM Rangers build guidance for more on that).</li>
<li>If using 7-Zip to extract zip files use the <em>-y</em> switch to avoid prompts hanging the process.</li>
</ul>
<li>When the deployment actions were complete, the final server in the deployment sequence was scripted to:</li>
<ol>
<li>Stop the maintenance website and start the application&#8217;s website</li>
<li>Copy all the generated logs into the build drop folder</li>
<li>Send an email notification of the deployment</li>
</ol>
</ol>
<p>Preparatory steps and signposting of deployment steps were output into the build log itself, but process calls with extensive output were set to use log files instead. The build log doesn&#8217;t lend itself well to very verbose logging.</p>
<h5>Psexec</h5>
<p>This is a command line tool from Sysinternals which performs the magic of triggering a process on a remote machine. It is very temperamental about how it is used but not unreliable once you find a stable usage pattern. Here are the lessons I learned:</p>
<ul>
<li>Admin shares (<em>\\server\C$</em> style file shares) need to be enabled on the remote machine.</li>
<ul>
<li>This requires some one-time config changes if the server has been hardened against it (which should only be done on an internal network with appropriate approval). I needed to set <em>Server</em> and <em>Computer Browser</em> services to run automatically, set registry key <em>HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters</em> to 1, and kill/restart the explorer.exe process.</li>
</ul>
<li>The full path to Psexec is needed for it to be found by the build agent (even if it is under the PATH environment variable)</li>
<li><em>cmd /c</em> is necessary to run Psexec from an <em>InvokeProcess</em> build activity as it is a console command, not a standalone executable</li>
<li>Psexec returns its own output as StdErr, causing the build log to contain an error for every line of output &#8211; and failing the whole build. You can use output handler <em>2&gt;&amp;1</em> to push StdErr into StdOut.</li>
<li>Psexec likes to output empty lines but you can strip them out within (or before) a <em>WriteBuildMessage</em> activity</li>
<li>For reliability I found I needed switches <em>-d</em> and <em>-accepteula</em> to run non-interactively and accept the embedded license agreement (the latter is common to Sysinternals tools).</li>
<li>I used Psexec only once per server, which seemed necessary to avoid overlapping processes (I don&#8217;t know why that should have been a problem, but it caused poor reliability). Having this constraint actually helped ensure the deployment process was well structured.</li>
<li>If you don&#8217;t specify a user account, Psexec uses impersonation which may result in the remote machine lacking access to network resources. This can be avoided by explicitly passing the username and password.</li>
<li>To pass the output of a remotely executed command to a log requires a middle-man script on the remote server. If you try to log on the calling server, you will get the output of Psexec itself, not the command being called.</li>
</ul>
<h5>Shared Deployment Scripts</h5>
<p>This deployment strategy was later reused for other applications. To avoid duplication of componentised scripts and other shared items, I moved them to their own source folder and included them in the workspace of the build definition. You can&#8217;t map two source folders into the same working folder, so you have to figure out the correct relative paths, but it&#8217;s a small price to pay for the elimination of duplication (<a href="http://www.quora.com/Duplication-Is-Evil-DIE">it&#8217;s evil!</a>)</p>
<h4>Summary</h4>
<p>I will readily admit that this deployment approach is a little archaic. It&#8217;s also littered with gotchas, but new technology is not immune from that either.</p>
<p>Going forward, WebDeploy is still my first choice whenever possible. But if faced again with a trade-off between extensive MSBuild scripting and relatively transparent TFS Build + Windows scripting, I would still go for the latter.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andygeldman.com/index.php/2012/02/case-study-automated-build-deployment-of-a-legacy-web-app/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

