Showing posts with label TFS. Show all posts
Showing posts with label TFS. Show all posts

Monday, September 28, 2015

Automatic update of assembly version using TFS2013

To successfully implement Octopus Deploy you need to have unique version numbers for each build. If you don't want to manually edit the assembly info this could be a real pain in the ***. With the following trick you can automatically generate version numbers using TFS Build server 2013.

What I did was create a BuildCommon.targets that automatically searches for the AssemblyInfo and updates the version number that matches the build number as generated by TFS, and check this file in your codetree. In our case the file is named: BuildCommon.targets and is placed next to the root of the solution:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">

<!--
    Defining custom Targets to execute before project compilation starts.
-->
<PropertyGroup>
    <CompileDependsOn>
        CommonBuildDefineModifiedAssemblyVersion;
        $(CompileDependsOn);
    </CompileDependsOn>
</PropertyGroup>

<!--
    Creates modified version of AssemblyInfo.cs, replaces [AssemblyVersion] attribute with the one specifying actual build version (from MSBuild properties), and includes that file instead of the original AssemblyInfo.cs in the compilation.

    Works with both, .cs and .vb version of the AssemblyInfo file, meaning it supports C# and VB.Net projects simultaneously.
-->
<Target Name="CommonBuildDefineModifiedAssemblyVersion" Condition="'$(VersionAssembly)' != ''">
    <!-- Find AssemblyInfo.cs or AssemblyInfo.vb in the "Compile" Items. Remove it from "Compile" Items because we will use a modified version instead. -->
    <PropertyGroup>
        <VersionAssembly>$([System.Text.RegularExpressions.Regex]::Replace($(VersionAssembly), `[\w|\D]+_`, ``, System.Text.RegularExpressions.RegexOptions.IgnoreCase))</VersionAssembly>
    </PropertyGroup>
    <ItemGroup>
        <OriginalAssemblyInfo Include="@(Compile)" Condition="(%(Filename) == 'AssemblyInfo') And (%(Extension) == '.vb' Or %(Extension) == '.cs')" />
        <Compile Remove="**/AssemblyInfo.vb" />
        <Compile Remove="**/AssemblyInfo.cs" />
    </ItemGroup>
    <!-- Copy the original AssemblyInfo.cs/.vb to obj\ folder, i.e. $(IntermediateOutputPath). The copied filepath is saved into @(ModifiedAssemblyInfo) Item. -->
    <Copy SourceFiles="@(OriginalAssemblyInfo)"
          DestinationFiles="@(OriginalAssemblyInfo->'$(IntermediateOutputPath)%(Identity)')">
        <Output TaskParameter="DestinationFiles" ItemName="ModifiedAssemblyInfo"/>
    </Copy>
    <!-- Replace the version bit (in AssemblyVersion and AssemblyFileVersion attributes) using regular expression. Use the defined property: $(VersionAssembly). -->
    <Message Text="Setting AssemblyVersion to $(VersionAssembly)" />
    <RegexUpdateFile Files="@(ModifiedAssemblyInfo)"
                Regex="Version\(&quot;(\d+)\.(\d+)(\.(\d+)\.(\d+)|\.*)&quot;\)"
                ReplacementText="Version(&quot;$(VersionAssembly)&quot;)"
                />
    <!-- Include the modified AssemblyInfo.cs/.vb file in "Compile" items (instead of the original). -->
    <ItemGroup>
        <Compile Include="@(ModifiedAssemblyInfo)" />
    </ItemGroup>
</Target>

<UsingTask TaskName="RegexUpdateFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
        <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
        <Regex ParameterType="System.String" Required="true" />
        <ReplacementText ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
        <Reference Include="System.Core" />
        <Using Namespace="System" />
        <Using Namespace="System.IO" />
        <Using Namespace="System.Text.RegularExpressions" />
        <Using Namespace="Microsoft.Build.Framework" />
        <Using Namespace="Microsoft.Build.Utilities" />
        <Code Type="Fragment" Language="cs">
            <![CDATA[
            try {
                var rx = new System.Text.RegularExpressions.Regex(this.Regex);
                for (int i = 0; i < Files.Length; ++i)
                {
                    var path = Files[i].GetMetadata("FullPath");
                    if (!File.Exists(path)) continue;

                    var txt = File.ReadAllText(path);
                    txt = rx.Replace(txt, this.ReplacementText);
                    File.WriteAllText(path, txt);
                }
                return true;
            }
            catch (Exception ex) {
                Log.LogErrorFromException(ex);
                return false;
            }
        ]]>
        </Code>
    </Task>
</UsingTask>

