Specifying results filename for vstest.console.exe - visual-studio-2012

May be a silly question, but does anybody know how to specify the output filename of a VSTEST.Console.exe run? My command line is as follows:
vstest.console.exe [assembly] /logger:trx
At the end of the run, the following comes up in the console:
ResultsFile: somepath\TestResults\{username}_{workstation} {timestamp}.trx
I tried using the .runsettings file to specify the output location, but that only seems to control the output directory, but not the output file. Have not found anything else that would seem to control it.
I want to parse the TRX file and generate a report out of it (this already works, but if I can't specify the output path of the TRX file, I won't know where to pick it up from in the scripts!)
I have to be missing something here...

EDIT: See #AnaFranco's answer - apparently since VS2017 the file name can be configured like so:
vstest.console.exe [assembly] /logger:trx;LogFileName=[filename].trx
I'll leave the old answer for posterity and pre-2017 versions.
Nope, you're not missing anything. The TRX logger doesn't support any parameters (unlike the TFS publisher logger).
The logger assembly is located in "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions\Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.dll". If you check it out in your favorite .NET decompiler, you'll see the method TrxLogger.GetTrxFileName. It uses some basic knowledge about the current test run to produce the mangled name of form {username}_{workstation} {timestamp}.trx and is in no appreciable way configurable.
As far as I can tell, the TRX file is created in the TestResults\ folder under the current working directory unless otherwise configured. What you can do is:
Create a new temporary folder
Change the current directory to it
Run the test runner
Scan the folder for the result .trx file using your favorite recursive file search method and you're done
At least that is what I do in our build (MSBuild, sob):
<ItemGroup>
<TestResult Include="**\*.trx"/>
</ItemGroup>
I.e, gather all .trx files under the current directory and stuff them into the #(TestResult) item group for further processing.

This has worked for me for testing .net core I haven't tried it with .net framework:
vstest.console.exe [assembly] /logger:trx;LogFileName=[filename].trx
Maybe its a new thing
Update: This works for .net framework projects too using the latest Test platform and vstest.console.exe

Apparently, you can specify a directory where to put the *.trx file (not of the file itself though). This is, however, done via .runsettings file rather than via command line.
Excerpt from Bhuvaneshwari's blog:
If the default location of results need to be overriden user need to
pass this value using a runsettings file.
Example:
Mstest.exe /testcontainer:abc.dll /results:C:\Results.trx
Vstest.console.exe abc.dll /settings:output.runsettings
where the context of the
.runsettings file would be something like below :
<?xml version="1.0" encoding="UTF-8"?>
<RunSettings>
<RunConfiguration>
<ResultsDirectory>c:\</ResultsDirectory>
</RunConfiguration>
</RunSettings>

