Manually Trigger a TFS Team Build - tfs

How would you manually trigger additional team builds from a team build? For example, when we were in CC.Net other builds would trigger if certain builds were successful. The second build could either be projects that use this component or additional, long running test libraries for the same component.

One way you could do it is you could an an AfterEndToEndIteration target to your TFSBuild.proj file that would runs the TfsBuild.exe command line to start you other builds. I'm thinking something like this (though I haven't tested it)
<Target Name="AfterEndToEndIteration">
<GetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
BuildUri="$(BuildUri)"
Condition=" '$(IsDesktopBuild)' != 'true' ">
<Output TaskParameter="Status" PropertyName="Status" />
</GetBuildProperties>
<Exec Condition=" '$(Status)'=='Succeeded' "
Command="TfsBuild.exe start /server:$(TeamFoundationServerUrl) /buildDefinition:"Your Build Definition To Run"" />
</Target>

I've done the same thing Martin suggested on a number of occasions (his blog is beyond helpful, BTW). However, I ended up needing to trigger cascading builds like this (based on some other complicated rules) enough that I created a custom task to do it. Keep your build scripts nice and lean and gives you some more flexibility and encapsulation possibilities.
public override bool Execute()
{
IBuildDefinition[] buildDefinitions = BuildServer.QueryBuildDefinitions(ProjectName);
foreach (IBuildDefinition build in buildDefinitions)
{
if(build.Enabled) //I did a bunch of custom rules here
{
Log.LogMessage(String.Concat("Queuing build: ", build.Name));
BuildServer.QueueBuild(build);
}
}
return true;
}
There's some more good stuff on Aaron Hallberg's blog too:
http://blogs.msdn.com/aaronhallberg/archive/2007/04/24/team-build-object-model-queueing-a-build.aspx

Related

ClickOnce myApp.application generated with wrong PublishUrl

