I wonder what the ISProjectFolder, ISProductFolder, ISProjectDataFolder, ISPROJECTDIR (predefined paths) values are assigned when I build using TFS 2008 build agent
I think these can have different values from the values that are seen on local
does anyone know about this????
You can use the task to 'dump' the values you describe to the build log, i.e :
<!--Copy the installer files into the distribution location.-->
<Message Text="PATH TO SERVER INSTALL SET : $(ISServerOutputToBeCopied)" />
<exec command="xcopy "$(ISServerOutputToBeCopied)" "\\jupiter\Albany Products\In Development\EFT Corporate\ePay 1.5 Releases\1.5.$(AlbanyServicePackNumber)\$(BuildNumber)\ePay Server Installer" /i /s /e /h /y" />
</Target>
<!--Build the "ePay Client" Installer project.-->
<Target Name="CompileISClientProject"
DependsOnTargets="CustomCoreDropBuild"
Condition="('$(InstallShieldIsCmdBldPath)' != '') And ('#(ISClientProjectFile)' != '') And ('$(InstallShieldProductConfiguration)' != '' ) And ('$(InstallShieldRelease)' != '')">
<exec Command=""$(InstallShieldIsCmdBldPath)" -p "#(ISClientProjectFile)" -c "$(InstallShieldProductConfiguration)" -r "$(InstallShieldRelease)" -z "ARPCOMMENTS=$(BuildNumber)" -y "$(AlbanyMajorNumber).$(AlbanyMinorNumber).$(AlbanyServicePackNumber).$(AlbanyBuildNumber)"" IgnoreExitCode="true" />
<!--Copy the installer files into the distribution location.-->
<Message Text="PATH TO CLIENT INSTALL SET : $(ISClientOutputToBeCopied)" />
<exec command="xcopy "$(ISClientOutputToBeCopied)" "\\jupiter\Albany Products\In Development\EFT Corporate\ePay 1.5 Releases\1.5.$(AlbanyServicePackNumber)\$(BuildNumber)\ePay Client Installer" /i /s /e /h /y" />
</Target>
Hope that helps !
Related
I'm using TeamCity to build and deploy into our demo site. We have one configuration called HTML Demo Site and one of the build step is using NAnt to deploy the HTML to the site.
The build file have defined a target:
<target name="deploy-html" description="Deploys the HTML to the demo server">
<echo message="Deploying HTML to the demo server..."/>
<copy todir="\\<server>\<dir>\<client>" includeemptydirs="true" overwrite="true">
<fileset basedir="..\html\_master">
<include name="**\*"/>
<exclude name="node_modules\**"/>
</fileset>
</copy>
</target>
Each time I run the build on TeamCity, it's failing with this error:
C:\tc\w\9149e011dfa8657d\build_scripts\website.build(27,14):
[NAnt output] Error creating FileSet.
[NAnt output] The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
So I tried running on PowerShell to get a list of files that exceed the max length:
Get-ChildItem -Recurse | Where-Object {$_.FullName.Length -gt 248}
But the only files returned are files under the node_modules directory. But in the build file, it's being excluded. So I'm not sure where else to look? Any ideas?
You could try a few things:
Delete the node_modules dir first
Use robocopy /mir in an <exec> task
try putting exclude first before include (not likely, but worth a try)
try changing the path expression to name="node_modules\**\*" or name="**\node_modules\**" or similar
Deleting first worked for me - but the built in nant delete task also has problems so I had to use the rmdir console command
<exec program="${environment::get-variable('WinDir')}\system32\cmd">
<arg value="/c "rmdir /q /s ${Build.BuildFolder}\WebApplication\node_modules"" />
</exec>
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
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>
I have Cruise Control configured with a task to run a NAnt script, which runs an MSTest suite. MSTest allows me to specify test categories so I want to specify "!Integration" (which means "don't run Integration tests"). My Nant script successfully runs when I run it from the command line, but when Cruise runs it, the "!Integration" directive is being garbled -- the Cruise output suggests its inserting a line break after the '!' character. The result is that all my tests run, including integration tests.
Extract from ccnet.config:
<tasks>
<nant>
<executable>C:\nant\bin\nant.exe</executable>
<baseDirectory>C:\MyProject\BuildDirectory</baseDirectory>
<buildFile>MyProject.build</buildFile>
<targetList>
<target>CIServerBuild</target>
</targetList>
</nant>
</tasks>
Extract from MyProject.build:
<target name="CIServerBuild">
:
<call target="RunUnitTests" />
</target>
<target name="RunUnitTests">
<property name="TestCategories" value="!Integration" />
<call target="RunMSTest" failonerror="true"/>
</target>
<target name="RunMSTest">
<call target="BuildListOfTestContainers" failonerror="true"/>
<exec program="${MSTest.exe}"
commandline=" /category:"${TestCategories}" ${TestContainers} /resultsfile:${MSTest.ResultsFile} /nologo "
/>
</target>
Extract from Cruise output:
[exec] Starting 'C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe ( /category:"!
Integration" /testcontainer:C:\TaxWise\BuildDirectory\TaxWise\TaxWise.Data.Tests\bin\Debug\TaxWise.Data.Tests.dll /testcontainer:C:\TaxWise\BuildDirectory\TaxWise\TaxWise.Domain.Tests\bin\Debug\TaxWise.Domain.Tests.dll /testcontainer:C:\TaxWise\BuildDirectory\TaxWise\TaxWise.Infrastructure.Tests\bin\Debug\TaxWise.Infrastructure.Tests.dll /resultsfile:.\TestResults\UnitTests.trx /nologo )'
in 'C:\TaxWise\BuildDirectory'
I have tried replacing the '!' character with
'!'
but that made no difference.
Any ideas, anyone?
I suggest splitting the commandline attribute in the exec task into Nant arg elements.
http://nant.sourceforge.net/release/0.85/help/tasks/exec.html
You'll have more flexibility and the readability will increase.
Yes, perhaps it is not caused by CC. Try setting verbose="True" on the <exec> task and check the raw build protocol. Remember what you see on the report page is not the exact output (typically subject to line-wrap and coalescing whitespaces).
Maybe it depends on from where you run the script, a hidden dependency on a build property or different environment variables. You can check the latter using <exec program="cmd.exe" commandline="/c set" />. For the properties you can use the following script:
<script language="C#" prefix="util" verbose="true">
<code>
<![CDATA[
public static void ScriptMain(Project project)
{
foreach (DictionaryEntry entry in new System.Collections.SortedList(project.Properties) )
Console.WriteLine("{0}={1}", entry.Key, entry.Value);
}
]]>
</code>
</script>
I am trying to copy a folder to a remote machine using xcopy. This command is executed via cruise control task. I can run xcopy source destOnRemoteMachine successfully if i am running it from command prompt. But if i am executing it from cruise control .net, it is always complaining about "Invalid drive specification" error.
I tried :
> <exec
> executable="c:\Windows\System32\xcopy.exe">
> <baseDirectory>$(BASE)\Project</baseDirectory>
> <buildArgs>.\*.* RemoteMachine\Project /Y</buildArgs>
> <buildTimeoutSeconds>10</buildTimeoutSeconds>
> <successExitCodes>-1,0,1</successExitCodes>
> </exec>
and :
<exec executable="c:\Windows\System32\cmd.exe">
<baseDirectory>$(BASE)\Project</baseDirectory>
<buildArgs>/C xcopy $(BASE)\Project\*.* RemoteMachine /y</buildArgs>
<buildTimeoutSeconds>30</buildTimeoutSeconds>
<successExitCodes>-1,0,1</successExitCodes>
</exec>
Any Suggestions?
thanks for your answer. Putting xcopy in batch was also not helpful, the problem was something else. here is problem:
It was problem with the account on which Cruise Control .net service was running. It was running as local service. Thus was not able to see the network path. I changed CCNet Service to run on a domain account which have permission to read/ write on remote machine. This solved my problem.
Thanks.
Create a batch file using xcopy source destOnRemoteMachine command and execute that bat file using <exec> command in cruise control .net
In my case I was running CC as a user account, after having used NET USE to persistently map a drive letter to a network share on another domain. Although it worked in a desktop session, CC could still not get to the share as part of the build. Executing NET USE as part of the build (without a drive mapping) allowed the copy to succeed.
<exec program="net" verbose="true">
<arg value="use" />
<arg value="\\server\share" />
<arg value="password" />
<arg value="/user:domain\username" />
</exec>