I had this issue as well. I decided to write a MSBuild target that executes vstest.console via the EXEC task, handling all its outputs, including the coverage results.
Basically, I captured the vstest output and used a regex to capture the *.trx and *.coverage portion of the output, which turned out to be really easy. Plus, it removes the TestResults directory to keep the workspace nice and clean.
In the end, you will get the *.trx file and the *.coverage file (optionally).
The script may look a bit complex, but it was necessary to fit our needs. I tried to clean it up a bit.
Hope this helps.
<Target Name="Test" DependsOnTargets="Build">
<!-- Declare the defaults and arrange parameters -->
<PropertyGroup>
<ArtifactsPath Condition=" '$(ArtifactsPath)' == '' ">Artifacts</ArtifactsPath>
<VSTestSessionName Condition=" '$(VSTestSessionName)' == ''">TestResults</VSTestSessionName>
<VSTestExe Condition=" '$(VSTestExe)' == '' ">C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe</VSTestExe>
<VSTestFailBuildOnTestFail Condition=" '$(VSTestFailBuildOnTestFail)' == '' ">false</VSTestFailBuildOnTestFail>
<VSTestInIsolation Condition=" '$(VSTestInIsolation)' == '' ">true</VSTestInIsolation>
<VSTestUseVsixExtensions Condition=" '$(VSTestUseVsixExtensions)' == '' ">true</VSTestUseVsixExtensions>
<VSTestFramework Condition=" '$(VSTestFramework)' == '' ">framework45</VSTestFramework>
<VSTestLogger Condition=" '$(VSTestLogger)' == '' ">trx</VSTestLogger>
<ErrorCode>0</ErrorCode>
</PropertyGroup>
<ItemGroup>
<VSTestResultsPath Include="$(VSTestResultsPath)" />
<VSTestParams Include="#(VSTestFiles ->'"%(FullPath)"', ' ')" />
<VSTestParams Condition="$(VSTestEnableCodeCoverage)" Include="/EnableCodeCoverage" />
<VSTestParams Condition="$(VSTestInIsolation)" Include="/InIsolation" />
<VSTestParams Include="/UseVsixExtensions:$(VSTestUseVsixExtensions)" />
<VSTestParams Include="/Framework:$(VSTestFramework)" />
<VSTestParams Include="/Logger:$(VSTestLogger)" />
<VSTestParams Condition="$(VSTestCaseFilter) != ''" Include="/TestCaseFilter:"$(VSTestCaseFilter)"" />
<VSTestParams Condition="$(VSTestRunSettings) != ''" Include="/Settings:"$(VSTestRunSettings)"" />
</ItemGroup>
<Message Text="TestAssembly: %(VSTestFiles.Identity)" Importance="high"/>
<Exec ContinueOnError="!$(VSTestFailBuildOnTestFail)" ConsoleToMSBuild="true" WorkingDirectory="$(WorkingDirectory)" Condition=" '#(VSTestFiles)' != ''"
Command=""$(VSTestExe)" #(VSTestParams, ' ')">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode"/>
<Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
</Exec>
<Message Importance="high" Text="VSTest exitcode: $(ErrorCode)"/>
<!-- Use the VSTest output to discover the Results & Coverage files respectively -->
<PropertyGroup>
<!-- Unencoded Regex: (?<=(Results file: )).*?(?=\;)|(?<=(Attachments:;)).*?(?=\;) -->
<ResultsFileRegexPattern>(?<=(Results File: )).*.trx</ResultsFileRegexPattern>
<CoverageFileRegexPattern>(?<=(Attachments:;)).*.coverage</CoverageFileRegexPattern>
<SourceResultsFile>$([System.Text.RegularExpressions.Regex]::Match($(OutputOfExec), $(ResultsFileRegexPattern)))</SourceResultsFile>
<SourceCoverageFile Condition="$(VSTestEnableCodeCoverage)">$([System.Text.RegularExpressions.Regex]::Match($(OutputOfExec), $(CoverageFileRegexPattern)))</SourceCoverageFile>
</PropertyGroup>
<ItemGroup>
<TestArtifact Include="$(SourceResultsFile)" />
<TestArtifact Include="$(SourceCoverageFile)" />
</ItemGroup>
<Warning Condition=" '$(SourceResultsFile)' == '' " Text=".trx file not found" />
<Warning Condition=" $(VSTestEnableCodeCoverage) and '$(SourceCoverageFile)' == '' " Text=".coverage file not found" />
<!-- Copy files to the artifact directory -->
<Copy SourceFiles="#(TestArtifact)" DestinationFiles="#(TestArtifact->'$(ArtifactsPath)\$(VSTestSessionName)%(Extension)')" />
<!-- Clear the test results temporary directory -->
<RemoveDir Directories="#(TestResults)" />
<ItemGroup>
<TestFile Include="$(ArtifactsPath)\**\$(VSTestSessionName).trx" />
<CoverageFile Include="$(ArtifactsPath)\**\$(VSTestSessionName).coverage" />
</ItemGroup>
<Message Text="TestReport: #(TestFile)" />
<Message Text="CoverageReport: #(CoverageFile)" />
</Target>

Related

Visual Studio Online - DevOps

Current client we are setting up CI/CD using VSO => Azure devops and I need some help with the configuration of the releases in the environments. Here's the situation and issue.
I've got the builds all set up and working properly.
I've got 2 Environments set up in the release configuration. Artifact is set up for the drops. Dev environment is set up as well as QA.
In VS2015 I've got the web.config transforms and configurations set up for Debug, Dev, QA, and Release. Dev/QA/Release each have a transformation that is to be applied for their respective enviornment.
Build triggers upon checkin and the release deployment triggers correctly upon successful build.
Dev environment and QA environment both trigger correctly in the release and are released accordingly.
In the task configuration for each I've got the XML Transformation selected as well as the correct deployment slot. The issue is that the only web.config transformation that is being applied is the release transformation not the correct transformation for the respective environment.
I have 4 transformation configs in the environment set up.
web.config
web.Debug.config
web.Dev.config
web.QA.config
web.Release.config
in VSO I have 2 environments set up in the Release Package
Dev & QA
In each of the environment I have the XML Transformation check which the tooltip states that it will apply the web.Release.config and each respective environment config.
The later is not happening.
logs:
the logs state:
Unable to apply transformation for the given package. Verify the following.

1. Whether the Transformation is already applied for the MSBuild generated package during build. If yes, remove the tag for each config in the csproj file and rebuild.