</Project>

Then change the build number format to:
$(BuildDefinitionName)_0.1.$(Year:yy)$(DayOfYear)$(Rev:.r)

and the MSBuild arguments:
/p:CustomAfterMicrosoftCommonTargets="$(TF_BUILD_SOURCESDIRECTORY)\src\BuildCommon.targets" /p:RunOctoPack=true /p:OctoPackPublishApiKey=API-123465 /p:OctoPackPublishPackageToHttp=http://octopus-server/nuget/packages /p:VersionAssembly=$(TF_BUILD_BUILDNUMBER)

This should result in unique assembly versions for each build.

Many thanks for the creators of these posts to help me create this:
http://www.lionhack.com/2014/02/13/msbuild-override-assembly-version/
http://blog.casavian.eu/blog/2014/04/23/increment-version-for-changed-assemblies-only-first-part/
http://blogs.msdn.com/b/visualstudio/archive/2010/04/02/msbuild-property-functions.aspx

Cheers,
Luuk

Friday, July 3, 2015

Unhandled Exception: System.InvalidOperationException: Cannot dispose the build manager because it is not idle.

Today we got this really annoying error when building on TFS2010:


Long story short: Not our build server was causing this error, but the TFS server itself... it was out of diskspace..

So please check this first before blaming everything else except TFS :)

Cheers,
Luuk

Tuesday, July 8, 2014

Automatically deploy services using TFS2010

All credits for this post goes out to: Hrusikesh Panda and Mike Hadlow (see references below).

To deploy Windows services with TFS2010 there are 2 major challenges; seperate the binaries on a per-project basis and automatically stop and start a service without changing the build workflow. Sounds hard? It isn't!

If you don't want any blabla and download the sample solution directly, goto github.

First add the following files to your Solution folder and make sure they will be committed to TFS:
DeployApplication.targets (this is a copy of the WebDeploy targets from Microsoft with an extra change to copy the .config file).
DeployService.targets (this stops the service, copies the files and starts the service, it also contains the location on where to put the files)
safeServiceStart.bat (helper to start a remote service)
safeServiceStop.bat (helper to stop a remote service)
you can simply add these files to the solution items (right click solution and click add existing item).

