<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;C0AFRXc4eCp7ImA9WhdSGU0.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248</id><updated>2011-07-28T19:08:34.930-06:00</updated><category term="Build Automation" /><category term="Boise Code Camp" /><category term="Continuous Integration" /><category term="TDD" /><category term="MSpec" /><category term="BDD" /><category term="TeamCity" /><category term="Esoterica" /><title>CodeProgression.com</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://codeprogression.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/codeprogression" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="codeprogression" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DEEERno-fCp7ImA9WxFbF0k.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-8069416748416576500</id><published>2010-07-10T01:23:00.001-06:00</published><updated>2010-07-10T01:23:27.454-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-10T01:23:27.454-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Esoterica" /><title>Defining Development Experience</title><content type="html">&lt;p&gt;Friday morning, one of my colleagues asked, “What do you consider to be the difference between a junior, mid-level, and senior developer?” &lt;/p&gt;  &lt;p&gt;Head over to &lt;a href="http://elegantcode.com/2010/07/10/defining-development-experience/"&gt;Elegant Code&lt;/a&gt; to see my response.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-8069416748416576500?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/PlHvJ3trFGM" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2010/07/defining-development-experience.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/8069416748416576500?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/8069416748416576500?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2010/07/defining-development-experience.html" title="Defining Development Experience" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkABRHs4eCp7ImA9WxBaF0Q.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-6959654061372987700</id><published>2010-03-28T11:52:00.001-06:00</published><updated>2010-03-28T11:52:35.530-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-28T11:52:35.530-06:00</app:edited><title>Boise Code Camp 2010: Distributed Event-Driven Architecture Session Notes</title><content type="html">&lt;p&gt;I presented a session on event-driven architecture (with examples using NServiceBus) at Boise Code Camp yesterday.&amp;#160; I had a great turnout and great feedback. Thanks so much to those who attended!&amp;#160; &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;If you attended and have any feedback/constructive criticism, please leave a comment!&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;For those who missed the session – or for those who would like to see it again – you will get another opportunity. I will be presenting this session at &lt;a href="http://www.netdug.com/" target="_blank"&gt;NETDUG&lt;/a&gt; (in April, I believe).&amp;#160; I am also submitting the session to &lt;a href="http://portlandcodecamp.org" target="_blank"&gt;Portland Code Camp&lt;/a&gt;.&lt;/p&gt;  &lt;h4&gt;Session Assets&lt;/h4&gt;  &lt;p&gt;As promised, I have included, in an &lt;a href="http://code.google.com/p/codeprogression/source/browse/sample-projects/CodeProgression.BCC2010.zip" target="_blank"&gt;archive&lt;/a&gt;:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The slide deck &lt;/li&gt;    &lt;li&gt;The solution as completed during the session (CodeProgression.BCC2010) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I have also included:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The solution with which we started (CodeProgression.BCC2010.Start) &lt;/li&gt;    &lt;li&gt;A solution based on a MassTransit sample (from which I based the NServiceBus sample) &lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Notes about the solutions:&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;If you are planning on working the NServiceBus sample from scratch, don’t forget to add the NServiceBus.Host.exe as the startup program for each endpoint project.&lt;/p&gt;    &lt;p&gt;For the MassTransit solution, you may need to update the &lt;em&gt;references\masstransit\MassTransit.RuntimeServices.exe.config&lt;/em&gt; to point to your local database.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Resources&lt;/h4&gt;  &lt;p&gt;Here is also a list of resources I used while preparing for this session:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;NServiceBus        &lt;br /&gt;&lt;/u&gt;&lt;/strong&gt;&lt;a href="http://www.nservicebus.com"&gt;http://www.nservicebus.com&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://gurustop.net/blog/2008/04/20/enterprise-service-bus-messaging-using-nservicebus/"&gt;http://gurustop.net/blog/2008/04/20/enterprise-service-bus-messaging-using-nservicebus/&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://elegantcode.com/2009/10/09/exploring-nservicebus/"&gt;http://elegantcode.com/2009/10/09/exploring-nservicebus/&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://sourceforge.net/apps/mediawiki/nservicebus/index.php?title=Tutorials"&gt;http://sourceforge.net/apps/mediawiki/nservicebus/index.php?title=Tutorials&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://blog.zoolutions.se/post/2010/02/08/Conquering-NServiceBus-part-1-e28093-Getting-Started.aspx"&gt;http://blog.zoolutions.se/post/2010/02/08/Conquering-NServiceBus-part-1-e28093-Getting-Started.aspx&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://blog.zoolutions.se/post/2010/02/09/Conquering-NServiceBus-part-2-e28093-Initial-configuration.aspx"&gt;http://blog.zoolutions.se/post/2010/02/09/Conquering-NServiceBus-part-2-e28093-Initial-configuration.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;MassTransit        &lt;br /&gt;&lt;/u&gt;&lt;/strong&gt;&lt;a href="http://masstransit.pbworks.com/A-First-Look-at-Mass-Transit"&gt;http://masstransit.pbworks.com/A-First-Look-at-Mass-Transit&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://blogs.dovetailsoftware.com/blogs/kmiller/archive/2009/08/26/producing-and-consuming-messages-using-masstransit-and-structuremap.aspx"&gt;http://blogs.dovetailsoftware.com/blogs/kmiller/archive/2009/08/26/producing-and-consuming-messages-using-masstransit-and-structuremap.aspx&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://rhysc.blogspot.com/2009/05/getting-started-with-masstransit.html"&gt;http://rhysc.blogspot.com/2009/05/getting-started-with-masstransit.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;TopShelf        &lt;br /&gt;&lt;/u&gt;&lt;/strong&gt;&lt;a href="http://blogs.dovetailsoftware.com/blogs/kmiller/archive/2010/01/20/configuring-topshelf-using-a-structuremap-container.aspx"&gt;http://blogs.dovetailsoftware.com/blogs/kmiller/archive/2010/01/20/configuring-topshelf-using-a-structuremap-container.aspx&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://blogs.dovetailsoftware.com/blogs/kmiller/archive/2010/01/20/controlling-application-lifetime-in-topshelf.aspx"&gt;http://blogs.dovetailsoftware.com/blogs/kmiller/archive/2010/01/20/controlling-application-lifetime-in-topshelf.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Misc        &lt;br /&gt;&lt;/u&gt;&lt;/strong&gt;&lt;a href="http://www.enterpriseintegrationpatterns.com"&gt;http://www.enterpriseintegrationpatterns.com&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://www.enterpriseintegrationpatterns.com/ramblings/18_starbucks.html"&gt;http://www.enterpriseintegrationpatterns.com/ramblings/18_starbucks.html&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://www.amazon.com/Enterprise-Integration-Patterns-Designing-Deploying/dp/0321200683"&gt;http://www.amazon.com/Enterprise-Integration-Patterns-Designing-Deploying/dp/0321200683&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-6959654061372987700?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/AId9xawuows" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2010/03/boise-code-camp-2010-distributed-event.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/6959654061372987700?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/6959654061372987700?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2010/03/boise-code-camp-2010-distributed-event.html" title="Boise Code Camp 2010: Distributed Event-Driven Architecture Session Notes" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0cHRH04cCp7ImA9WxBUFU0.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-2054718049155041191</id><published>2010-03-01T20:36:00.001-07:00</published><updated>2010-03-01T20:37:15.338-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-01T20:37:15.338-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term="MSpec" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>An Evolution of Test-Specification Styles – My Journey to MSpec</title><content type="html">&lt;p&gt;Over the last few years, the practice of Test-Driven Design and Behavior-Driven Design has increased in acceptance, even if its practice has not increased in equal proportion.&amp;#160; From my perspective, specification-based design is a natural way to develop software.&amp;#160; Each developer has a preferred framework, and a framework they loathe. &lt;/p&gt;  &lt;p&gt;I have changed my style of testing over the years, using different frameworks.&amp;#160; My current favorite is MSpec.&amp;#160; Check out how my style has changed at &lt;a href="http://elegantcode.com/2010/03/01/an-evolution-of-test-specification-styles-my-journey-to-mspec/"&gt;elegantcode.com&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-2054718049155041191?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/abFYBJgSvkY" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2010/03/evolution-of-test-specification-styles.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/2054718049155041191?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/2054718049155041191?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2010/03/evolution-of-test-specification-styles.html" title="An Evolution of Test-Specification Styles – My Journey to MSpec" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0ADQ3kzcCp7ImA9WxNaFUs.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-8081172036670834948</id><published>2009-11-30T00:22:00.001-07:00</published><updated>2009-11-30T00:22:52.788-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-30T00:22:52.788-07:00</app:edited><title>Wrapping up the StructureMap Automocking Container</title><content type="html">&lt;p&gt;I have been using StructureMap.AutoMocking with MSpec (Machine.Specifications) and Rhino.Mocks for a few months now.&amp;#160; Although I am very comfortable with the patterns that emerge from using the frameworks together, introducing StructureMap.Automocking to other developers is sometimes challenging. &lt;/p&gt;  &lt;p&gt;When viewing a specification or test set up with the Rhino.Mocks or Moq automocking container, what is being tested is not readily apparent.&amp;#160; Once the concept is explained and demonstrated, these same developers seem to have no issue with maintaining the specifications/tests.&amp;#160; &lt;/p&gt;  &lt;p&gt;I decided to wrap the details of the container to make the intention clearer and explanation easier.&amp;#160; I have started using this wrapper in my projects, and have found it makes building up specifications more efficient in my daily coding. &lt;/p&gt;  &lt;p&gt;See the full post at &lt;a href="http://elegantcode.com/2009/11/30/wrapping-up-the-structuremap-automocking-container/" target="_blank"&gt;ElegantCode.com&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-8081172036670834948?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/2OWXWqG5VJQ" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/11/wrapping-up-structuremap-automocking.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/8081172036670834948?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/8081172036670834948?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/11/wrapping-up-structuremap-automocking.html" title="Wrapping up the StructureMap Automocking Container" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D08ERHo7fSp7ImA9WxNUEU4.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-6480926051218161191</id><published>2009-11-01T21:23:00.001-07:00</published><updated>2009-11-01T21:23:25.405-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-01T21:23:25.405-07:00</app:edited><title>State Pattern, Enumeration Class and Fluent NHibernate (Oh my!)</title><content type="html">&lt;p&gt;Recently, I needed to change a basic enumeration into a full-fledged state pattern. After getting all my domain classes updated, I began reviewing the persistence layer. And I hit a wall.&amp;#160; I wasn’t sure how I wanted to update my Fluent NHibernate convention to persist the current state.&lt;/p&gt;  &lt;p&gt;See the complete post on &lt;a href="http://elegantcode.com/2009/11/01/state-pattern-enumeration-class-and-fluent-nhibernate-oh-my/" target="_blank"&gt;ElegantCode.com&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-6480926051218161191?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/yYQ2ybMh-NY" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/11/state-pattern-enumeration-class-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/6480926051218161191?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/6480926051218161191?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/11/state-pattern-enumeration-class-and.html" title="State Pattern, Enumeration Class and Fluent NHibernate (Oh my!)" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEAMQXg-fSp7ImA9WxNXGEQ.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-52690978732038513</id><published>2009-10-06T23:19:00.001-06:00</published><updated>2009-10-06T23:19:40.655-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-06T23:19:40.655-06:00</app:edited><title>AutoMapper Introduction and Samples from NETDUG</title><content type="html">&lt;p&gt;&lt;em&gt;In September, Cory Isakson and I presented AutoMapper to the Boise .NET Developer User Group (NETDUG).&amp;#160; As promised, I have included the sample code &lt;/em&gt;&lt;a href="http://code.google.com/p/codeprogression/source/browse/sample-projects" target="_blank"&gt;&lt;em&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&amp;#160; AutoMapper 1.0 RC1 is available on the &lt;a href="automapper.codeplex.com" target="_blank"&gt;CodePlex&lt;/a&gt; site. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The complete post is available on &lt;a href="http://elegantcode.com/2009/10/06/automapper-introduction-and-samples-from-netdug/" target="_blank"&gt;Elegant Code&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-52690978732038513?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/PGOA_qXHPls" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/10/automapper-introduction-and-samples.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/52690978732038513?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/52690978732038513?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/10/automapper-introduction-and-samples.html" title="AutoMapper Introduction and Samples from NETDUG" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0QMQXs-fip7ImA9WxJaGEU.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-414038478439880904</id><published>2009-08-09T23:15:00.001-06:00</published><updated>2009-08-09T23:16:20.556-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-09T23:16:20.556-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Build Automation" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity" /><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration" /><title>Implementing Team City for .NET Projects, Part 5: Deployments</title><content type="html">&lt;p&gt;My apologies to all those who have been waiting for the deployment scenario – I appreciate your patience.&amp;#160; My approach to deployments has been a moving target – as it is starting to firm up a bit, I thought&amp;#160; I would write down some thoughts.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;For more information on this series, please see the &lt;/em&gt;&lt;a title="Implementing TeamCity introduction" href="http://codeprogression.blogspot.com/2009/03/implementing-teamcity-for-net-projects.html" target="_blank"&gt;introductory post&lt;/a&gt;&lt;em&gt;&lt;/em&gt;&lt;em&gt;.&lt;/em&gt; In the &lt;a href="http://codeprogression.blogspot.com/2009/05/implementing-teamcity-for-net-projects.html" target="_blank"&gt;previous post&lt;/a&gt;, I discussed build scripts as a way of extending the functionality of TeamCity.&amp;#160; If you downloaded the sample solution, you could see the tasks and structure of the NAnt and Rake scripts.&amp;#160; Since then, I have fully embraced Rake as my default build script engine; therefore, my script examples in this post are Rake scripts.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Don’t forget to listen to &lt;a href="http://elegantcode.com/2009/07/23/code-cast-28-jim-wierich/" target="_blank"&gt;Elegant Code Cast #28&lt;/a&gt; , where Chris Brandsma and I had the privilege of speaking with Jim Wierich, the father of Rake.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I have modeled the Rake scripts after the Fluent NHibernate and FubuMVC scripts.&amp;#160; I am also very interested in rake-dotnet from Pete Mounce.&amp;#160; Once rake-dotnet has support for NUnit and MSpec, I will be migrating my scripts to use it as a base library.&amp;#160; (Pete, I am actually planning on a patch for both – you know…in my spare time.)&amp;#160; Rake-dotnet is definitely worth checking out, especially if you use xUnit as your test library.&lt;/p&gt;  &lt;h4&gt;The Deployment Process&lt;/h4&gt;  &lt;p&gt;Here is a representation of my preferred folder structure for a solution:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_bGTiQEGe9PE/Sn-sy-TloPI/AAAAAAAAAEw/ipYZFspkHB4/s1600-h/image%5B21%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="before build" border="0" alt="before build" src="http://lh4.ggpht.com/_bGTiQEGe9PE/Sn-szLN0SRI/AAAAAAAAAE0/GEdYyA5wpkw/image_thumb%5B11%5D.png?imgmax=800" width="160" height="232" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The following tasks are completed on each check-in:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;MSBuild is called to clean and build both debug and release versions of the projects in the solution &lt;/li&gt;    &lt;li&gt;Tests are run &lt;/li&gt;    &lt;li&gt;An archive is created of each site and/or binaries (both debug and release versions), build scripts, and possibly SQL scripts &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;A post-build event is run on each web application project to pre-compile the site into a specific directory for each compilation type. My post build event looks like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe&amp;#160; &lt;br /&gt;–nologo -errorstack -f -u -c -p $(ProjectDir) -v temp       &lt;br /&gt;$(SolutionDir)\Build\results\PrecompiledWeb\$(ConfigurationName)\$(TargetName)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The post-build event is also a good place to add any plug-in type binaries not directly depended on by your site, but included in your solution. Each site also has a set of configuration sources for each environment up the chain (nightly, test, staging, production)&lt;/p&gt;  &lt;p&gt;After the build, I have added several folders and archive files to the build directory:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_bGTiQEGe9PE/Sn-sz2HgsbI/AAAAAAAAAE4/6rt-2zt-HxU/s1600-h/image%5B25%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="after build" border="0" alt="after build" src="http://lh4.ggpht.com/_bGTiQEGe9PE/Sn-s0UP7HKI/AAAAAAAAAE8/K7_wd91RQCI/image_thumb%5B13%5D.png?imgmax=800" width="167" height="231" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The archive files are stored in subsequent builds.&amp;#160; I never have to rebuild my solution for each platform.&amp;#160; Here is an example artifact path definition:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_bGTiQEGe9PE/Sn-s0e7_gvI/AAAAAAAAAFA/YPdobQlp0Bo/s1600-h/image%5B36%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_bGTiQEGe9PE/Sn-s02xxlHI/AAAAAAAAAFE/JNWW2m1OwBU/image_thumb%5B18%5D.png?imgmax=800" width="244" height="74" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;For the nightly build artifacts, I have the following definitions:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;build/*=&amp;gt;Build      &lt;br /&gt;build/results/Debug.zip=&amp;gt;Sites       &lt;br /&gt;build/results/Release.zip=&amp;gt;Sites       &lt;br /&gt;build/results/DebugBinaries.zip=&amp;gt;Binaries       &lt;br /&gt;build/results/ReleaseBinaries.zip=&amp;gt;Binaries&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;For subsequent builds, the definitions change slightly:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;build/**/*=&amp;gt;build      &lt;br /&gt;sites/**/*=&amp;gt;sites       &lt;br /&gt;binaries/**/*=&amp;gt;binaries&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;When the nightly build is run:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;The check-in build is run, if it has pending changes&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;The desired (debug or release) site is unzipped and pushed to the nightly build site&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;The configuration files for the site are overwritten with the nightly build environment files &lt;em&gt;(See script below) You may update the configuration files before or after pushing your site, depending on your preference)&lt;/em&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;Artifacts of the sites, binaries, and build scripts are stored with the build on TeamCity&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;Smoke test the sites (see script below)&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;When a subsequent environment is run:    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;Clean all files before build (checkmark on the VCS configuration page for the build)&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;The artifacts from the dependent build are retrieved (configured from the dependencies page of the build configuration).        &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_bGTiQEGe9PE/Sn-s1QpSiJI/AAAAAAAAAFI/7Fyip6yc1zs/s1600-h/image%5B44%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_bGTiQEGe9PE/Sn-s1oLjlrI/AAAAAAAAAFM/SQU64SFt1F0/image_thumb%5B22%5D.png?imgmax=800" width="244" height="154" /&gt;&lt;/a&gt; &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;The build tools are retrieved from source control using an edit checkout rule (+:lib)        &lt;br /&gt;&lt;em&gt;Whereas the compile-check and nightly build configurations get the entire folder structure from version control, the subsequent builds only retrieve the &lt;strong&gt;lib&lt;/strong&gt; directory.          &lt;br /&gt;&lt;/em&gt;&lt;em&gt;&lt;a href="http://lh3.ggpht.com/_bGTiQEGe9PE/Sn-s1-tsZ_I/AAAAAAAAAFQ/7dkWeY8E6QE/s1600-h/image%5B41%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/Sn-s2Evj4JI/AAAAAAAAAFU/OO0clXTsrg8/image_thumb%5B21%5D.png?imgmax=800" width="244" height="135" /&gt;&lt;/a&gt;&lt;/em&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;The existing site is archived&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;The new site is unzipped and pushed&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;The configuration files for the site are overwritten with the specific environment files&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;Artifacts of the sites, binaries, and build scripts are stored with the build on TeamCity&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;Smoke test the sites&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;The idea is to feed up the chain of deployments the artifacts needed to complete the next deployment.&amp;#160; It takes a little trial and error to get it right, but the benefits are worth it.&amp;#160; Our current builds at &lt;a href="http://www.unitymg.com" target="_blank"&gt;Unity Media Group&lt;/a&gt; take 2 to 3 minutes for the compile check (including test runs and zipping files), then approximately 45 seconds to deploy the site on the internal network.&lt;/ul&gt;  &lt;p style="margin-right: 0px"&gt;What I have not automated yet (but would like to):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;Reconfiguring the sites to point to a maintenance page while deploying&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;Running the SQL schema compare and integration&lt;em&gt; &lt;/em&gt;or run update scripts         &lt;br /&gt;&lt;em&gt;-- I have run compare/integration scripts previously, but they tended to be more hassle than running them manually.&amp;#160; Still looking for better ways to do this, though.&lt;/em&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;If building binaries for use by other projects, update those projects with the new binaries&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div style="margin-right: 0px"&gt;Run data scrubbing scripts (for creating known default environments for test or demonstration sites)&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;   &lt;h4&gt;     &lt;ul&gt;Rake File Snippets&lt;/ul&gt;   &lt;/h4&gt; To update the configuration files, I define the following method in my helper file:&lt;/ul&gt;  &lt;pre class="brush: ruby;"&gt; # UPDATING CONFIGURATION FILES &lt;br /&gt; def copyToDirectory(zip_file, website_dir, config_type)&lt;br /&gt;  throw(&amp;quot;ZipFile does not exist!&amp;quot;, zip_file) unless File.exist?(zip_file)&lt;br /&gt;  seven_zip = SevenZip.new :ziparchive =&amp;gt;  zip_file, :directory=&amp;gt;website_dir&lt;br /&gt;  seven_zip.unzip&lt;br /&gt;&lt;br /&gt;  # WEB_PROJECTS: list of web application projects with a Config directory&lt;br /&gt;  #     =&amp;gt; WEB_PROJECTS = &lt;br /&gt;  #        ['ElegantCode.Example.Administration', &lt;br /&gt;  #        'ElegantCode.Example.Client', &lt;br /&gt;  #        'ElegantCode.Example.Services']&lt;br /&gt;  WEB_PROJECTS.each do |site|&lt;br /&gt;  puts &amp;quot;##teamcity[progressMessage 'Updating application settings for #{site}']&amp;quot;&lt;br /&gt;    list=FileList.new(&amp;quot;#{website_dir}/#{site}/Config/*-#{config_type}.config&amp;quot;)&lt;br /&gt;    list.each do |file|&lt;br /&gt;      target = file.gsub(&amp;quot;-#{config_type}&amp;quot;,'')&lt;br /&gt;      puts &amp;quot;##teamcity[progressMessage 'Copying #{file.to_s} to #{target.to_s}']&amp;quot;&lt;br /&gt;      cp file,target&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And this is how I use it in the rakefile:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;# USAGE:&lt;br /&gt;zip_file = File.expand_path(File.join(&amp;quot;..&amp;quot;,&amp;quot;Sites&amp;quot;, 'Debug.zip'))&lt;br /&gt;website_dir = File.join('Z:', 'AdventureMVC')&lt;br /&gt;copyToDirectory zip_file, website_dir, 'sandbox'&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Similarly, to smoke test the site, I have the following class in my helper file:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;# SMOKE TEST &lt;br /&gt;class PreJIT&lt;br /&gt;    attr_reader :sites&lt;br /&gt;&lt;br /&gt;    def self.compile(sites)&lt;br /&gt;        sites.each do |site|&lt;br /&gt;            puts &amp;quot;##teamcity[progressMessage 'Pre-jitting #{site}']&amp;quot;&lt;br /&gt;            open (site)&lt;br /&gt;        end&lt;br /&gt;    end&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And this is how I use it:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;# USAGE:&lt;br /&gt;sites = ['http://test.example.com/admin', 'http://test.example.com']&lt;br /&gt;PreJIT.compile(sites)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;If the site&amp;#160; has a 40x/50x error, the build will fail.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There is much more to the rake scripts; however, you should peruse the rake files from Fluent NHibernate or FubuMVC for more ideas on writing your own Rake scripts.&amp;#160; You can incorporate rake-dotnet into your rake environment, as well.&amp;#160; Finally, you can accomplish the same tasks using MSBuild or NAnt, if you feel more confident in those environments.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Until next time..&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a title="Fluent NHibernate on googlecode" href="http://code.google.com/p/fluent-nhibernate/" target="_blank"&gt;Fluent NHibernate&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;a title="FubuMVC on googlecode" href="http://code.google.com/p/fubumvc/" target="_blank"&gt;FubuMVC&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;a title="rake-dotnet on GitHub" href="http://github.com/petemounce/rake-dotnet/tree/master" target="_blank"&gt;rake-dotnet&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;a href="http://www.jetbrains.com/teamcity" target="_blank"&gt;TeamCity&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;a href="http://rake.rubyforge.org/" target="_blank"&gt;Rake&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-414038478439880904?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/7A2ZKhlgu0k" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/08/implementing-team-city-for-net-projects.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/414038478439880904?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/414038478439880904?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/08/implementing-team-city-for-net-projects.html" title="Implementing Team City for .NET Projects, Part 5: Deployments" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_bGTiQEGe9PE/Sn-szLN0SRI/AAAAAAAAAE0/GEdYyA5wpkw/s72-c/image_thumb%5B11%5D.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;A0IHRHg-fSp7ImA9WxJQEk8.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-4741698710175178330</id><published>2009-05-24T21:57:00.003-06:00</published><updated>2009-05-24T23:32:15.655-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-24T23:32:15.655-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Build Automation" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity" /><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration" /><title>Implementing TeamCity for .NET Projects, Part 4: Using Build Scripts</title><content type="html">&lt;p&gt;&lt;em&gt;For more information on this series, please see the &lt;/em&gt;&lt;a title="Implementing TeamCity introduction" href="http://codeprogression.blogspot.com/2009/03/implementing-teamcity-for-net-projects.html" target="_blank"&gt;introductory post&lt;/a&gt;&lt;em&gt;&lt;/em&gt;&lt;em&gt;.  This post also assumes that you have completed parts &lt;a title="Just Build It!" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects.html" target="_blank"&gt;1&lt;/a&gt;-3.  The sample solution has been updated with new build scripts as of May 24, 2009.  If you have downloaded the solution previously, please download the updated solution.  You can explore the source or create a working copy.  A zip file has been provided for you to download to import into your own writeable repository.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;For more advanced or complex build scenarios, the build it solution runners prove somewhat inflexible.  Once you have arrived at this conclusion, you will most likely start investigating some of the other build runner options.&lt;/p&gt;  &lt;p&gt;For .NET projects, the two obvious choices are MSBuild and NAnt.  The new hotness for building .NET projects is Rake.  And, if you use a scripting language not built into TeamCity (such as FinalBuilder, Psake, or shell scripts), the command line runner is your friend.  TeamCity also has two .NET build runners specifically targeting code inspection: Duplicates finder and FxCop.&lt;/p&gt;  &lt;p&gt;I have been using NAnt for several years to build both web and desktop applications.  NAnt has been fairly quiet for the last couple years.  The latest official release (0.86 Beta 1) is dated December 2007, but there has been sporadic 0.86 Beta 2 activity in the nightly releases. &lt;/p&gt;  &lt;p&gt;I have just started working with Rake for build scripts. (A big thanks to the &lt;a href="http://fluentnhibernate.org/" target="_blank"&gt;Fluent NHibernate&lt;/a&gt; and &lt;a href="http://fubumvc.pbworks.com/" target="_blank"&gt;FubuMVC&lt;/a&gt; contributors for their pioneering efforts on this front.)  Rake, like Ruby itself, seems to be infinitely extensible.&lt;/p&gt;  &lt;h4&gt;What Should a Build Script Do?&lt;/h4&gt;  &lt;p&gt;My build scripts need to at least handle the following targets/tasks:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Compile the application &lt;/li&gt;    &lt;li&gt;Run the tests &lt;/li&gt;    &lt;li&gt;Provide a code coverage report &lt;/li&gt;    &lt;li&gt;Zip up the compiled application for artifact retention &lt;/li&gt;    &lt;li&gt;Update the configuration files &lt;/li&gt;    &lt;li&gt;Publish the website to a folder or IIS virtual directory &lt;/li&gt; &lt;/ol&gt;  &lt;ul&gt;TeamCity natively handles 1 and 2, but we will be duplicating that functionality with the build scripts.  TeamCity also allows you to download your artifacts as a zip file, but does not store it as one.  TeamCity does not provide code coverage for .NET projects.  However, it does for Java projects.) &lt;/ul&gt;  &lt;ul&gt;Our NAnt and Rake scripts will handle the all the tasks.  I will cover the first four tasks in this post.  I will cover the other three in another post.  &lt;/ul&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;Setting Up an NAnt Build Runner&lt;/h4&gt;  &lt;p&gt;We’ll start with an NAnt Build Runner.  In your TeamCity website:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;From the Projects page, click the drop arrow next to the existing project and click on Edit Settings &lt;/li&gt;    &lt;li&gt;On the right hand side of the screen, click on the Copy button to copy the configuration &lt;/li&gt;    &lt;li&gt;Name the new build configuration “Just Build It! (with NAnt)” &lt;/li&gt;    &lt;li&gt;Select the Runner link from the navigation bar on the right &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Based on the sample solution, enter the following values and save your changes.  Leave all other values at their defaults. (If your solution is structured differently, adjust accordingly.)&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="200"&gt;&lt;strong&gt;Build Runner:&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="200"&gt;NAnt&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;&lt;strong&gt;Path to a build file:&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="200"&gt;nant.build&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;&lt;strong&gt;NAnt Home:&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="200"&gt;lib/nant&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Leaving the Targets text box blank will force the runner to use the default target.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The default targets in thee script files create a zipped file of the website and code coverage results from the free NCover Community edition.  I am using a couple custom tasks from &lt;a href="http://www.kiwidude.com/blog/" target="_blank"&gt;kiwidude&lt;/a&gt; for integrating NCover with the NAnt script.  &lt;/p&gt;    &lt;p&gt;In the General Settings page, add the following to the Artifacts text box to force both files to show up as artifacts:&lt;/p&gt;    &lt;pre class="brush: plain; gutter: true;"&gt;results/Artifacts.zip&lt;br /&gt;results/CoverageReport.html=&amp;gt;ncover&lt;/pre&gt;&lt;p&gt;Creating custom tabs is fairly simple as well.  Add the following entry to the &lt;strong&gt;&lt;em&gt;&amp;lt;TeamCity data directory&amp;gt;/config/main-config.xml&lt;/em&gt;&lt;/strong&gt; (the default data directory is named &lt;em&gt;&lt;strong&gt;.BuildServer &lt;/strong&gt;to create a tab that shows the NCover results for each build&lt;/em&gt;:&lt;/p&gt;&lt;pre class="brush: xml; gutter: false; "&gt;&amp;lt;report-tab title="NCover"&lt;br /&gt;basePath="ncover"&lt;br /&gt;startPage="CoverageReport.html" /&amp;gt;&lt;/pre&gt;&lt;p&gt;(Thanks to Laurent Kempé for the &lt;a href="http://weblogs.asp.net/lkempe/archive/2008/03/30/integration-of-ncover-into-team-city-for-tech-head-brothers.aspx" target="_blank"&gt;instructions&lt;/a&gt; on integrating NCover with TeamCity)&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h4&gt;Setting Up a Rake Build Runner &lt;/h4&gt;&lt;p&gt;Make another copy of a configuration and name the new build configuration “Just Build It! (with Rake)”. This time select Rake as the build runner on the Build Runner page.  Leave all other values at their default.  (The Rakefile in the root directory will be used.  I modified the rake scripts from the FubuMVC project for this solution.)&lt;/p&gt;&lt;p&gt;You will need Ruby and a couple of Gems to get started.  Check the information in the Ruby_Not_Installed.txt file in the root directory of the sample solution.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Setting Up an MSBuild Build Runner&lt;/h4&gt;&lt;p&gt;I actually do not have an example of an MSBuild script (because I do not have enough experience with MSBuild).  Setting up the build runner is similar to the NAnt and Rake runners.  If you are interested in this build runner type, check out &lt;a href="http://www.buzzuti.com/post/TeamCity-1-Creating-an-MSBuild-File-and-talks-on-Continuous-Integration.aspx" target="_blank"&gt;Ryan Anderson’s posts&lt;/a&gt;. He has done an excellent job detailing the process.&lt;/p&gt;&lt;br /&gt;&lt;hr /&gt;&lt;h4&gt;Upcoming posts:&lt;/h4&gt;&lt;ul&gt; &lt;li&gt;Deployment: Using TeamCity and build scripts to update different deployment environments.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Setting up notifications: We will look at the different options for notifications, such as email and the tray notifier.&lt;br /&gt; &lt;hr /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href="http://www.jetbrains.com/teamcity" target="_blank"&gt;JetBrains TeamCity&lt;/a&gt;&lt;br /&gt;&lt;a href="http://codeprogression.googlecode.com/" target="_blank"&gt;Sample Project on GoogleCode&lt;/a&gt;&lt;br /&gt;&lt;a href="http://nant.sourceforge.net/" target="_blank"&gt;NAnt&lt;/a&gt;&lt;br /&gt;&lt;a href="http://nantcontrib.sourceforge.net/" target="_blank"&gt;NAntContrib&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.kiwidude.com/dotnet/DownloadPage.html" target="_blank"&gt;NCoverExplorer Downloads&lt;/a&gt;&lt;br /&gt;&lt;a href="http://nant.sourceforge.net/" target="_blank"&gt;NAnt&lt;/a&gt;&lt;br /&gt;&lt;a href="http://nantcontrib.sourceforge.net/" target="_blank"&gt;NAntContrib&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.kiwidude.com/dotnet/DownloadPage.html" target="_blank"&gt;NCoverExplorer Download Page (with NAnt/MSBuild documentation links)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ruby-lang.org/en/downloads/" target="_blank"&gt;Ruby Downloads&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-4741698710175178330?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/BYm-o5jeIZU" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/05/implementing-teamcity-for-net-projects.html#comment-form" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/4741698710175178330?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/4741698710175178330?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/05/implementing-teamcity-for-net-projects.html" title="Implementing TeamCity for .NET Projects, Part 4: Using Build Scripts" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>11</thr:total></entry><entry gd:etag="W/&quot;CUUGRXY6eSp7ImA9WxJTEUs.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-3453412091063189078</id><published>2009-04-19T11:47:00.001-06:00</published><updated>2009-04-19T11:47:04.811-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-19T11:47:04.811-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Build Automation" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity" /><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration" /><title>Implementing TeamCity for .NET Projects, Part 3: Running Tests, Nightly Builds, and Creating Artifacts</title><content type="html">&lt;p&gt;&lt;em&gt;For more information on this series, please see the &lt;/em&gt;&lt;a title="Implementing TeamCity introduction" href="http://codeprogression.blogspot.com/2009/03/implementing-teamcity-for-net-projects.html" target="_blank"&gt;&lt;em&gt;introductory post&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&amp;#160; This post also assumes that you have completed parts &lt;a title="Just Build It!" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects.html" target="_blank"&gt;1&lt;/a&gt; and &lt;a title="Triggering Builds" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_15.html" target="_blank"&gt;2&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;With our basic solution build, we want to start running our unit tests on every check-in, create a nightly build (that runs both unit and integration tests), and generate some artifacts.&lt;/p&gt;  &lt;h4&gt;Running Tests&lt;/h4&gt;  &lt;p&gt;First things first, lets get the tests running.&amp;#160; Open the current build configuration and select the build runner navigation link (it should say &lt;strong&gt;&lt;em&gt;Runner: sln2008&lt;/em&gt;&lt;/strong&gt;).&amp;#160; On the build runner page, select NUnit 2.4.8 from the &lt;strong&gt;NUnit runner&lt;/strong&gt; combo box.&amp;#160; Add the path to the unit test assembly in the assembly text box.&amp;#160; For our solution, the path is: &lt;em&gt;**/bin/debug/AdventureMVC.Tests.dll&lt;/em&gt; .&amp;#160; As you can see, this is using an MSBuild wildcard format to find the correct assembly.&amp;#160; It is unnecessary to point to the full path.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_bGTiQEGe9PE/SetjgwktTsI/AAAAAAAAADA/E0ppw9FdUzo/s1600-h/image%5B52%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="105" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/SetjhKkvslI/AAAAAAAAADE/zpUn6lBeUEM/image_thumb%5B36%5D.png?imgmax=800" width="404" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Save your changes.&lt;/p&gt;  &lt;p&gt;Now, when your builds run, you should get a new status indicator showing how many tests passed.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_bGTiQEGe9PE/SetjhNlrXKI/AAAAAAAAADI/iawoT7Sr61A/s1600-h/image%5B7%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="38" alt="image" src="http://lh6.ggpht.com/_bGTiQEGe9PE/Setjhg4Id5I/AAAAAAAAADM/gFqKNfaGdpg/image_thumb%5B3%5D.png?imgmax=800" width="155" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you click on the status, you will also see a new tab on the build results page showing the test information.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_bGTiQEGe9PE/SetjhrMw1XI/AAAAAAAAADQ/nYTHrbBltP8/s1600-h/image%5B10%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="82" alt="image" src="http://lh4.ggpht.com/_bGTiQEGe9PE/Setjh-t9hxI/AAAAAAAAADU/36RV_RBw4yI/image_thumb%5B4%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;a href="http://lh5.ggpht.com/_bGTiQEGe9PE/Setjicm4mLI/AAAAAAAAADY/DTvKZhmg6SM/s1600-h/image%5B14%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="102" alt="image" src="http://lh6.ggpht.com/_bGTiQEGe9PE/SetjimGUQUI/AAAAAAAAADc/oPMY_29kw6g/image_thumb%5B6%5D.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h4&gt;Nightly Builds (with integration tests)&lt;/h4&gt;  &lt;p&gt;Now that we have our &lt;a href="http://lh4.ggpht.com/_bGTiQEGe9PE/Setjiz2NBUI/AAAAAAAAADg/5VU1vYlDtdY/s1600-h/image%5B19%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="127" alt="image" src="http://lh4.ggpht.com/_bGTiQEGe9PE/SetjjCvcAYI/AAAAAAAAADk/8ofZ3QyJYhI/image_thumb%5B12%5D.png?imgmax=800" width="244" align="right" border="0" /&gt;&lt;/a&gt;unit tests running on every check-in, let’s create a nightly build.&amp;#160; Open the current build configuration.&amp;#160; Make a copy of the build by clicking on the &lt;strong&gt;&lt;em&gt;Copy &lt;/em&gt;&lt;/strong&gt;button on the right-hand side of the page.&amp;#160; &lt;/p&gt;  &lt;p&gt;Rename the new configuration as you see fit.&amp;#160; I will use&lt;em&gt;&lt;strong&gt; &lt;/strong&gt;Nightly Build&lt;/em&gt;. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_bGTiQEGe9PE/SetjjQJQOQI/AAAAAAAAADo/YJ79CaPIpns/s1600-h/image%5B26%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="119" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/Setjjo_10PI/AAAAAAAAADs/proSJBVodPI/image_thumb%5B17%5D.png?imgmax=800" width="304" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Select the build runner link.&amp;#160; Add the integration test assembly to the test assembly text box. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_bGTiQEGe9PE/Setjj1z70vI/AAAAAAAAADw/41gX9Pi9wRY/s1600-h/image%5B32%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="40" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/SetjkMgr1wI/AAAAAAAAAD0/WyXdq06KULE/image_thumb%5B21%5D.png?imgmax=800" width="504" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Save your changes.&lt;/p&gt;  &lt;p&gt;Select the &lt;strong&gt;&lt;em&gt;Build triggering &lt;/em&gt;&lt;/strong&gt;link.&amp;#160; Deselect the check box.&amp;#160; On the &lt;strong&gt;&lt;em&gt;&lt;a href="http://lh4.ggpht.com/_bGTiQEGe9PE/SetjkcgPL1I/AAAAAAAAAD4/omaSboacWV8/s1600-h/image%5B36%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="106" alt="image" src="http://lh6.ggpht.com/_bGTiQEGe9PE/SetjkuHwjkI/AAAAAAAAAD8/SHagt8uJOUY/image_thumb%5B23%5D.png?imgmax=800" width="244" align="right" border="0" /&gt;&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;Schedule&lt;/em&gt;&lt;/strong&gt; tab, click on &lt;strong&gt;&lt;em&gt;Add time trigger &lt;/em&gt;&lt;/strong&gt;and configure your nightly build time. Save your changes.&amp;#160; (You can test the build at this point by clicking on the Run button.)&lt;/p&gt;  &lt;h4&gt;Creating Artifacts&lt;/h4&gt;  &lt;p&gt;We want to make the compiled website readily available, so we are going to create some artifacts.&amp;#160; Getting at the precompiled website through the file system is inconvenient.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;If the example solution contained a website, compiling the solution would create a precompiled website.&amp;#160; Since the example solution contains a web application project (specifically an ASP.NET MVC application project), I had to add a post-build event to create the precompiled site.&amp;#160; Check the AdventureMVC project properties to see the syntax.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;On the Nightly Build configuration page, select the &lt;strong&gt;&lt;em&gt;General Settings&lt;/em&gt;&lt;/strong&gt; link.&amp;#160; In the Artifacts text box, type: &lt;em&gt;PrecompiledWeb\Web=&amp;gt;PrecompiledWeb&lt;/em&gt;.&amp;#160; Save your changes.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_bGTiQEGe9PE/Setjk8cDnOI/AAAAAAAAAEA/OkE1pau7wSc/s1600-h/image%5B53%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="50" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/SetjlBmHeHI/AAAAAAAAAEE/6bqbz9nJxhc/image_thumb%5B38%5D.png?imgmax=800" width="636" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Now when you run your build, you should see an Artifacts dropdown link in the status line of the build.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_bGTiQEGe9PE/SetjlDht8SI/AAAAAAAAAEI/bXBDD6UQiko/s1600-h/image%5B47%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="107" alt="image" src="http://lh4.ggpht.com/_bGTiQEGe9PE/SetjlXLjzNI/AAAAAAAAAEM/i9GFounB_RI/image_thumb%5B33%5D.png?imgmax=800" width="228" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;When you click on the build status, the status page now has an artifacts tab.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_bGTiQEGe9PE/Setjl-No3mI/AAAAAAAAAEQ/hyo0hHdeiHg/s1600-h/image%5B51%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="62" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/SetjmFcHx-I/AAAAAAAAAEU/sf8eWf8RcUM/image_thumb%5B35%5D.png?imgmax=800" width="404" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Not only do you have the ability to download the individual files, you can now use these artifacts in other build configurations…but that is for another post.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h4&gt;Upcoming posts: &lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;p&gt;Build scripts: We need some additional functionality that the basic solution runner doesn’t provide, such as zipping up artifacts.&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;Setting up notifications: We will look at the different options for notifications, such as email and the tray notifier.&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;Deployment: Using TeamCity and build scripts to update different deployment environments.&lt;/p&gt;   &lt;/li&gt;    &lt;ul&gt;&lt;/ul&gt; &lt;/ul&gt;  &lt;hr /&gt;&lt;a href="http://www.jetbrains.com/teamcity" target="_blank"&gt;JetBrains TeamCity&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://codeprogression.googlecode.com" target="_blank"&gt;Sample Project on GoogleCode&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-3453412091063189078?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/IBS_Uy5HnBs" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_19.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/3453412091063189078?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/3453412091063189078?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_19.html" title="Implementing TeamCity for .NET Projects, Part 3: Running Tests, Nightly Builds, and Creating Artifacts" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_bGTiQEGe9PE/SetjhKkvslI/AAAAAAAAADE/zpUn6lBeUEM/s72-c/image_thumb%5B36%5D.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;CUUAR3s6fip7ImA9WxJTEUs.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-3584714041161218387</id><published>2009-04-15T03:16:00.001-06:00</published><updated>2009-04-19T11:47:26.516-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-19T11:47:26.516-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Build Automation" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity" /><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration" /><title>Implementing TeamCity for .NET Projects, Part 2: Triggering Builds</title><content type="html">&lt;p&gt;&lt;em&gt;For more information on this series, please see the &lt;/em&gt;&lt;a title="Implementing TeamCity introduction" href="http://codeprogression.blogspot.com/2009/03/implementing-teamcity-for-net-projects.html" target="_blank"&gt;&lt;em&gt;introductory post&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;  &lt;h4&gt;Why Continuous Integration?&lt;/h4&gt;  &lt;p&gt;The benefit of continuous integration, &lt;a href="http://www.martinfowler.com/articles/continuousIntegration.html#BenefitsOfContinuousIntegration"&gt;according to Martin Fowler&lt;/a&gt;, is reduced risk.&amp;#160; Reduced risk is accomplished through a quick feedback cycle.&amp;#160; The longer you defer integration, the more difficult integration becomes.&amp;#160; If you integrate automated testing into your integration cycle, you can further reduce your risk.&lt;/p&gt;  &lt;h4&gt;Continuous Integration with TeamCity (VCS Triggers)&lt;/h4&gt;  &lt;p&gt;TeamCity has four build trigger options:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;VCS Triggers: Triggers a build when files are checked into source control. &lt;/li&gt;    &lt;li&gt;Schedule: Triggers a build on a predetermined schedule. &lt;/li&gt;    &lt;li&gt;Dependencies: Triggers a build when another build completes successfully. &lt;/li&gt;    &lt;li&gt;Other Triggers: Triggers a build if previous build fails. &lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;p&gt;VCS triggers are analogous to continuous integration.&amp;#160; Check in files to source control and a build is started.&amp;#160; Enabling continuous integration in TeamCity takes only a few clicks to configure.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_bGTiQEGe9PE/SeWl4q9bSzI/AAAAAAAAACY/urgxFaaqw5I/s1600-h/image%5B9%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="145" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/SeWl5N0ZuLI/AAAAAAAAACc/_cnWwfdjkuU/image_thumb%5B6%5D.png?imgmax=800" width="244" align="left" border="0" /&gt;&lt;/a&gt;Lets get started. Click the arrow next to the build configuration we completed in the &lt;a href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects.html" target="_blank"&gt;last post&lt;/a&gt;. Select &lt;em&gt;Edit Settings&lt;/em&gt;. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;a href="http://lh5.ggpht.com/_bGTiQEGe9PE/SeWl5Jt3KQI/AAAAAAAAACg/lGbRWgQTlVQ/s1600-h/image19.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="124" alt="image" src="http://lh6.ggpht.com/_bGTiQEGe9PE/SeWl5RsvJ_I/AAAAAAAAACk/Zj8kcKy0hM4/image_thumb21.png?imgmax=800" width="244" align="right" border="0" /&gt;&lt;/a&gt;&lt;/em&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;a href="http://lh5.ggpht.com/_bGTiQEGe9PE/SeWl5Jt3KQI/AAAAAAAAACg/lGbRWgQTlVQ/s1600-h/image19.png"&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;On the right side of the build configuration screen, you will see a list of &lt;em&gt;Build Configuration Steps&lt;/em&gt;.&amp;#160; Select the&lt;em&gt; Build Triggering &lt;/em&gt;step.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Select the checkbox labeled &lt;strong&gt;Enable triggering when files are checked into VCS&lt;/strong&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_bGTiQEGe9PE/SeWl5n6JYaI/AAAAAAAAACo/GNlmnlydViQ/s1600-h/image%5B14%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="46" alt="image" src="http://lh5.ggpht.com/_bGTiQEGe9PE/SeWl5zb4cbI/AAAAAAAAACs/SoTzNoAph_w/image_thumb%5B9%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;em&gt;At this point, you can save your changes and you will have enabled continuous integration.&amp;#160; The quiet period and trigger rules (explained below)&amp;#160; fine-tune the behavior of the build trigger.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Once checked, an option to set a quiet period is enabled.&amp;#160; A quiet period is the length of time after a check-in which TeamCity will wait before starting the build.&amp;#160; If check-ins tend to come in waves, this can help keep the build queue short.&amp;#160; (If you tend to forget to check in all your files or need to check in files from your IDE and file system, you may want to give yourself a short quiet period before triggering a build to allow for multiple check-ins.)&lt;a href="http://lh4.ggpht.com/_bGTiQEGe9PE/SeWl6zbbiBI/AAAAAAAAACw/weZSzQaToqg/s1600-h/image23.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="100" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/SeWl7URsp9I/AAAAAAAAAC0/zcV9WOdDXxY/image_thumb23.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;However, if you configure too long of a quiet period with a project with a large team, the build may take too long to start, negating the benefits of continuous integration.&amp;#160; I prefer to select &lt;em&gt;Do not use &lt;/em&gt;or &lt;em&gt;Use default value (60 seconds)&lt;/em&gt; for my projects.&lt;/p&gt;  &lt;p&gt;Finally, you can exclude some check-ins from triggering the build by defining trigger patterns.&amp;#160; Exclusions can be based on file paths, users, or a combination.&amp;#160; For example, if your project team includes a technical writer who produces documentation, those check-ins probably do not affect build quality.&amp;#160; Or, when you update your build scripts, those changes may not need to trigger a build either (see example below).&amp;#160; &lt;em&gt;For the purposes of the example solution, you may define the &lt;strong&gt;–:*.build&lt;/strong&gt; pattern, even though we haven’t started using build scripts yet.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://lh3.ggpht.com/_bGTiQEGe9PE/SeWl7hHHTDI/AAAAAAAAAC4/Ei2jbubqoAI/s1600-h/image%5B16%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="88" alt="image" src="http://lh5.ggpht.com/_bGTiQEGe9PE/SeWl7wTkm1I/AAAAAAAAAC8/sr1EYSRph9Y/image_thumb%5B11%5D.png?imgmax=800" width="316" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Defining a trigger pattern is fairly straightforward. The pattern is:    &lt;br /&gt;&lt;strong&gt;+|-:[user][VCS root][path]      &lt;br /&gt;&lt;/strong&gt;Defining a +: rule removes the include all rule, allowing a very fine-grade include path. Defining a –: rule excludes the defined path from triggering a build.&amp;#160; For more information, see the &lt;a href="http://www.jetbrains.net/confluence/display/TCD4/Configuring+VCS+Triggers" target="_blank"&gt;documentation&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Finish by saving your changes and returning to the main page.&amp;#160; Update and check in a project file and you can watch TeamCity start a new build process.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;strong&gt;&lt;em&gt;Congratulations! You have just enabled continuous integration with TeamCity!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h4&gt;Upcoming posts: &lt;a href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_19.html" target="_blank"&gt;Creating artifacts and nightly builds&lt;/a&gt;&lt;/h4&gt;  &lt;p&gt;&lt;/p&gt;  &lt;hr /&gt;&lt;a href="http://www.jetbrains.com/teamcity" target="_blank"&gt;JetBrains TeamCity&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://codeprogression.googlecode.com" target="_blank"&gt;Sample Project on GoogleCode&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-3584714041161218387?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/gW0j1GMtLqA" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_15.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/3584714041161218387?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/3584714041161218387?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_15.html" title="Implementing TeamCity for .NET Projects, Part 2: Triggering Builds" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_bGTiQEGe9PE/SeWl5N0ZuLI/AAAAAAAAACc/_cnWwfdjkuU/s72-c/image_thumb%5B6%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEcEQX0zcSp7ImA9WxJSFU0.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-7967534924326845303</id><published>2009-04-05T20:29:00.003-06:00</published><updated>2009-05-04T23:40:00.389-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-04T23:40:00.389-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Build Automation" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity" /><title>Implementing TeamCity for .NET projects, Part 1: Just Build It! (A Simple Build Configuration)</title><content type="html">&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;For more information on this series, please see the &lt;/em&gt;&lt;a title="Implementing TeamCity introduction" href="http://codeprogression.blogspot.com/2009/03/implementing-teamcity-for-net-projects.html" target="_blank"&gt;&lt;em&gt;introductory post&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;When working on an development team, one of the more challenging tasks can be building your integrated source code for deployment.    Building a production version of the application may be a long and difficult process, especially if production builds are infrequent.  Even a well-documented build procedure may take hours or days to complete and is probably prone to error.  One person may have all the requisite knowledge to perform the build, causing delays or rifts for other team members when builds are needed.&lt;/p&gt;  &lt;p&gt;Therefore, creating a repeatable build process that any team member can instantiate can provide great benefit for the team, reducing the risks in the build process.  That is our purpose for this exercise – to Just Build It!  &lt;/p&gt;  &lt;p&gt;For a production build system, your build server should be a mirror of your production environment.  This helps reveal possible issues and risks before deploying to your production environment.  For the purposes of this series, this is not necessary; however, you must have the following installed:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Microsoft Visual Studio 2008 &lt;/li&gt;    &lt;li&gt;A version control system(VCS), such as Subversion or Team Foundation Server.  &lt;ul&gt;       &lt;li&gt;If you do not have a current VCS instance, consider &lt;a href="http://www.google.com/url?q=http://www.visualsvn.com/server/&amp;amp;ei=FD7ZSZXCBovCsQOS6_ixAw&amp;amp;sa=X&amp;amp;oi=smap&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;cd=4&amp;amp;usg=AFQjCNE1ra5T-I4JkE3GXhzLUPDssx-02w" target="_blank"&gt;VisualSVN Server&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;Ensure that the system on which you will install TeamCity has the ability to check out files from your VCS natively.  For Team Foundation Server, you must have &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0ed12659-3d41-4420-bbb0-a46e51bfca86&amp;amp;displaylang=en" target="_blank"&gt;Team Explorer&lt;/a&gt; installed.  For Subversion, you must have &lt;a href="http://subversion.tigris.org/" target="_blank"&gt;SVN&lt;/a&gt; or &lt;a href="http://tortoisesvn.tigris.org/" target="_blank"&gt;TortoiseSVN&lt;/a&gt; installed. &lt;/li&gt;        &lt;li&gt;For a full list of supported systems, consult the &lt;a href="http://www.jetbrains.net/confluence/display/TCD4/TeamCity+Documentation" target="_blank"&gt;TeamCity documentation&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=53289097-73ce-43bf-b6a6-35e00103cb4b&amp;amp;displaylang=en" target="_blank"&gt;ASP.NET MVC&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;The sample AdventureMVC solution      &lt;ul&gt;       &lt;li&gt;Added to your installed VCS &lt;/li&gt;        &lt;li&gt;Available from &lt;a href="http://codeprogression.googlecode.com/" target="_blank"&gt;codeprogression.googlecode.com&lt;/a&gt;           &lt;ul&gt;           &lt;li&gt;A zip file is available to download for utilization in your VCS &lt;/li&gt;            &lt;li&gt;You may also browse the source on the site &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;The &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=e719ecf7-9f46-4312-af89-6ad8702e4e6e&amp;amp;displaylang=en" target="_blank"&gt;AdventureWorks&lt;/a&gt; database installed on SQL Server 2005 or SQL Express 2005       &lt;ul&gt;       &lt;li&gt;Available from &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=e719ecf7-9f46-4312-af89-6ad8702e4e6e&amp;amp;displaylang=en" target="_blank"&gt;Microsoft downloads&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;Update the web.config file to your specific database connection information prior to running the solution or any builds &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.jetbrains.com/teamcity/download/" target="_blank"&gt;TeamCity 4.02 or later&lt;/a&gt;       &lt;ul&gt;       &lt;li&gt;If you are using VisualSVN Server 1.7, you must download &lt;a href="http://www.jetbrains.net/confluence/display/TW/Download+Latest" target="_blank"&gt;TeamCity 4.1 EAP or later&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;For installation instructions, consult the &lt;a href="http://www.jetbrains.net/confluence/display/TCD4/TeamCity+Documentation" target="_blank"&gt;TeamCity documentation&lt;/a&gt;. &lt;/li&gt;        &lt;li&gt;Note your installation directory and build server directories.  These will be useful in the future. &lt;/li&gt;        &lt;li&gt;I usually locate my buildServer directory in the TeamCity installation directory rather than in the user profile folders. &lt;/li&gt;        &lt;li&gt;When choosing the port for the TeamCity website, be aware of other sites configured on the machine.  Unless the server is dedicated to TeamCity operations, I suggest using port 8111. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;em&gt;Note: I am assuming that you will be installing all of these packages on one system for exploratory purposes.  If you are not, you will need to adjust the instructions accordingly, especially in later posts.  For example, you will need an instance of AdventureWorks on your development system and your build system.  In a future post, I plan to explore the challenges of integrating databases into a continuous integration solution, such as TeamCity.&lt;/em&gt;&lt;/p&gt;  &lt;h4&gt;Your First Project&lt;/h4&gt;  &lt;p&gt;With &lt;a href="http://www.jetbrains.com/teamcity" target="_blank"&gt;TeamCity&lt;/a&gt;, the time between finishing installation and running the first build can literally be minutes.  Lets get started.The minimum requirements for build configurations are:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;A project to house the configuration (TeamCity houses all build configurations within user-defined projects). &lt;/li&gt;    &lt;li&gt;A connection to a version control system &lt;/li&gt;    &lt;li&gt;A build runner &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Start up the TeamCity site.   Click on the &lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="41" alt="image" src="http://lh6.ggpht.com/_bGTiQEGe9PE/SdlpDvRKbsI/AAAAAAAAABU/an9U1Cv41EU/image%5B13%5D.png?imgmax=800" width="147" align="right" border="0" /&gt;&lt;strong&gt;Create Project&lt;/strong&gt; link, name your project, provide a description of the project (optional), and click the &lt;strong&gt;Create Project &lt;/strong&gt;link.   &lt;/p&gt;  &lt;h4&gt;Your First Build Configuration &lt;/h4&gt;  &lt;p&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="72" alt="image" src="http://lh3.ggpht.com/_bGTiQEGe9PE/SdlpEPuhapI/AAAAAAAAABY/6fFUBqAtv8Q/image18%5B1%5D%5B1%5D.png?imgmax=800" width="244" align="right" border="0" /&gt; Click on &lt;strong&gt;Create Build Configuration &lt;/strong&gt;(you have 20 total in the professional version).  &lt;/p&gt;  &lt;p&gt;On the &lt;em&gt;General Settings, &lt;/em&gt;provide a name for your build configuration and an optional description.  Leave the rest of the options on the &lt;em&gt;General Settings &lt;/em&gt;page at their default. &lt;/p&gt;  &lt;p&gt;Click on &lt;strong&gt;VCS Settings.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Name your VCS root and choose your VCS type.  Fill out your VCS-specific settings.  Ensure that the root of the source control directory is the trunk folder.  &lt;/p&gt;  &lt;p&gt;Here is my Subversion configuration for the example project:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_bGTiQEGe9PE/SdlpFL1cwTI/AAAAAAAAABc/EckUeqAfxEo/s1600-h/image%5B12%5D.png" target="_blank"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="139" alt="image" src="http://lh6.ggpht.com/_bGTiQEGe9PE/SdlpFk76ibI/AAAAAAAAABo/8ZoATQcUmZA/image_thumb%5B5%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;And my working directory:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_bGTiQEGe9PE/SdlpGKgdp1I/AAAAAAAAABs/OoCEUFjlqmg/s1600-h/image%5B11%5D.png" target="_blank"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="109" alt="image" src="http://lh4.ggpht.com/_bGTiQEGe9PE/SdlpGvGAwNI/AAAAAAAAAB4/hdh3ymrNxG8/image_thumb%5B4%5D.png?imgmax=800" width="211" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here is a possible TFS configuration:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_bGTiQEGe9PE/SdlpHXXXiII/AAAAAAAAAB8/fTsvDE0gB3A/s1600-h/image%5B10%5D.png" target="_blank"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="177" alt="image" src="http://lh5.ggpht.com/_bGTiQEGe9PE/SdlpHyZUQ5I/AAAAAAAAACA/0U0omtpdSGY/image_thumb%5B3%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Test your connection and save.  Once again, leave the rest of the options at their defaults.  &lt;/p&gt;  &lt;p&gt;Click on &lt;strong&gt;Choose Build Runner&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Select &lt;strong&gt;&lt;em&gt;sln2008&lt;/em&gt;&lt;/strong&gt; from the &lt;strong&gt;Build Runner:&lt;/strong&gt; option list.  In the &lt;strong&gt;Solution file path: &lt;/strong&gt;text box, enter &lt;em&gt;&lt;strong&gt;src\AdventureMVC.sln&lt;/strong&gt;&lt;/em&gt;.  Change the text in the &lt;strong&gt;Confguration: &lt;/strong&gt;text box to &lt;strong&gt;&lt;em&gt;Debug&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;  &lt;h4&gt;Running Your Build&lt;/h4&gt;  &lt;p&gt;Click on the Projects tab in the top navigation. In your newly defined build configuration, click on the Run button (do not click the ellipse) and watch your build run.&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="68" alt="image" src="http://lh5.ggpht.com/_bGTiQEGe9PE/SdlpILOH7BI/AAAAAAAAACE/NFrqd00164Y/image15%5B1%5D.png?imgmax=800" width="217" align="right" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="68" alt="image" src="http://lh6.ggpht.com/_bGTiQEGe9PE/SdlpIv-S90I/AAAAAAAAACQ/KUM8wMYSoKg/image12%5B1%5D.png?imgmax=800" width="217" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;If everything compiles, you should see a success message for your build.  If not, check the error messages in the build log.  You may have errors in your VCS configuration.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="24" alt="image" src="http://lh5.ggpht.com/_bGTiQEGe9PE/SdlpI4AgyQI/AAAAAAAAACU/HLT3Cb6FtYg/image25%5B1%5D.png?imgmax=800" width="193" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt; &lt;strong&gt;&lt;em&gt;Congratulations! You have just completed and run your first build configuration!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;You can find your compiled website in the TeamCity installation directory under \buildAgent\work\&lt;em&gt;guid&lt;/em&gt;\src\PrecompiledWeb\Web.&lt;/p&gt;  &lt;hr /&gt;  &lt;h4&gt;Next: &lt;a href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_15.html" target="_blank"&gt;Continuous Integration (or Triggering Builds)&lt;/a&gt; and Creating Artifacts&lt;/h4&gt;  &lt;p&gt;Even with a source code version control system (VCS), ensuring each developer has a working, buildable version of source code can be a slippery slope.  A developer may forget to check in a new file or dependent library.  With a VCS based on optimistic locks, a careless developer may break another developer’s code during a merge operation. So, how do we make sure that the latest code is compiling code? By using &lt;strong&gt;&lt;em&gt;Continuous Integration&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;And, isn’t there an easier way to get at my compiled application? Yes, there is.  Its called &lt;em&gt;&lt;strong&gt;Artifacts&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Stay tuned.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-7967534924326845303?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/XfL4QOdqYSE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/7967534924326845303?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/7967534924326845303?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects.html" title="Implementing TeamCity for .NET projects, Part 1: Just Build It! (A Simple Build Configuration)" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_bGTiQEGe9PE/SdlpDvRKbsI/AAAAAAAAABU/an9U1Cv41EU/s72-c/image%5B13%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0ICRXg-fSp7ImA9WxJaGEU.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-7408746382978771721</id><published>2009-03-31T00:06:00.005-06:00</published><updated>2009-08-09T23:19:24.655-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-09T23:19:24.655-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Boise Code Camp" /><category scheme="http://www.blogger.com/atom/ns#" term="Build Automation" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity" /><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration" /><title>Implementing TeamCity for .NET Projects: Evolving Your Build Automation Solution</title><content type="html">&lt;p&gt;&lt;em&gt;As the title suggests, I will be focusing on using TeamCity with .NET projects.  However, &lt;u&gt;make no mistake&lt;/u&gt;: TeamCity is well-positioned and well-tuned for use with many development environments, and many of the concepts I will discuss are applicable to those environments.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;&lt;p&gt;Posts in this Series:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;a href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects.html"&gt;Just  Build It! (A Simple Build Configuration)&lt;/a&gt;  &lt;/li&gt;&lt;li&gt;&lt;a href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_15.html" target="_blank"&gt;Triggering Builds&lt;/a&gt;  &lt;/li&gt;&lt;li&gt;&lt;a href="http://codeprogression.blogspot.com/2009/04/implementing-teamcity-for-net-projects_19.html" target="_blank"&gt;Nightly Builds  and Creating Artifacts&lt;/a&gt;  &lt;/li&gt;&lt;li&gt;&lt;a href="http://codeprogression.blogspot.com/2009/05/implementing-teamcity-for-net-projects.html" target="_blank"&gt;Using Build Scripts&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://codeprogression.blogspot.com/2009/08/implementing-team-city-for-net-projects.html"&gt;Deployments&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Setting Up Notifications (Coming Soon)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;&lt;ol&gt; &lt;/ol&gt;  &lt;p&gt;During my talk at Boise Code Camp 2009, we discussed the evolution of build automation and continuous integration.  If you are not familiar with build automation and continuous integration, Martin Fowler’s &lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt;article&lt;/a&gt; is a nice primer on the subject. &lt;/p&gt;  &lt;p&gt;When I started on my current project, our team was not using a build server.  We were encountering problems with incomplete check-ins, hostile merging, missing dependencies, and inconsistent and bloated production builds.  The classic “it works on my machine” and “your code broke my code” syndromes were very prevalent.  Prior to this gig, I had worked on a team that was using a continuous integration solution and I knew that we needed to implement something similar.&lt;/p&gt;  &lt;p&gt;While investigating options, I compared Team Foundation Build, CruiseControl.net, and TeamCity.  TeamCity quickly became the forerunner strictly due to the ease of configuration and raving reviews from the community.  Both Team Build and Cruise Control use XML configuration (yes, MSBuild is XML).  Although I am very comfortable with scripting builds using nAnt, this was a barrier to implementation as a team.  I wanted a low-friction entry point with the ability to implement more powerful functionality later.&lt;/p&gt;  &lt;p&gt;In the next several posts, I would like to expound on the evolution of our build process, starting with basic patterns, and then exploring more powerful patterns, all implemented using TeamCity.  The patterns I will discuss are…&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Simple Build Automation &lt;/li&gt;    &lt;li&gt;Build and Test &lt;/li&gt;    &lt;li&gt;Continuous Integration &lt;/li&gt;    &lt;li&gt;Nightly Builds &lt;/li&gt;    &lt;li&gt;Artifact Creation &lt;/li&gt;    &lt;li&gt;Alternative Build Runners (Build scripting) &lt;/li&gt;    &lt;li&gt;Build Dependencies &lt;/li&gt;    &lt;li&gt;Deployments &lt;/li&gt;    &lt;li&gt;Custom User Interface Elements &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You may want to &lt;a href="http://www.jetbrains.com/teamcity/download/index.html?free" target="_blank"&gt;download&lt;/a&gt; your own copy of TeamCity (the Professional version is free!).  &lt;a href="http://www.jetbrains.net/confluence/display/TCD4/Installing+and+Configuring+the+TeamCity+Server" target="_blank"&gt;Installation&lt;/a&gt; is quick and painless . Make note of which directory you designate to be the .BuildServer directory – for convenience purposes, I suggest placing it in the root of the main TeamCity directory.  I will make a sample project available for use in exercising the build server configurations shortly.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.boisecodecamp.com/" target="_blank"&gt;Boise Code Camp&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms181716.aspx" target="_blank"&gt;Team Foundation Build&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://cruisecontrol.sourceforge.net/" target="_blank"&gt;CruiseControl.net&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://www.jetbrains.com/teamcity" target="_blank"&gt;TeamCity&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-7408746382978771721?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/2GotqcwJzM0" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/03/implementing-teamcity-for-net-projects.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/7408746382978771721?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/7408746382978771721?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/03/implementing-teamcity-for-net-projects.html" title="Implementing TeamCity for .NET Projects: Evolving Your Build Automation Solution" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;D0IAQXg9eSp7ImA9WxVbE0o.&quot;"><id>tag:blogger.com,1999:blog-2027921681594931248.post-4528626449125910919</id><published>2009-03-29T13:36:00.002-06:00</published><updated>2009-03-29T19:12:20.661-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-29T19:12:20.661-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Boise Code Camp" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity" /><title>Boise Code Camp Session: Getting Started with Continuous Integration using Team City</title><content type="html">&lt;p&gt;Giving a talk today at &lt;a href="http://www.boisecodecamp.com/"&gt;Boise Code Camp&lt;/a&gt; on JetBrains TeamCity build management server.  &lt;/p&gt;  &lt;p&gt;Topics:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Benefits of continuous integration&lt;/li&gt;    &lt;li&gt;Why TeamCity?&lt;/li&gt;    &lt;li&gt;Evolution of automated builds/continuous integration&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Will follow up with examples of evolving your build automation from just compiling code in a team environment to deploying websites.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.jetbrains.com/teamcity"&gt;TeamCity Home Page&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt;Continuous Integration (Martin Fowler)&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2027921681594931248-4528626449125910919?l=codeprogression.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/codeprogression/~4/WaLnAPJUyfA" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://codeprogression.blogspot.com/2009/03/boise-code-camp-session-getting-started.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/4528626449125910919?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2027921681594931248/posts/default/4528626449125910919?v=2" /><link rel="alternate" type="text/html" href="http://codeprogression.blogspot.com/2009/03/boise-code-camp-session-getting-started.html" title="Boise Code Camp Session: Getting Started with Continuous Integration using Team City" /><author><name>Richard</name><uri>http://www.blogger.com/profile/10743754891977266662</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="27" height="32" src="http://4.bp.blogspot.com/_bGTiQEGe9PE/Sc_OIvtodBI/AAAAAAAAAAM/_cZ0vs_797k/S220/simpsonizedme.png" /></author><thr:total>0</thr:total></entry></feed>