2. Ensure that the config file and transformation files are present in the same folder inside the package.
Both of those states have been confirmed. I've got the transform configs set to copy if newer.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.8\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.8\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.Default.props" Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.Default.props')" />
<Import Project="..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{88941EE6-99FC-4DE5-8FE3-9F532FD855F2}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TripManager</RootNamespace>
<AssemblyName>TripManager</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
<UseIISExpress>true</UseIISExpress>
<IISExpressSSLPort>44385</IISExpressSSLPort>
<IISExpressAnonymousAuthentication>disabled</IISExpressAnonymousAuthentication>
<IISExpressWindowsAuthentication>enabled</IISExpressWindowsAuthentication>
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<TargetFrameworkProfile />
<Use64BitIISExpress />
<TypeScriptToolsVersion>1.8</TypeScriptToolsVersion>
<ApplicationInsightsResourceId>/subscriptions/ee4492d7-5913-4e7b-85c0-3915e8c6c5c2/resourcegroups/rg-TripTracker-dev-SC/providers/microsoft.insights/components/TripManager</ApplicationInsightsResourceId>
<WebProject_DirectoryAccessLevelKey>1</WebProject_DirectoryAccessLevelKey>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Dev|AnyCPU'">
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QA|AnyCPU'">
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
</Project>
The problem is that config transform files are not included in the build result.
Ensure that the config file and transformation files are present in
the same folder inside the package.
Marina Liu's answer could work, but there is a much simpler way to achieve this:
The transform file should not be Dependent upon web.config. Just create a new file in the same directory as the web.config file.
Set the Build Action of the transform file to Content.
Or just change the entry in the .csproj file from this:
<None Include="Web.QA.config">
<DependentUpon>Web.config</DependentUpon>
</None>
To this:
<Content Include="Web.QA.config" />
This makes sure the files are included in the package after build.
No matter whether the transformation is applied for the MSBuild generated package or not, add the config files to the zipped package (as option 2 in release log suggests: Ensure that the config file and transformation files are present in the same folder inside the package) should work.
So you can add the config files in your build definition before the artifacts published. Detail steps as below:
After Visual Studio Build task (and before Publish Build Artifacts) and the following tasks to extract the zip file and add config files in the extract folder, then zip the files again:
1. Extract files task
Archive file patterns: $(Build.ArtifactStagingDirectory)\*.zip
Destination folder: specify the folder for the extract files, such as $(Build.ArtifactStagingDirectory)\test
2. Copy Files task
Source Folder: $(Build.SourcesDirectory)
Contents: **\*.config
Target Folder: Folder for the extract files, such as $(Build.ArtifactStagingDirectory)\test
3. Delete Files task
Source Folder: $(Build.ArtifactStagingDirectory)
Contents: *.zip (delete the zip file which generated by Visual Studio Build task)
4. Archive Files task
Root folder (or file) to archive: Folder for the extract files, such as $(Build.ArtifactStagingDirectory)\test
Archive type: zip
Archive file to create: such as $(Build.ArtifactStagingDirectory)\package.zip
5. Delete Files task
Source Folder: $(Build.ArtifactStagingDirectory)
Contents: delete the extract folder,such as test
Then the package will be deployed to Azure App Service successful in release.

How can I timestamp IIS Web deployment packages made with Visual Studio 2013?