I have added a MSBuild target to update the PublishUrl and then call the 'Publish' target, passing the new value in. This has allowed me to build multiple branches and have the corresponding ClickOnce app dropped in a branch specific share location.
<PropertyGroup>
<PublishUrl >\\someNetworkShare\</PublishUrl>
</PropertyGroup>
<Target Name="PublishClickOnce">
<PublishUrl>$(PublishUrl)$(BranchName)\</PublishUrl>
<MSBuild Projects="$(ProjectPath)" Properties="PublishUrl=$(PublishUrl); PublishDir=$(PublishUrl); Platform=AnyCPU" Targets="Publish" />
</Target>
The problem is that this just doesn't work on one of my build machines. It works perfectly fine on 2 of them, but not the 3rd.
Looking at the myApp.application file i can see that the deploymentProvider codebase points to the unchanged PublishedUrl (but it has been updated at the time of calling the 'Publish' target:
<deploymentProvider codebase="file://someNetworkShare/myApp.application" />
The above should be:
<deploymentProvider codebase="file://someNetworkShare/branchName/myApp.application" />
A few things i have tried:
Update the 'InstallUrl' to match the 'PublishUrl'
Added logging to ensure that the 'PublishUrl' has updated before calling the 'Publish' target.
Added a condition to the 'PublishUrl' to only update if it is empty
Any help would be much appreciated.
Thanks
-------------------------------- UPDATE --------------------------------
So a couple of things:
The working build machines are on W7, the failing machines are on a mixture of W7 and W8.
It turns out that you can exclude the deploymentProvider element (ProjectProperties -> Publish -> Manifest -> Exclude deployment provider URL). If excluded the system attempts to figure it out by its self at run-time (this is sufficient in most cases).
So I tested the build on a few more machines (a completely clean W7 VM, a W7 dev machine, W8.1 dev machine) and they both produced the incorrect deploymentProvider line.
Still curious to the actual root cause of the issue so I don't want to mark it as answered.

How to get build definition from TFS and pass it to the external program

How to get build definition from TFS and pass it to the external program
This is what we are doing manually:
1) Queue new build
2) Once build is completed go to the drop folder and get the exe name
3) pass this exe name to the test automation program and run it.`
I want to automate these 3 steps.
Is it possible to get the build definition programatically?
Create a custom Build Template. Use a copy of the default (or what ever you're using now) as your starting point. Look in the work flow where BuildDetail.CompilationStatus = BuildPhaseStatus.Succeeded. You will then have the opportunity to invoke another application, it would be a stub program/powershell script/any other executable process. you can pass the path of the build that you just completed by using BuildDetail.DropLocation.
Assuming that your step #1 has executed, this latest (successful!) build is reachable as the lastKnownGoodBuild of the specific build definition.With this in mind you can employ a console app that bases on the following:
using System;
using System.IO;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
namespace BuildDropLocation
{
class Program
{
static void Main()
{
TfsTeamProjectCollection teamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://yourTFSServerUri"));
var buildService = (IBuildServer)teamProjectCollection.GetService(typeof(IBuildServer));
IBuildDefinition myBuildDefinition = buildService.GetBuildDefinition("TeamProjectName", "BuildDefinitionName");
Uri lastKnownGoodBuild = myBuildDefinition.LastGoodBuildUri;
IBuildDetail myBuildDetail = buildService.GetBuild(lastKnownGoodBuild);
string[] myExeFiles = Directory.GetFiles(myBuildDetail.DropLocation, "*.exe",SearchOption.AllDirectories);
foreach (var exeFile in myExeFiles)
{
Console.WriteLine(myExeFile);
}
}
}
}
With the above you can retrieve the path to any *.exe under the drop location of the last build of build definition BuildDefinitionName that lives in Team Project TeamProjectName.This approach allows you to fully separate your TFS-Build with the execution of your tests. You can, for example, schedule this console-app to execute every night and invoke your runner to operate on the latest successful build.In case you would like the build and the testrun to be coupled in any way, you should proceed as #TimWagaman suggests by invoking your test runner during build. This 'coupling' might include:
The test results are contained in the build log
A failure generates a Bug
Test coverage is reportable
In this case, your tests will execute with each and every build that doesn't break in the compilation phase.
<MakeDir Directories="$(TemporaryFolder)" />
<Exec Condition=" '$(IsInTeamBuild)'=='True'" Command=""$(TfsTask)" history ../ /r /noprompt /stopafter:1 /version:W > "$(TemporaryFolder)\grab-changeset.txt"" />
<Exec Condition=" '$(IsInTeamBuild)'=='True'" Command=""$(TfsTask)" properties "$(MyMSBuildStartupDirectory)\all-companies-run-after-update.js" > "$(TemporaryFolder)\grab-properties.txt"" />
We use the above to extract: build#, branch, revision#
from the generated .txt files.

Get reference to the list of modifications from within Ant task

I'm try to develop a cruise control step which will process database migration scripts and apply them.
I'd like to be able to get hold of a list of the modifications from the SourceControl (to see if any new database changes need to be applied).
Any ideas how I can achieve this? I know that this information is written into the log xml but I was wondering if there is an easy mechanism to get a reference to this from with an Ant builder.
I have investigated writing a custom CC Listener or Builder plugin but neither supply this in the interface.
We have "svn update" as one of the steps in ant builder, and later we use output redirected to the file (ant property also could be used):
<exec executable="svn" dir=".">
<arg line="up"/>
<redirector output="svnup.log" alwayslog="true" append="true"/>
</exec>
<property name="svnup.log" value="svnup.log"/>
this creates file named "svnup.log" in the build folder with output of "svn up" command.
I think I'm going to try to write a custom plugin implementing Publisher
#Override
public void publish(Element cruisecontrolLog) throws CruiseControlException { XMLLogHelper xmlHelper = new XMLLogHelper(cruisecontrolLog);
Set<Modification> modifications = xmlHelper.getModifications();
for (Modification modification : modifications) {
handleModification(modification);
}
}
Or another idea is to use the timestamp flag in the sscm ant task combined with the cclastbuildtimestamp property supplied to the ant builder to produce a list of files changed since last build.

How to get Ant to ignore error from one target?

I have a target, comprised of several steps, that sometimes fails. All this target does is report to Sonar so if it fails, it's not catastrophic. How do I get the build to succeed even if this specific target fails?
I've tried some combinations of 'condition', 'or', 'true', and 'sequential', but Ant hasn't liked any of them.
Following is what I have more or less:
<target name='sonar'>
<!-- do some stuff -->
<sonar:sonar key='key' version='version'/>
</target>
The only way I can see this could work is using the slightly outdated yet still useful antcontrib extension. Then you can use a try/catch directive and just echo your error.
http://ant-contrib.sourceforge.net/tasks/tasks/trycatch.html

team build target not executed

I have a tfs 2008 build that I need to add WiX compliation to.
Currently the build executes and compiles and copies all output to a drops location in the following target
<Target Name="AfterCompile"> .... </Target>
I have added another target directly below it that looks like the following
<UsingTask TaskName="HeatDirectory" AssemblyFile="$(WixTasksPath)" />
<Target Name="BuildMsi" DependsOnTargets="AfterCompile">
<Message Text="Start harvesting Website files for Wix compliation" />
<HeatDirectory
ToolPath="$(WixToolPath)"
Directory="$(DropLocation)\Latest\x86\Release\_PublishedWebsites\IFMA.MasterPlan.Web"
GenerateGuidsNow="yes"
ComponentGroupName="Web"
OutputFile="$(MSBuildProjectDirectory)\Setup\Product\Fragments\wwwfiles.wxs"
SuppressFragments="yes"
DirectoryRefId="WebRoot"
KeepEmptyDirectories="yes"
PreprocessorVariable="var.WebRoot"
SuppressRegistry="yes"
SuppressRootDirectory="yes"
SuppressCom="yes"
/>
<Message Text="Finished harvesting Website files for Wix compliation" />
</Target>
The BuildMsi target is never executed but the AfterCompile one definitly is.
The BuildMsi isn't listed in the default build targets
but I thought that since it has a dependency on AfterCompile it would be executed after it.
What am I missing here?
DependsOnTargets lists the targets that must be executed before your target can run, it does not force your target to run after the list of targets run.
See: http://msdn.microsoft.com/en-us/library/t50z2hka(v=VS.90).aspx
If you're using MSBuild 4.0, AfterTargets attribute is what you need:
AfterTargets: Optional attribute.
A semicolon-separated list of target
names. When specified, indicates that
this target should run after the
specified target or targets. This
lets the project author extend an
existing set of targets without
modifying them directly.
Alternatively you can use target injection, which basically is overriding the CompileDependsOn property in your .proj file to include your target at the end. You need to declare this property after the imports of the common target files to ensure it is the last definition of the property.
<PropertyGroup>
<CompileDependsOn>
$(CompileDependsOn);
MyCustomTarget
</CompileDependsOn>
</PropertyGroup>
See "How to extend the visual studio build process" for more details.

Resources