In my last post I wrote about the requirements and challenges we encountered, implementing Team Foundation Server to create an automated build process. This post is meant to leave a more detailed view. 

Design Code structure

The main concern when it comes to design was to make deployment as easy as possible.  To enable this, we separated all BizTalk projects by types of artifacts. That left us with three different types of projects Orchestrations, Transformation and Schemas. No reason for Pipeline projects since we created generic pipelines to be configured at runtime. This way we got a chain of dependencies from Orchestrations -> Transformations -> Schemas. This would prove very important upon automating the undeploying of these assemblies.

We used the notion of BizTalk Applications to represent actual systems from which we'd receive and send messages to. The Application name would be used in the name of the BizTalk project, together with the information type. Eg. SAP.SalesRevenue.Orchestrations.proj.

Every BizTalk project where then grouped into a ILS solution, which in this case could be GeneralLedger.sln. To make sure each ILS solution could be built and deployed independent of other solutions, there could never be any references between these solutions.

Custom build tasks

Custom build tasks extends Team Foundation Build, and is necessary when you'd want to perform actions part from what is included in the product. There are lots of custom tasks, made available through the community, such as Microsoft.Sdc.Tasks. This library has lots of nice features for many of the products from MS, among them BizTalk.

Unfortunately, we couldn't quite get them to work with our requirements. But they where much helpful as a starting point.

We ended up creating four custom build tasks:

UndeployBindings

Undeploys ports and orchestrations from BizTalk applications using binding files. For this to work, the name of the binding file(s) are expected to end with target environment, Eg Sap.BindingFile.BUILD.xml.

<VIPN.Shared.Tools.BizTalkTfsBuildTasks.UndeployBindings
                TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
                BuildUri="$(BuildUri)"
                Server="$(BizTalkServerName)"
                RootPath="%(SolutionToBuild.Identity)"
                Database="$(BTServerDatabase)"
                ProcessTimeOutMilliseconds="60000"
                TargetEnviroment="DEV"/>
UndeployAssembly

The UndeployAssembly Task is only used internally from the UndeployBinding Task,  and is used for undeploying a single assembly from an BizTalk application. This is done after all ports and orchestrations are removed. The resources needs to be removed in the right order, assemblies, with references to others needs to be removed first. This is accomplished by encapsulating schemas, transformations and orchestrations in separate projects, and naming them thereafter. Eg. [Application].[InfomationType].Transfomations

ImportBindings

If the solution path includes a "Bindings" folder, all binding files will be imported into the application. The target environment will be set, if included in the name of the binding file. Eg Sap.BindingFile.TEST.xml.

Usages:

<VIPN.Shared.Tools.BizTalkTfsBuildTasks.ImportBindings
                TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
                BuildUri="$(BuildUri)"
                Server="$(BizTalkServerName)"
                Database="$(BTServerDatabase)"
                TargetEnviroment="$(TargetEnviroment)"
                RootPath="%(SolutionToBuild.Identity)"/>
ExportPackage

The ExportPackage exports one package per BizTalk Application, but only the assemblies stated in the binding file(  + all binding files for that application).

Usages:

<VIPN.Shared.Tools.BizTalkTfsBuildTasks.ExportApplication
                        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
                        BuildUri="$(BuildUri)"
                        Server="$(BizTalkServerName)"
                        RootPath="%(SolutionToBuild.Identity)"
                        Database="$(BTServerDatabase)"
                        TargetEnviroment="$(TargetEnviroment)"
                        OutputPath="$(OutDir)"/>

Download the task library, and make sure it builds. You might have to reset some of the Team Foundation references. Copy all the assemblies to a directory on the build server.

Team Foundation Build Type

To make use of all this, create a new Build type, and open the TfsBuild.proj file.  Copy the lower part of this template ( from <!– Blogical configuration –> and down). You need to change some of the configuration in the <!– BizTalk Variables –> property group.

  • <Blogical_CustomTasks> should be set to the directory on the build server where you copied the task library.
  • <TargetEnviroment> should be set to the name of your target environment, and correlate to the binding file name to use.
  • <BizTalkServerName> is the name of the database server.

That's it.

Summery

I realize that this is a complex solution, and it may not fit within your design. But hopefully it will give you some inspiration of how to solve the problem.