Tuesday, January 29, 2008

Skipping post-build in VS project in Team Build

Interesting question has come up in the forums: "If one has custom pre- or post- build logic in Visual Studio projects, that are being built both on desktop and using Team Build, how one would disable the pre-/post-build for non-desktop build?".
Or to be more concise - is there any property available that makes it possible to detect, whether the build is being performed from Visual Studio or from Team Build process?

Now, Team Build build types will simply call MSBuild task with the solution(s) to build; will Team Build pass any custom properties to MSBuild with the solution files?

It turns out that Team Build does indeed pass such property, named TeamBuildConstants; thus when the solution will be built from the Team Build script, the property will get the value of _TEAM_BUILD_, as defined in Microsoft.TeamFoundation.Build.targets file.

Then Visual Studio project (C# and VB.NET alike) can be modified in the following manner:


<!-- Prebuild logic will be executed both in VS and Team Build compilations -->
<Target Name="BeforeBuild">
    <Exec Command="attrib -r $(TargetPath)"/>
</Target>

<!-- Postbuild logic that will not be executed in Team Build-->
<Target Name="AfterBuild" Condition="'$(TeamBuildConstants)' == ''">
    <Copy SourceFiles="$(TargetPath)"
      DestinationFolder="$(SolutionDir)\bin\$(ConfigurationName)" />
</Target>

Team Build targets file also exposes property with very tempting name - SkipPostBuild; however, modifying the property value in TFSBuild.proj will have no effect on the projects post build logic. Setting SkipPostBuild property to false disables running GenCheckinNotesUpdateWorkItems task during Team Build build, and thus has no connection to Visual Studio projects logic.

Saturday, January 19, 2008

Using WIQL EVER with dates - dont!

One of very neat predicates available in Work Item Query Language is EVER conditional clause. It allows one to specify conditions similar to "was the value of the <field> ever <X>". Typical example of a query - list of all tasks ever assigned to myself:

SELECT [System.Id], [System.AssignedTo]
FROM WorkItems
WHERE [System.TeamProject] = 'Project1' AND [System.AssignedTo] EVER @me
ORDER BY [System.Id]

That feature is very convinient (saves all that ugly EXISTS queries of traditional SQL); however, it turned out it is not without its limitation.

Some time ago there was an interesting question on MSDN forums: "How one would use EVER to get work items specified at certain date?" Though MSDN says that date time fields should work with EVER operator, in reality it appears that the operator will not function correctly.

My guess is that EVER uses the exact field value to test against - and for the date time fields that includes time portion of the value. That of course limits its usefulness (while the query of whether certain work item was modified on date X is of value, nobody cares what work item was modified on date X at 12:33.56 :).

So the purpose of that post is to save you some time - do not attempt to use EVER with dates; depending on your actual objective the answer may be in WIQL or you might have to do additional filtering programmatically.

Friday, January 18, 2008

Specifying date and time in WIQL queries

When creating Work Item queries, sometimes it may be required to specify not only date, but time also for the query condition. For myself, I usually use that when I need to find all work items changed relative to certain event - for example, labeling of the source code; and as it happens, there may be several such events in one day, so the time is of importance.

The obvious solution is to specify a query similar to "Closed Date > 1/1/2008 10:00" (or in pure WIQL: [Microsoft.VSTS.Common.ClosedDate] > '2008-01-01T10:00:00.0000000').

But life is not that simple. What you get on running the query is the error message, saying "You cannot supply a time with the date when running a query using date precision. The error is caused by '[Microsoft.VSTS.Common.ClosedDate] > '2008-01-01T10:00:00.000'".

Without trying to analyze the message too much, one can surmise from it that currently only dates can be specified in query conditions, and apparently you need to change the precision from date to "date time". Easy enough, huh? So how do we change the precision?

You are in for a surprise - you cannot change the precision. If you ran the query in VS, you will always have the date precision and will not be able to specify times. However, there is sort of workaround if you are really hot for the query results. You will have to write a small bit of code (interestingly, the object model API allows one to specify the precision for the query), as demonstrated below:


TeamFoundationServer server = TeamFoundationServerFactory.GetServer("10.18.40.201");

WorkItemStore wit = new WorkItemStore(server);

stringwiql = @"SELECT [System.Id], [Microsoft.VSTS.Common.ClosedDate] 

                FROM WorkItems 

                WHERE [System.TeamProject] = 'Project1' AND 

                [Microsoft.VSTS.Common.ClosedDate] > '2008-01-01T10:00:00.00' 

                ORDER BY [System.Id]";

Query qry = new Query(wit, wiql, null, false);

ICancelableAsyncResult car = qry.BeginQuery();

WorkItemCollection items = qry.EndQuery(car);


The trick is in the fourth parameter passed to the Query class constructor (setting false specifies that date and time precision should be used instead of default date precision).

The documentation on that parameter is rather cryptic; I am not aware of any additioanl docs on WIQL precision.

While the issue is not critical, the lack of the date time precision in VS work item queries is a bit of a nuisance (as far as I know, VS2008 still suffers from that). Hope that Rosraio will handle that.