Edit the DeployService.targets for the right paths on the remote machine. The directory where the service is located should be available for the user running the build using a standard windows share (\\<servername>\<project directory>\<servicename>, the servername is determined during the build and can be configured for each build quality.

Copy the Deploy.targets into the project you want to deploy, unload the project file and edit it with visual studio. Lookup the following line:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
And add this line below:
<Import Project="Deploy.targets" Condition="'$(DeployOnBuild)'=='True'" />
Save the file and reload the project

Once you've reloaded the project, edit the Deploy.targets (just double click on it) and change the service name and service location. Commit all changes to TFS.

The next step is to install the service on the remote machine. (using installutil, or whatever method you like, in the sample we can install a service by running it with the -I command line argument). The automated deployment will only start and stop the service and is not able to install and delete the service. (In my case, the service is running as a domain user, and therefor I prefer to pre-install the service with the right credentials or else you'll have to enter the credentials in the deployment script).

To enable automatic deployment, create a new Build Configuration on your TFS2010 server and set it up with a scheduled trigger (or whatever trigger you want). In the process section add the following MSBuild arguments:
 /p:DeployOnBuild=True /p:DeploymentServerName=\\<server-to-deploy-to>
If you also want to configure transformations (change the .config file during deployment), have a look at SlowCheetah. This works without a problem with this configuration. To make sure SlowCheetah only works during deployment, I've edited the project file again and added AND '$(DeployOnBuild)'=='True' in the following line:
<Import Project="$(SlowCheetahTargets)" Condition="Exists('$(SlowCheetahTargets)') AND '$(DeployOnBuild)'=='True'" Label="SlowCheetah" />

(If you don't see this line, make sure you've installed SlowCheetah extension and added the transformations by right click on a .config file and click add transformations)

References:
http://mrchief.calepin.co/deploying-windows-service-via-msbuild
http://mikehadlow.blogspot.nl/2009/06/tfs-build-publishedwebsites-for-exe-and.html
https://github.com/luuksommers/TFSDeployedService

Happy deploying!

Luuk

Tuesday, June 4, 2013

Beyond Compare is Beyond Awesome with Source Control Integration

Just found out the Source Control Integration with Beyond Compare Pro, this is awesome! First install the TFS  SCC provider and click on Tools -> Source Controls Integration.


Now see a window where you can add the same folders as your mapped TFS workspaces. But when you now start to compare, merge or edit a file which is checked in, you get the following popup:


Nice, isn't it? So now you don't have to go to VS to checkout the item manually and this works a lot faster!

Cheers,
Luuk

Wednesday, November 21, 2012

Tfs Work Item HtmlFieldControl height on sharepoint

During my investigation to create a customer friendly interface for Tfs Work Items, we've found an interesting 'hidden' feature: the Height attribute. Without it, the HtmlFieldControl take up a huuuuuuuuuge amount of space:


But by adding the super secret nowhere to be found Height attribute, magic happens...


*badadum*

<Tab Label="Issue Details">
  <Group>
    <Column PercentWidth="100">
      <Control FieldName="WhatWentWrong" Type="HtmlFieldControl" Label="What went wrong:" LabelPosition="Top" Height="75" />
    </Column>
  </Group>
  <Group>
    <Column PercentWidth="100">
      <Control FieldName="ReproduceSteps" Type="HtmlFieldControl" Label="Steps to reproduce the problem:" LabelPosition="Top" Height="75" />
    </Column>
  </Group>
  <Group>
    <Column PercentWidth="100">
      <Control FieldName="ExpectedBehavior" Type="HtmlFieldControl" Label="What is the expected behavior:" LabelPosition="Top" Height="75" />
    </Column>
  </Group>
</Tab>
By the way, to prevent the Html controls, make te type of the field PlainText.

Cheers!

Friday, February 3, 2012

How to add Beyond Compare to Visual Studio TFS

To use the mother of all compare tools "Beyond Compare" as your default code comparer in Visual Studio 2010, you need to follow the next steps:

1. Install BC3 (Download the trial and buy it if you like at http://www.scootersoftware.com)

2. Go to the options followed by Source Control, Visual Studio Team Foundation Server and click on Configure User Tools.

3. Click on Add and add a Compare command for extension .* using command C:\Program Files (x86)\Beyond Compare 3\BComp.exe and arguments %1 %2 /title1=%6 /title2=%7

4. Click on Add and add a Merge command for extension .* using command C:\Program Files (x86)\Beyond Compare 3\BComp.exe and arguments %1 %2 /savetarget=%4 /title1=%6 /title2=%7
- or -
if you want BC Pro's 3-way merge: %1 %2 %3 %4 /title1=%6 /title2=%7 /title3=%8 /title4=%9



You need to use the bcomp.exe, else it wound work see http://www.scootersoftware.com/vbulletin/showthread.php?t=5538

Cheers,
L

Wednesday, September 7, 2011

Automatic deploy multiple websites in a solution using TFS Continious build

On the internet are a lot of resources to be found to automatically deploy websites to your (development) webserver. Here's how I solved that problem:

First of all, make sure your Team Foundation Server Continious build is up and running, and building packages the way you configured is.
Second of all, make sure you can deploy your website using the single click publish using MsDeploy.
Now edit the project file of the project(s) you would like to deploy and add the following tags in the PropertyGroup element:
<DeployTarget>MsDeployPublish</DeployTarget>
<CreatePackageOnPublish>false</CreatePackageOnPublish>
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
<MSDeployServiceUrl>https://yourwebserver:8172/MsDeploy.axd</MSDeployServiceUrl>
<UserName>YOURDOMAIN\User</UserName>
<Password>yourpassword</Password>
<AllowUntrustedCertificate>true</AllowUntrustedCertificate>
In the PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " element add the application path. By doing this, we can deploy different configuration types to app paths. If you need for example also a different username and password, you can add them in this section too.
<DeployIisAppPath>websites/Website</DeployIisAppPath>
Once we've edited the projects as mentioned above, we can setup the Build:

Voila! You're finished! Now build and watch your site change!

Save the build configuration and start a new build. If everything is correct, the website will be deployed on each build! For references you can look at the site of Vishal Joshi:
http://vishaljoshi.blogspot.com/2010/11/team-build-web-deployment-web-deploy-vs.html
http://vishaljoshi.blogspot.com/2009/11/web-deployment-painkillers-vs-2010-ms.html

and stack overflow:
http://stackoverflow.com/questions/2878385/how-do-you-deploy-a-website-and-database-project-using-tfs-2010

Tuesday, March 8, 2011

Undo unchanged files in TFS 2010

Download the Team Foundation Server Power Tools here: http://visualstudiogallery.msdn.microsoft.com/c255a1e4-04ba-4f68-8f4e-cd473d6b971f

Then after a reboot on W7 you can use the following command from your workspace directory:
tfpt uu . /noget /recursive

Do not forget the /noget switch or else you're changes will be lost!