TFS Build controller and extensions - tfs

I am setting up a TFS 2012 Build server. I am using some extensions (NUnit Test Adapter). Per the instructions, I have added the dlls to a common folder in TFS, and configured the "Version Control Path to Custom Assemblies" on the build controller to reference the correct folder in TFS.
Everything works, BUT: According to the docs, I can create subfolders under my "Path to custom assemblies" folder, and the controller should pick them up.
That doesn't seem to be working for me. If I put the NUnit support in the root, it works, in subfolders, it does not.
I would like to use the subfolders feature so that I can keep each set of extensions/custom build targets, etc separate.
Does this just not work, or am I missing something?
Edit
As requested, here is a reference to the documentation where I found the information:
http://msdn.microsoft.com/en-us/library/vstudio/ee330987(v=vs.120).aspx#custom_process
Here's the passage:
To enable your build processes to leverage these kinds of code, check the binaries in to the folder (or any of its descendant folders) that you specify in the Version control path to custom assemblies box.

It turns out that the documentation is just wrong -- all of the dlls must go into 1 folder.
http://social.msdn.microsoft.com/Forums/en-US/0059bc66-d3c9-42e6-8d8a-dd22f3416e07/version-control-path-to-custom-assemblies-doesnt-use-subfolders?forum=tfsbuild
I do understand that helps to ensure that you don't get duplicate dependencies with different versions -- makes sense. It just makes it a little tougher to know what depends upon what if you add a few extensions. Seems to work fine using a single folder, though.

Related

Adding references search folder for MSBuild from Visual Studio Build definition UI

I am working on configuring a XAML build definition for a .net solution (of another company) stored in TFS2015.
The solution uses Dll references from a software X, installed on the developers computers, but not present in the Build server. (FTS and Build servers are shared among many clients).
I have option to add the required Dlls in a folder along with the source code, but I do not have option to modify the .csproj files.
In the Build definition, I tried to add the following in the MSBuild arguments field :
/p:AdditionalLibPaths=$/[long tfs path here]/CommonDlls
/p:AdditionalLibPaths=$(SourceDir)/CommonDlls
but it is not working.
Ideally, I would like to specify a relative folder from the root of the source code.
(a static path might work but only for one build server and agent, which is not the objective of shared build).
Any ideas on how I can define this parameter ?
There is also option to add a prebuild script path. I can store a script file along with source code. Any pointers for how to write such script file ?
You do not really need a script.
There are two things to make this work.
The first step is making sure that the DLLs are downloaded to the Agent working folder, the simplest way is have the $/[long tfs path here]/CommonDlls mapped in the Build Workspace; this is specified in the Source Settings tab of the Build Definition. Be careful to use the $(SourceDir) token in the mapping (see here).
The second point is to use a proper reference to the downloaded folder: use the TF_BUILD_SOURCESDIRECTORY variable (see here for full list).
So, if you added a mapping like
$/[long tfs path here]/CommonDlls -> $(SourceDir)\CommonDlls
use $(TF_BUILD_SOURCESDIRECTORY)\CommonDlls.
It took me almost 20 trials to get the right one, it all started with how long it took that warning to consider all other directories, I could've ignored it but here's the warning first
C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5): Warning MSB3245: Could not resolve this reference. Could not locate the assembly "nameOfDllFile". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
and this is the argument that got it working
/p:ReferencePath="$(build.sourcesdirectory)\Binaries"
where Binaries is the equivalent to CommonDlls from the question, and it is all because of the vague documentation and differences between versions of MSBuild, mine is 14.0 (VS2015).

Customizing Drop Folder Structure with TFS Team Build

