Ant doesn't see when msbuild build failed - msbuild

As part of my Ant integration test script, I run an MSBuild build (just executing the msbuild.exe), and it works fine in the positive cases. However, Ant doesn't recognize when the msbuild build fails. How can I make it work?
EDIT:
I can msbuild by executing the executable:
<target name="executeMsbuild">
<exec command="C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe /t:build-for-tests ${csharp.dir}\msbuild.xml"/>
</target>

Provide failonerror attribute to exec.
Also provide a property formsbuild.exe path.
Also pass command line arguments as args
<target name="executeMsbuild">
<property name="msbuild-prog"
location="C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe"
/>
<exec
executable="${msbuild-prog}"
failonerror="true"
>
<arg value="/t:build-for-tests"/>
<arg file="${csharp.dir}/msbuild.xml"/>
</exec>
</target>

Using failonerror=true will give you an instant "BUILD FAILED" in case
of an error and will be sufficiant in most cases.
For a more sophisticated error handling use =
the try task from the Antelope tasksuite (1), which will give you a
try/catch/finally (2) as in java.
Antelope has also a limit task (3), which is a taskcointainer where other tasks
are put in and provided with a timeout.
Limit may be combined with try or use alone
In case someone mentions AntContrib, it's another ant task suite, that has
equivalent tasks as Antelope ,but it seems the development of AntContrib
has stopped (4)
(1) Antelope Tasksuite
(2) Manpage try task
(3) Manpage limit task
(4) Antelope <> AntContrib

Related

How can I enable "Treat Warnings as Errors" for my TransformXml task?

I'm using the following (heavily simplified) MSBuild script:
<?xml version="1.0"?>
<Project DefaultTargets="Transform" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="Transform">
<TransformXml Source="../web.config"
Transform="Config\Production\webapp.xml"
Destination="Config\Build\Production\web.config" />
</Target>
</Project>
This works great to transform a single configuration file without having to go through MSDeploy.
However, let's say in my Transform I misspell a variable. I will receive a warning:
C:\MyApp\DevOps\Config\Production\webapp.xml(15,6): warning : No element in the source document matches '/configuration/appSettings/add[#key='MyUnknownVariable']'[C:\MyApp\DevOps\ConfigBundle.msbuild]
While it's nice that we get a warning for this, I really need this to be an error because this will become part of our automated build and deployment process so it's unlikely anyone would spot it until an application stops working.
I would like a way to treat these warnings as errors. Based off some things I've seen on the internet, I've tried a PropertyGroup with two different TreatWarningsAsErrors symbols:
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup>
I've tried setting this on the command-line (which I suspect is the same as the above):
C:\MyApp\DevOps>msbuild /p:TreatWarningsAsErrors="true" ConfigBundle.msbuild
None of these work unfortunately; the warning continues to be sent. Based off that I'm guessing that it's down to the individual MSBuild task to respect the TreatWarningsAsErrors directive and in this case, TransformXml does not.
If I could find a way to learn if the last task threw a warning for example I could do something like:
<Message Text="##teamcity[message text='Config Transform Failed!' status='ERROR']" Condition="$WarningOccurred == 'true'" />
It's not exactly perfect but that would certainly stop the build from finishing successfully. Hopefully someone will have a helpful suggestion for this.
TreatWarningsAsErrors
Is used to instruct the different language Compilers to treat warnings as errors
CodeAnalysisTreatWarningsAsErrors
Is used to instruct Code Analysis to treat warnings as errors.
There is no general switch to treat all MsBuild warnings as errors. Generally the invoker of MsBuild would pass a logger to MsBuild to detect that a warning has occurred, this is what Team Build does for example. Then the calling tool can either pass or fail the overall build result.

MSbuild style cop extensions task to run on solution

I need help in running stylecop task on all cs files included in solution.
Please let me know if its possible and how?
Right now I can run it on a file, but not on solution.
<CreateItem Include="$(RootPath)\**\*.cs">
<Output TaskParameter="Include" ItemName="StyleCopFiles"/>
</CreateItem>
<MSBuild.ExtensionPack.CodeQuality.StyleCop
TaskAction="Scan"
ShowOutput="true"
ForceFullAnalysis="true"
CacheResults="false"
SourceFiles="#(StyleCopFiles)"
logFile="$(OutDir)\StyleCopLog.txt"
SettingsFile="$(MSBuildStartupDirectory)\..\Settings.StyleCop"
ContinueOnError="false">
<Output TaskParameter="Succeeded" PropertyName="AllPassed"/>
<Output TaskParameter="ViolationCount" PropertyName="Violations"/>
<Output TaskParameter="FailedFiles" ItemName="Failures"/>
</MSBuild.ExtensionPack.CodeQuality.StyleCop>
Have you considered automatically running StyleCop rules as a part of your project build process? This won't run all rules at the solution level but at a project level. I prefer this approach because the rules will run whenever you build your project/solution and will display as Warnings in the Error List panel (double click to navigate to the offending line of code). Configuring this on a project by project basis may seem like a pain but we have a different set of StyleCop rules for our Unit Test projects, and this allows us to configure them individually.
Also, You won't have to explicitly add a MSBuild task to your build script because building the projects will automatically execute the StyleCop rules.
It's also worth noting that I'm using the NuGet Package: StyleCop.MSBuild (version 4.7.17.1) and using a relative path to reference the package from within my .csproj file like this:
<Project>
<Import Project="..\Packages\StyleCop.MSBuild.4.7.17.1\tools\StyleCop.targets" />
</Project>
http://stylecop.codeplex.com/wikipage?title=Running%20StyleCop%20in%20VS2005%20or%20VS%20Express&referringTitle=Documentation
You can also set conditions on when you want the rules to run. If the condition evaluates to false StyleCop will not run. We use the condition to suppress StyleCop when running Unit Tests
<Project>
<Import Project="..\Packages\StyleCop.MSBuild.4.7.17.1\tools\StyleCop.targets" Condition="'$(NCrunch)'!='1'" />
</Project>
In order to configure StyleCop rules, you will need to install StyleCop_v4.7.17.0.msi. We only define a single Settings.StyleCop file (Parent Settings File) for our entire codebase.
http://stylecop.codeplex.com/wikipage?title=Sharing%20StyleCop%20Settings%20Across%20Projects&referringTitle=Documentation