Right now I can deploy a package to a directory but we may want to have a weekly deployment package so is there some easy way to append the filename of the deployment zip file with a timestamp ?
You can make MSBUILD script which makes such deployment package for you:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
<BasePackageName>TestPackage</BasePackageName>
<BuildTime>$([System.DateTime]::Now.ToString("yyyy-MM-dd-HH-mm-ss"))</BuildTime>
<DeployDir Condition=" '$(DeployDir)' == '' ">$(MSBuildProjectDirectory)\Output</DeployDir>
<PackageFileName Condition=" '$(PackageFileName)' == '' ">$([System.String]::Format("{0}\{1}_{2}.zip", $(DeployDir), $(BuildTime), $(BasePackageName)))</PackageFileName>
</PropertyGroup>
<Target Name="CheckProperties">
<Error Condition=" '$(ProjectFile)' == '' " Text="ProjectFile is required." />
</Target>
<Target Name="Build" DependsOnTargets="CheckProperties">
<!-- Deploy using windows authentication -->
<Message Text="Creating $(PackageFileName)" />
<MSBuild Projects="$(ProjectFile)"
Targets="WebPublish"
Properties="Configuration=$(Configuration); WebPublishMethod=Package; DeployOnBuild=true; PackageFileName=$(PackageFileName);"
/>
<Message Text="$(PackageFileName) successfully created!" />
</Target>
</Project>
It will create in deploy dir (DeployDir script parameter, with $(MSBuildProjectDirectory)\Output as default value) files:
2014-06-23-17-04-21_TestPackage.zip
2014-06-23-17-04-21_TestPackage.deploy.cmd
2014-06-23-17-04-21_TestPackage.deploy-readme.txt
2014-06-23-17-04-21_TestPackage.SetParameters.xml
2014-06-23-17-04-21_TestPackage.SourceManifest.xml
This script requires ProjectFile parameter to be set.
To run this MSBUILD script you can use the following bat file (let's save MSBUILD script in the same directory with name deploy.xml) or use autobuild server.
set WORK_DIR=%~dp0
pushd %WORK_DIR%
set VSTOOLS="%VS120COMNTOOLS%"
if %VSTOOLS%=="" goto vsnotfounderror
call "%VSTOOLS:~1,-1%vsvars32.bat"
if errorlevel 1 goto end
msbuild.exe deploy.xml "/p:ProjectFile=%1"
if errorlevel 1 goto end
:vsnotfounderror
echo "Can't find Visual Studio 2013"
:end
popd
exit /b %ERRORLEVEL%
Now run this script:
deploy.bat TestSolution\TestWebApplication.csproj

How to setup building steps for CruiseControl.net from repository of the building project?

I'd like to store ccnet.config file (or other cc.net configuration file for this project) in the repository (git) of my project and make CC.NET use it when I force building from dashboard. How can I do it?
Thank you!
Your "ccnet.config" should remain fairly static.
If you need different "logic" for your solution/project building, then I suggest:
1. Write your ccnet.config code to pull source code from repository. (aka, Task #1)
2. In your repository, include a MasterBuild.proj (msbuild definition).
3. Have cc.net call msbuild.exe on MasterBuild.proj (aka, Task #2).
4. Have the majority of your logic inside the MasterBuild.proj file. That is what you check in/out of source control.
If you think of CC.NET as a "super fancy msbuild.exe executor", you're world will make more sense IMHO.
Here is a very basic msbuild (definition) file.
You can call it
MySolutionMasterBuild.proj (or similar)
Put this in the same directory as your .sln file (in source control).
Use CC.NET to download the code.
Then wire up msbuild.exe to call the below file.
Then have any extra logic inside the .proj file.
You can do some of the other CC.NET stuff, like post build emailing and merging any results xml, but the majority of the logic (my preference anyways)..........would be in the file below.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="AllTargetsWrapped">
<PropertyGroup>
<!-- Always declare some kind of "base directory" and then work off of that in the majority of cases -->
<WorkingCheckout>.</WorkingCheckout>
<ArtifactDestinationFolder>$(WorkingCheckout)\ZZZArtifacts</ArtifactDestinationFolder>
</PropertyGroup>
<Target Name="AllTargetsWrapped">
<CallTarget Targets="CleanArtifactFolder" />
<CallTarget Targets="BuildItUp" />
<CallTarget Targets="CopyFilesToArtifactFolder" />
</Target>
<Target Name="BuildItUp" >
<MSBuild Projects="$(WorkingCheckout)\MySolution.sln" Targets="Build" Properties="Configuration=$(Configuration)">
<Output TaskParameter="TargetOutputs" ItemName="TargetOutputsItemName"/>
</MSBuild>
<Message Text="BuildItUp completed" />
</Target>
<Target Name="CleanArtifactFolder">
<RemoveDir Directories="$(ArtifactDestinationFolder)" Condition="Exists($(ArtifactDestinationFolder))"/>
<MakeDir Directories="$(ArtifactDestinationFolder)" Condition="!Exists($(ArtifactDestinationFolder))"/>
<Message Text="Cleaning done" />
</Target>
<Target Name="CopyFilesToArtifactFolder">
<ItemGroup>
<MyExcludeFiles Include="$(WorkingCheckout)\**\*.doesnotexist" />
</ItemGroup>
<ItemGroup>
<MyIncludeFiles Include="$(WorkingCheckout)\bin\$(Configuration)\**\*.*" Exclude="#(MyExcludeFiles)"/>
</ItemGroup>
<Copy
SourceFiles="#(MyIncludeFiles)"
DestinationFiles="#(MyIncludeFiles->'$(ArtifactDestinationFolder)\%(Filename)%(Extension)')"
/>
</Target>
</Project>
Take a look at the scenario's at
http://www.cruisecontrolnet.org/projects/ccnet/wiki/Build_Server_Scenarios
Step 1 Setting up Source Control
Step 2 Build on Check-in
Step 3 Add unit tests
Step 4 Add Coverage
Step 5 Add source code analysis
There are build scripts foreseen in each step where you can base yourself on.

Always execute target in project on solution rebuild even when project is not modified

I have an msbuild target that invokes external generator and has to be always executed on solution rebuild even if project that contains this target was not modified.
I have tried appending to $(BuildDependsOn) but it is only executed if project was modified.
Essentially I have to extend mechanism that msbuild uses to check whether project was modified to plug my own check.
I guess you tried do it this way:
<Target Name="MyCustomBeforeBuild" BeforeTargets="BeforeBuild" Inputs="#(Compile)" Outputs="#(Compile->'%(RecursiveDir)%(Filename)%(Extension).generated')">
<Message Text="MyCustomBeforeBuild Begin" Importance="High" />
<Copy SourceFiles="#(Compile)" DestinationFiles="#(Compile->'%(RecursiveDir)%(Filename)%(Extension).generated')" />
<Message Text="MyCustomBeforeBuild End" Importance="High" />
</Target>
In this case MSBuild will use incremental build and evaluates that no file were modified based on timestamp comparison of input and output files.
In this case you can see in detailed or in diagnostic log message like this
Skipping target "MyCustomBeforeBuild" because all output files are up-to-date with respect to the input files.
But by specifying “fake outputs” (see .fake in Outputs attribute of Target) you can force MSBuild execute it every time (because fake file does not exist, no timestamp comparison will happen so it is always executed).
<Target Name="MyCustomBeforeBuild" BeforeTargets="BeforeBuild" Inputs="#(Compile)" Outputs="#(Compile->'%(RecursiveDir)%(Filename)%(Extension).generated.fake')">
<Message Text="MyCustomBeforeBuild Begin" Importance="High" />
<Copy SourceFiles="#(Compile)" DestinationFiles="#(Compile->'%(RecursiveDir)%(Filename)%(Extension).generated')" />
<Message Text="MyCustomBeforeBuild End" Importance="High" />
</Target>

Create file that keeps time and revision number of my project when I compile

Currently the file is only keeping the latest revision. I want to use a different file where the history is kept. Each time ANT is used, I want it to append the time and revision number on that file. On the home screen I will just have a link to that file.
This is how its written now:
<target name="compile-java" depends="prepare,compile">
<exec dir="${project.dir}" executable="tools/version.sh" output="${src.web.dir}/date_compile.jsp">
<arg line="" />
</exec>
<propertyfile file="${src.web.dir}/date_compile.jsp">
</propertyfile>
</target>
I want to append new revision while keeping old revision data too.
This is just a matter of using the BuildNumber or PropertyFile task to create the build version number file and then read the file to get that number, create also a timestamp of the build and then append them both to another file.
Here is a basic idea of how to do it. Starting from that you should be able to write something of the likes of this:
<project default="increment">
<target name="increment">
<tstamp>
<format property="build.time" pattern="yyyy-MM-dd HH:mm:ss" />
</tstamp>
<propertyfile file="build.properties">
<entry key="build.number" type="int" operation="+" default="0" />
</propertyfile>
<property file="build.properties" />
<echo message="Build ${build.number} on ${build.time}
" append="true" file="build.history" />
</target>
</project>
This creates two files: build.properties with your build number (always the last number as it is overwritten on each build) and build.history that contains a list of build numbers and a timestamp of each build.
EDIT : Based on the comments, if the version.sh outputs the revision and date to date_compile.jsp and overrides it on each build then - to keep history - you just need to load date_compile.jsp in your build and append its content to another file, something like this:
<target name="compile-java" depends="prepare,compile">
<exec dir="${project.dir}" executable="tools/version.sh" output="${src.web.dir}/date_compile.jsp">
<arg line="" />
</exec>
<loadfile property="revision" srcfile="${src.web.dir}/date_compile.jsp" />
<echo message="${revision}<br>
" append="true" file="${src.web.dir}/compile_history.jsp" />
</target>
Not 100% sure what you want, but it looks like a combination of <tstamp/>, <echo>, and <propertyfile/>.
You can use <propertyfile> to specify the property file where the build number is stored, and for editing it:
<propertyfile file="${build.prop.file}">
<entry key="build.number"
value="1"
default="0"
operation="+"/>
</propertyfile>
Now, you can include that property file in your build:
<property file="${build.prop.file}"/>
Which will set ${build.number}.
Next, you're going to get the date and time:
<tstamp>
<format property="build.time.stamp"
pattern="yyyy-mmm-dd.hh:mm:ss-zzzzz"/>
</tstamp>
Now, you'll append this to your log file
<echo append="true" file="${build.log}"
message="Building build # ${build.number} on ${build.time.stamp}"/>

Resources