I'm using TFS 2012 to automate a build of a solution which contains multiple windows services and two web applicaitons.
I've used the guide I found here to customize the build process template so that the windows services are put in a folder structure that I like. Specifically:
\dropserver\droproot\MyApp\BuildNumber\
\Service1
\Service2
\Service3
\Service4
This works great, but unfortunately it doesn't work for web applicaitons. If I used the same strategy for those, I just get the contents of /bin for each web app, rather than the full site contents.
MSBuild typically uses the web application targets to handle this, but for some reason, this doesn't work when you customize the build as I have. I no longer get the _PublishedWebSites folder in the build output. (I'm guessing that's because I cleared our the OutDir property of the MSBuild task.)
Has anybody done something like this and gotten it to work with web applications as well?
I think I can help with this, it looks like in the build targets that the published websites folder isn't created if the OutDir is the same as the OutputPath.
So this isn't perfect, but if you add the following into the csproj file in the first property group, you'll get everything deployed into "\bin\deploy\" including the _PublishedWebsites folder
<DeployOnBuild>True</DeployOnBuild>
<OutDir>bin\deploy\</OutDir>
With a bit of customization, this solution ended up working for me:
http://www.edsquared.com/2011/01/31/Customizable+Output+Directories+For+TFS+2010+Build.aspx
Basically, did what that link recommended, but also leveraged a new solution configuration (which I called TeamBuild) rather than conditional property definitions.
I believe the key to making this all work was the passing of the outputDirectory as the TeamBuildOutDir argument to MSBuild. Embedding this variable reference in the OutDir or OutputPath variable was allowed Team Build to build to the correct staging location and then automatically copy files from that location to the drop folder.
I'm going to take this a little futher and get rid of the whole _PublishedWebSites thing, but that will be done entirely in the build workflow.
EDIT: TFS 2013 supports this natively with a simply build configuration option:
Take a look at this thread as this post as well.
Team Build: Publish locally using MSDeploy
Since you need all the files for your web projects, you need to trigger the publishing process, and by tweaking the destination of that process, you can have all of your files copied where you need them.
I think option (2) from his answer will work for you.
I hope that helps.
As I can see in your reference link, it will just compile and package the binaries. It does not deploy the website by the steps mentioned in that.
If you want to get the .html, .css, .js etc. under the _PublishedWebSites folder, you need to do a Web Deployment. This manually we can do by clicking the publish option from right click menu of your VS project and by selecting Publish Method as File System.
But, since you need to automate this in your build and drop it in custom drop folder, you may need to manipulate your MSBuild script by calling a AspNetCompiler task. You can get more information on this at the MSDN link. By specifying the TargetPath while you call this target you can get your Web files deployed at the appropriate custom drop folder.
Happy Scripting.
Have you check this blog, this solved my problem where I wanted customized TeamBuild Ouput Directory.
Customizable O/P with TFS 2013
Customizaable O/P with TFS 2012 and .NET Framework 4.5

Using wixlibs from another solution with TFS builds

We have installers referencing a wixlib file to get some common functionality. The wixlib is built in another solution then moved to a folder within that solution. When we try to build the installers with a TFS build, we get an error from light.exe:
light.exe: The system cannot find the file '..\..\..\Core\Common\assemblies\v1.0\Common.Wix.wixlib' with type 'Source'.
Our regular projects can reference \assembiles\v1.0, since we have some other common assemblies stored there. How do we get WiX to recognize this location during build?
You are referencing wixlib directly. So as far as I understand the TFS build process, it should be added to TFS project of your solution. TFS project shouldn't be dependent on the output of another non-dependent solution. It is at least bad practice. And in any case you can't guarantee this output would be generated before your project build on server.
As far as I remember, TFS build creates separate folder for each build and gets sources there. So your solutions are no longer on the same folder hierarchy level.
One more point in favor of explicitly copying wixlibs into your installer project: versioning - in this case any bugs made in the common library will not immediately break all projects that reference it. And you can gradually upgrade and test every project. Can you imagine auomatically downloading new version of any 3rd party dll on every build? Any change in that dll will immediately break your application even if changes are not critical to you.
Since the shared component and the active solution are in two separate projects in TFS, the workspace must be setup so that the relative paths for references remain intact. The easiest way to do this is to set your Build Agent Folder structure in Workspace in your TFS Build to have $(SourceDir) represent your root. However, don't change your Source Control Folder - that stays the same.
For example, say you have the following structure:
-TFS
|-SharedComponents
||-MyComponents
|-ProjectArea
||-MyProject
You would want to have the following two items in the build Workspace:
Source Control Folder Build Agent Folder
---------------------------------------------------------------------------------
$/ProjectArea/MyProject $(SourceDir)\ProjectArea\MyProject
$/SharedComponents/MyComponents $(SourceDir)\SharedComponents\MyComponents
This mimics the structure in TFS in your build folder, thus allowing all relative paths to remain intact.
One more note about this configuration: Since you have the shared components in another location, you may want to create a solution folder in MyProject and add the components that you are using to it. This will ensure they get pulled automatically when anyone loads your project from TFS - they won't have to go back and pull down the share components folder separately after discovering a build error.

