{"id":10281,"date":"2005-09-19T12:08:05","date_gmt":"2005-09-19T16:08:05","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/buckh\/?p=10281"},"modified":"2019-05-06T12:09:01","modified_gmt":"2019-05-06T16:09:01","slug":"continuous-integration-demo-code-from-doug-neumanns-tln301-pdc-talk","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/buckh\/continuous-integration-demo-code-from-doug-neumanns-tln301-pdc-talk\/","title":{"rendered":"Continuous Integration Demo Code from Doug Neumann&#8217;s TLN301 PDC Talk"},"content":{"rendered":"<p><P>Doug Neumann&#8217;s TLN301 presentation, <A href=\"http:\/\/commnet.microsoftpdc.com\/content\/sessionview.aspx?TopicID=500bec40-7643-4298-8c72-efd1826e80d8\">VSTS: Behind the Scenes of Visual Studio 2005 Team Foundation Server<\/A>&nbsp;(<A href=\"http:\/\/216.55.183.63\/pdc2005\/slides\/TLN301_Neumann.ppt\">slides<\/A>), featured a demonstration of how to use the server&#8217;s check-in event notification to kick off a build for a continuous integration build system using Team Build.&nbsp; A number of people asked for it, so we&#8217;ve decided to post it here.<\/P>\n<P>Doug&#8217;s demonstration used the July CTP, but since <A href=\"https:\/\/blogs.msdn.com\/jeffbe\/archive\/2005\/09\/17\/470257.aspx\">beta 3 will hopefully be released this week<\/A>, the code has been modified to run on beta 3.&nbsp; You&#8217;ll need to create a web service and put the following code into it.&nbsp; Here are the assemblies you&#8217;ll need to reference.<\/P>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\">\n<P>Microsoft.TeamFoundation.Build.Client.dll<BR>Microsoft.TeamFoundation.Build.Common.dll<BR>Microsoft.TeamFoundation.Client.dll<BR>Microsoft.TeamFoundation.VersionControl.Client.dll<BR>Microsoft.TeamFoundation.VersionControl.Common.dll<BR>Microsoft.TeamFoundation.WorkItemTracking.Client.dll<\/P><\/BLOCKQUOTE>\n<P>The code is intentionally simplified to meet the needs of a demo (e.g., a real continuous integration system would need more intelligence in handling check-in events that come in while the current build is running, etc.), but it&#8217;s a good example of how to hook into the Team Foundation server&#8217;s events and build useful extensions.<\/P>\n<P>Once you&#8217;ve built and deployed your web service using VS 2005, you&#8217;ll need to add a subscription for your web service.&nbsp; The&nbsp;check-in event is sent to your continuous integration web service via SOAP.&nbsp; The following command, with changes as necessary for the name of your machine (here, I use localhost), must be run on the application tier to add an event subscription for your service.<\/P>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\">\n<P>bissubscribe \/eventType CheckinEvent \/userId&nbsp;mydomain\\myusername \/address <A href=\"http:\/\/localhost:8080\/ContinuousBuild\/Service.asmx\">http:\/\/localhost:8080\/ContinuousBuild\/Service.asmx<\/A> \/deliveryType Soap \/domain localhost<\/P><\/BLOCKQUOTE>\n<P dir=ltr>Now when you check code into your server, your continuous integration service will kick off a build.<\/P>\n<P dir=ltr>The Team Build team plans to post a more elaborate continuous integration example.<\/P>\n<P dir=ltr><STRONG>[UPDATE 2\/20\/06]<\/STRONG>&nbsp; I updated the version numbers in the SoapDocumentMethod attribute to work with RC and RTM releases.<\/P><PRE><SPAN style=\"COLOR: blue\">using<\/SPAN> System;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Collections;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Collections.Generic;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Collections.Specialized;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.ComponentModel;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Configuration;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Diagnostics;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Globalization;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.IO;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Reflection;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Threading;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Web;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Web.Services;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Web.Services.Protocols;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Xml;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> System.Xml.Serialization;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> Microsoft.Win32;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> Microsoft.TeamFoundation.Build.Common;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> Proxy = Microsoft.TeamFoundation.Build.Proxy;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> Microsoft.TeamFoundation.Client;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> Microsoft.TeamFoundation.WorkItemTracking.Client;\n<SPAN style=\"COLOR: blue\">using<\/SPAN> Microsoft.TeamFoundation.WorkItemTracking.Common;<\/p>\n<p>[WebService(Namespace = <SPAN style=\"COLOR: maroon\">&#8220;http:\/\/tempuri.org\/&#8221;<\/SPAN>)]\n[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]\n<SPAN style=\"COLOR: blue\">public<\/SPAN> <SPAN style=\"COLOR: blue\">class<\/SPAN> Service : System.Web.Services.WebService\n{\n    <SPAN style=\"COLOR: blue\">public<\/SPAN> Service ()\n    {\n    }<\/p>\n<p>    [SoapDocumentMethod(<SPAN style=\"COLOR: maroon\">&#8220;http:\/\/schemas.microsoft.com\/TeamFoundation\/2005\/06\/Services\/Notification\/03\/Notify&#8221;<\/SPAN>, \n                        RequestNamespace = <SPAN style=\"COLOR: maroon\">&#8220;http:\/\/schemas.microsoft.com\/TeamFoundation\/2005\/06\/Services\/Notification\/03&#8221;<\/SPAN>)]\n    [WebMethod]\n    <SPAN style=\"COLOR: blue\">public<\/SPAN> <SPAN style=\"COLOR: blue\">void<\/SPAN> Notify(<SPAN style=\"COLOR: blue\">string<\/SPAN> eventXml)     <SPAN style=\"COLOR: green\">\/\/ Do not change the name of this argument.<\/SPAN>\n    {\n        ThreadPool.QueueUserWorkItem(CallBuild, eventXml);\n    }<\/p>\n<p>    <SPAN style=\"COLOR: blue\">public<\/SPAN> <SPAN style=\"COLOR: blue\">void<\/SPAN> CallBuild(<SPAN style=\"COLOR: blue\">object<\/SPAN> state)\n    {\n        <SPAN style=\"COLOR: blue\">string<\/SPAN> eventXml = (<SPAN style=\"COLOR: blue\">string<\/SPAN>)state;<\/p>\n<p>        <SPAN style=\"COLOR: green\">\/\/ De-serializing the event<\/SPAN>\n        XmlDocument Xmldoc = <SPAN style=\"COLOR: blue\">new<\/SPAN> XmlDocument();\n        Xmldoc.LoadXml(eventXml);<\/p>\n<p>        <SPAN style=\"COLOR: blue\">string<\/SPAN> teamProject = Xmldoc.DocumentElement[<SPAN style=\"COLOR: maroon\">&#8220;TeamProject&#8221;<\/SPAN>].InnerText;\n        <SPAN style=\"COLOR: blue\">string<\/SPAN> owner = Xmldoc.DocumentElement[<SPAN style=\"COLOR: maroon\">&#8220;Owner&#8221;<\/SPAN>].InnerText;<\/p>\n<p>        <SPAN style=\"COLOR: green\">\/\/ NOTE: hard-code info for demo<\/SPAN>\n        <SPAN style=\"COLOR: blue\">string<\/SPAN> teamFoundationServer = <SPAN style=\"COLOR: maroon\">&#8220;http:\/\/localhost:8080&#8221;<\/SPAN>;\n        <SPAN style=\"COLOR: blue\">string<\/SPAN> buildType = <SPAN style=\"COLOR: maroon\">&#8220;Continuous Integration Build&#8221;<\/SPAN>;\n        <SPAN style=\"COLOR: blue\">string<\/SPAN> buildMachine = <SPAN style=\"COLOR: maroon\">&#8220;localhost&#8221;<\/SPAN>;\n        <SPAN style=\"COLOR: blue\">string<\/SPAN> buildDirectoryPath = <SPAN style=\"COLOR: maroon\">&#8220;c:\\\\builds&#8221;<\/SPAN>;<\/p>\n<p>        Proxy.BuildController controller = Proxy.BuildProxyUtilities.GetBuildControllerProxy(teamFoundationServer);\n        Proxy.BuildStore store = Proxy.BuildProxyUtilities.GetBuildStoreProxy(teamFoundationServer);\n        Proxy.BuildParameters buildParams = <SPAN style=\"COLOR: blue\">new<\/SPAN> Proxy.BuildParameters();\n        buildParams.TeamFoundationServer = teamFoundationServer;\n        buildParams.TeamProject = teamProject;\n        buildParams.BuildType = buildType;\n        buildParams.BuildDirectory = buildDirectoryPath;\n        buildParams.BuildMachine = buildMachine;<\/p>\n<p>        <SPAN style=\"COLOR: blue\">string<\/SPAN> buildUri = controller.StartBuild(buildParams);<\/p>\n<p>        <SPAN style=\"COLOR: green\">\/\/ wait until the build completes<\/SPAN>\n        BuildConstants.BuildStatusIconID status;\n        <SPAN style=\"COLOR: blue\">bool<\/SPAN> buildComplete = <SPAN style=\"COLOR: maroon\">false<\/SPAN>;\n        <SPAN style=\"COLOR: blue\">do<\/SPAN>\n        {\n            Proxy.BuildData bd = store.GetBuildDetails(buildUri);\n            status = (BuildConstants.BuildStatusIconID)bd.BuildStatusId;\n            buildComplete = (status == BuildConstants.BuildStatusIconID.BuildSucceeded ||\n                status == BuildConstants.BuildStatusIconID.BuildFailed ||\n                status == BuildConstants.BuildStatusIconID.BuildStopped);\n        } <SPAN style=\"COLOR: blue\">while<\/SPAN> (!buildComplete);<\/p>\n<p>        <SPAN style=\"COLOR: blue\">if<\/SPAN> (status == BuildConstants.BuildStatusIconID.BuildFailed)\n        {\n            <SPAN style=\"COLOR: green\">\/\/ create a workitem for the developer who checked in<\/SPAN>\n            CreateWorkItem(teamFoundationServer, teamProject, owner);\n        }\n    }<\/p>\n<p>    <SPAN style=\"COLOR: blue\">public<\/SPAN> <SPAN style=\"COLOR: blue\">void<\/SPAN> CreateWorkItem(<SPAN style=\"COLOR: blue\">string<\/SPAN> server, <SPAN style=\"COLOR: blue\">string<\/SPAN> projectName, <SPAN style=\"COLOR: blue\">string<\/SPAN> owner)\n    {\n        TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(server);\n        WorkItemStore store = (WorkItemStore) tfs.GetService(<SPAN style=\"COLOR: blue\">typeof<\/SPAN>(WorkItemStore));<\/p>\n<p>        WorkItemTypeCollection workItemTypes = store.Projects[projectName].WorkItemTypes;<\/p>\n<p>        <SPAN style=\"COLOR: green\">\/\/ Enter the work item as a bug<\/SPAN>\n        WorkItemType wit = workItemTypes[<SPAN style=\"COLOR: maroon\">&#8220;bug&#8221;<\/SPAN>];\n        WorkItem workItem = <SPAN style=\"COLOR: blue\">new<\/SPAN> WorkItem(wit);<\/p>\n<p>        workItem.Title = <SPAN style=\"COLOR: maroon\">&#8220;The changes submitted have caused a build break &#8211; please investigate&#8221;<\/SPAN>;\n        <SPAN style=\"COLOR: blue\">string<\/SPAN>[] ownerSplit = owner.Split(<SPAN style=\"COLOR: maroon\">&#8216;\\\\&#8217;<\/SPAN>);\n        owner = ownerSplit[ownerSplit.GetLength(<SPAN style=\"COLOR: maroon\">0<\/SPAN>) &#8211; <SPAN style=\"COLOR: maroon\">1<\/SPAN>];\n        workItem.Fields[<SPAN style=\"COLOR: maroon\">&#8220;System.AssignedTo&#8221;<\/SPAN>].Value = owner;\n        workItem.Fields[<SPAN style=\"COLOR: maroon\">&#8220;Microsoft.VSTS.Common.Priority&#8221;<\/SPAN>].Value = <SPAN style=\"COLOR: maroon\">1<\/SPAN>;\n        workItem.Save();\n    }\n}\n<\/PRE><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Doug Neumann&#8217;s TLN301 presentation, VSTS: Behind the Scenes of Visual Studio 2005 Team Foundation Server&nbsp;(slides), featured a demonstration of how to use the server&#8217;s check-in event notification to kick off a build for a continuous integration build system using Team Build.&nbsp; A number of people asked for it, so we&#8217;ve decided to post it here. [&hellip;]<\/p>\n","protected":false},"author":94,"featured_media":10268,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-10281","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"blog_post_summary":"<p>Doug Neumann&#8217;s TLN301 presentation, VSTS: Behind the Scenes of Visual Studio 2005 Team Foundation Server&nbsp;(slides), featured a demonstration of how to use the server&#8217;s check-in event notification to kick off a build for a continuous integration build system using Team Build.&nbsp; A number of people asked for it, so we&#8217;ve decided to post it here. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/posts\/10281","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/users\/94"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/comments?post=10281"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/posts\/10281\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/media\/10268"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/media?parent=10281"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/categories?post=10281"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/tags?post=10281"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}