Catching Errors from MSTest running inside MSBuild

I'm calling MSTest like this:
<Target Name='UnitTests'>
<CallTarget Targets="BeforeUnitTests" />
<Exec Command='"$(VS90COMNTOOLS)..\IDE\mstest.exe" /testmetadata:$(SourceCodeRootFolder)ASA.File.Processing.vsmdi /testlist:buildtests' />
<CallTarget Targets="AfterUnitTests" />
</Target>
It's running, but whether it succeeds or fails, no errors are written to the MSBuild error file. I'm running MSBuild with these parms:
/fl /flp:v=detailed;logfile=Errors.txt;errorsonly
I have emails set up to email our team if there are errors in the Errors.txt file.
Unless the MSTest program itself fails, you won't get errors in the MSBuild logfile, at least from the test portion of your build stream.
One of the MSTest options is to publish the results to TFS; you should be able to use standard notification setup there to let your teammates know what happened. Or you could use the resultfile parameter in the MSTest call and parse/publish based on what you find in the file.
We use Codeplex project Trx2Html to publish the results to an internal website that everyone has access to.

Make a target run once at the Solution level in MSBuild

I need a set of tasks that need to be executed exactly once for the entire solution. This will run tasks that will modify each project to run a separate set of tasks for each project. We had done this earlier using a separate project to the solution which had the solution level tasks, but we want to move away from that. Has anyone done this or does anyone have any suggestions on how to implement this?
Since Solution files are not in MSBuild format they are not easily extended or customized. If you want more control over the build process you would have to create a "driver" msbuild file which would replace your solution file. Inside this driver file you would build all the projects that you needed and perform some additional tasks. You would do this using the MSBuild task. Here is a sample showing how to build more than 1 project.
<Project ...>
<ItemGroup>
<Projects Include="proj01.csproj"/>
<Projects Include="proj02.csproj"/>
<Projects Include="proj03.csproj"/>
</ItemGroup>
<Target Name="BuildAll">
<MSBuild Projects="#(Projects)" BuildInParallel="true" />
</Target>
</Project>
So in your case you would just execute the tasks before you build the projects. Also note that I specified the value true for the BuildInParallel indicating that MSBuild can try and build more than one project at once.
An alternative solution is to have a single target that dispatches to an MSBuild invoked target with as many Global properties removed as possible. My team have a target in the InitialTargets of a Directory.Build.props Import'ed props file - something like:
<Target Name="Prebuild">
<MSBuild Projects="$(MSBuildThisFileFullPath)"
Targets="PrebuildWorker"
RemoveProperties="Configuration;Platform;TargetFramework;BuildProjectReferences" />
</Target>
Since MSBuild appears to synchronize parallel builds on the {project file, global properties, target} set, then by removing all of the properties you can synchronize the build and run it once for all projects being built. The downside: you have to maintain the RemoveProperties attribute - MSBuild doesn't have a way to remove all global properties. If something in the build issues a new MSBuild task with a custom property specified, then you'll get a second instance of the Target invoked.
And - of course - your build will be synchronized on this target. You could try hooking the target up by setting, say, CompileDependsOn to depend on the Prebuild target, to allow independent progress in the build. But to have the target run early and ubiquitously using InitialTargets seems like the better option.

Apache Ant command line arguments without double quotes - is it possible?

Today I had to add a task to an Apache Ant file. The command line should have been something like
myprogram --param1 --param2 path\somefile 2> path\logfile
The problem with this was that if I used something like the following for this
<exec executable="$(myprogram)"
<arg value="--param1">
<arg value="--param2">
<arg path="$(somefile)">
<arg value="2>">
<arg path="$(logfile)">
</exec>
all arguments were quoted, so the command looked like this:
myprogram "--param1" "--param2" "path\somefile" "2>" "path\logfile"
which is not bad and especially nice if you have spaces in your files/path, but destroys the pipe to the logfile (instead, the program thinks there are two additional file arguments "2>" and "path\logfile").
I worked around this by calling a batch script instead that only wants the files as parameters, but I wondered: Is it possible to do this without such a workaround?
When you run "myprogram --param1 --param2 path\somefile 2> path\logfile", the arguments to your program end at "2>". File redirection is an operation of your shell, which isn't being used from within ant. If you look at the docs for the ant exec task, you'll see that it supports redirection via the output attribute.
Have you tried <arg line="..." />?
The ant exec task has an output parameter where you could specify the log file without requiring the command line piping, combined with the parameter append to determine if the output file should be overwritten or appended to.
I had an equal problem as the topic starter did. On a java execution command line I needed to add source files as separate arguments, not as one argument with quotes around them.
I used the <arg value="..." /> tag, but using the <arg line="..." /> as nullptr suggested solved my problem.