Using WiX to generate an installer for an ASP.Net MVC website

Has anyone used WiX to generate an installer for an ASP.Net MVC website? Do you harvest files from the web project? I can’t find any good examples of this being done. There doesn’t seem to be a documented way to include all the right files, only the right files and put them in the right place.
If you add the website project as a reference in the installer project, and set harvest=True in the properties, then all the website files are captured, but there are issues:
Some files that should not be copied are included, e.g. packages.config, Web.Debug.config There doesn’t seem to be any clear or simple way to exclude them (as per this discussion).
The .website dll file is in the wrong place, in the root rather than the bin folder (as per this discussion)
However if you do not use harvesting, you have a lot of files to reference manually (e.g. Under \Content\ alone I have 58 files in 5 folders. Most of that is jQuery UI) and they change from time to time, and errors and omissions could easily be missed from a WiX file list. So it really should be kept in sync automatically.
I disagree with the idea that the list of files should be specified explicitly in WiX and not generated dynamically (which is what seems to be suggested at the first link, the wording isn't very clear). If I need to remove a file I will remove if from the source control system, there is no need to do the extra work of maintaining two parallel but different catalogues – one set of files in source control, and the same files listed in WiX. there should be one version of the truth. All files in the website's source tree (with certain known exceptions that are not used at runtime e.g. packages.config) should be included in the deployment.
For corporate reasons I don't have much choice about using WiX for this project
In our MVC 3 project we use Paraffin to harvest files for the installer. For example, you can use "-ext " to ignore the files with extension , use "regExExclude " to ignore the file name matching the regular expression, etc.
Paraffin also keeps the proper structure, all your files would be in the correct folder as they appear in your project.
I use a program that I wrote called ISWIX that makes authoring wxs merge modules a simple drag and drop operation like InstallShield. I then consume that merge module in an installer that handles the UI and IIS configuration.
I also have postbuild automation that extracts the content of the MSI and compares it against what the project published. If there is a delta I fail the build and you have to either a) add it to the wxs or b) remove it from the publish.
I find that the file count churn from build to build is minimal and that this system is not difficult to maintain. The upside is everything remains 100% intentionally authored and files don't ever magically add or remove from the installer unless you intended them to. Dynamic installer generation isn't worth the risk and most people who argue that it is don't even know what those risks are.

TFS with different binaries folder for different projects

I've got a solution with Silverlight projects, a couple Web applications and some Windows service and their small Winforms test applications.
When I build it using TFS it puts all binary files in the Binaries folder. It also creates a _PublishedWebsites folder where it puts the web applications ready for deployment.
What I would like is for a few of the projects to have their ouput in a separate directory in the Binaries folder. I want the files that I would normally find in the bin\Release folder to be there.
I looked long and hard and could only find scarce documentation on how to achieve that and only for TFS 2008. There's a good article there link text and another entry for VS 2010 there link text. However, none of these work :-(
It seems that the build ignores the <OutputPath> property. I tried fiddling with the <AfterBuild> property but unfortunately if I use the $(OutDir) property I get ALL the files in the Binaries directory and not only the ones that just got compiled.
At the moment I'm setting up a separate build that only has the projects I'm interested in that get compiled but I would really like to have all the files needed for the release built all at once.
EDIT: I didn't make it clear enough but I'm using the latest version of TFS (TFS 2010 RTM). I set up <OutputPathDir> on the project level as explained in the links that I provided.
Cheers.
In your build definition (.proj) file, check that
<Project>
<PropertyGroup>
<CustomizableOutDir>true</CustomizableOutDir>
</PropertyGroup>
</Project>
Also, you may run into some problems if you're trying to compile what was once a "website" project type (created from File->New->Website->ASP.NET Webiste). They seem to override the output directory every time. We had to convert some of those to class libraries instead.

Resources