The expression "[System.Version]::Parse('')" cannot be evaluated. Version string portion was too short or too long - string

So,
I keep having this error:
Severity Code Description Line Suppression State
Error MSB4184 The expression "[System.Version]::Parse('')" cannot be evaluated. Version string portion was too short or too long. ...\.nuget\packages\gitinfo\2.2.0\build\GitInfo.targets 218
whenever I build/rebuild my solution. After trying to build it several times it runs perfectly but it takes a lot building the solution, so I take like 3 to 5 times more time to build and test my changes.
Here is the error-related code:
<Target Name="_EnsureGit">
<Exec Command='$(GitExe) --version'
EchoOff='true'
ContinueOnError='true'
ConsoleToMSBuild='true'
StandardErrorImportance='high'
StandardOutputImportance='low'>
<Output TaskParameter="ConsoleOutput" PropertyName="_GitOutput"/>
<Output TaskParameter="ExitCode" PropertyName="MSBuildLastExitCode" />
</Exec>
<Error Condition="'$(MSBuildLastExitCode)' != '0'" Text="Failed to run `git --version`. Git may not be properly installed: %0A $(_GitOutput)" />
<PropertyGroup>
<_GitCurrentVersion>$([System.Text.RegularExpressions.Regex]::Match("$(_GitOutput)", "\d+\.\d+\.\d+").Value)</_GitCurrentVersion>
</PropertyGroup>
<Error Condition="$([System.Version]::Parse('$(_GitCurrentVersion)').CompareTo($([System.Version]::Parse('$(GitMinVersion)')))) < 0"
Text="Required minimum git version is $(GitMinVersion) but found $(_GitCurrentVersion)." />
</Target>
As I said, the error disappears after some tries to build but it's really annoying and time consuming. I reinstalled VS2022, recloned my repo, reinstalled git, deleted the ".nuget" folder but the problem still occurs.
What should I do?

Related

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>

Specifying results filename for vstest.console.exe

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>

CruiseControl.net 1.5.7256.1: my build fails but the dashboard shows success

We are experiencing issues with CruiseControl.Net 1.5.7256.1. Our builds are showing success when they actually fail. We force the build, it runs unit tests, some units tests fail and it shows success. We are using an exec task to execute an ant script. Here's the target that executes the tests:
<target name="test" depends="build" description="unit test" >
<copy file="configuration_notag.txt" tofile="${build.dir}\configuration.txt"/>
<junit errorProperty="test.failed" failureProperty="test.failed">
<formatter type="brief" usefile="false" />
<formatter type="xml" />
<classpath refid="classpath" />
<test name="${test1.class}" />
<test name="${test2.class}" />
</junit>
<fail message="Tests failed: check test reports." if="test.failed" />
</target>
Here is the output in the build file:
Errors: (4)
[junit] Test TestNoTag FAILED
BUILD FAILED
C:\sandbox\idblue\idblue\trunk\Unit_Test\IDBlueJavaWindowsUnitTest\build_notag.xml:43: Tests failed: check test reports.
Total time: 2 minutes 37 seconds
Since ant is failing, returning a failure error code, why isn't cruisecontrol picking up on it? There's nothing to note in our ccnet.config file, it just calls ant with the proper build file. We did not have this problem with CruiseControl.Net 1.4.2. Has anyone else ran into this issue? Googled the problem but found nothing.
I figured out what the problem was after, I needed to add this to the last line of ant.bat:
exit %ERRORLEVEL%
This persisted the exit code back to CruiseControl and the build finally started failing properly.

Integrating PartCover.NET with NAnt

I'm trying to integrate PartCover.NET with NAnt and CruiseControl.NET
I can run PartCover.NET browser without problems, but it does not work once I try to run it in an NAnt task (in my CCNET build).
There must be an issue with my NAnt target but I can't find it. Maybe someone had experienced the same issues in the past?.
<target name="CoverageUnitTest" description="Code coverage of unit tests">
<exec program="${PartCover.exe}">
<arg value="--target=${NUnit.console}" />
<arg value="--target-work-dir=${project.dir}\bin\${configuration}"/>
<arg value="--target-args=${project}.dll" />
<arg value="--output=C:\partcover.xml" />
<arg value="--include=[*]*" />
</exec>
</target>
In CruiseControl, I got the following error message:
[exec] Invalid option '--target C:\NUnit\bin\nunit-console.exe'
Build Error: NAnt.Core.BuildException
External Program Failed: C:\PartCover\PartCover.exe (return code was -1)
in C:\default.build line: 20 col: 4
at NAnt.Core.Tasks.ExternalProgramBase.ExecuteTask()
at NAnt.Core.Tasks.ExecTask.ExecuteTask()
at NAnt.Core.Task.Execute()
at NAnt.Core.Target.Execute()
at NAnt.Core.Project.Execute(String targetName, Boolean forceDependencies)
at NAnt.Core.Project.Execute()
at NAnt.Core.Project.Run()
thanks !
David
As You may have noticed this task is rather complicated. It drove me to the edge of insanity but at last I got it running.
Here is some general advice:
use PartCover version 2.2 instead of 2.3 since the latter is a dev version that seems to be unstable.
remember to register PartCover.CorDriver.dll.
passing arguments is the hardest part if You need to quote paths. I finally decided to use a configuration file and pass it via --settings.
Replace = with space and use the &quot ; marker around the parameters for the arguments

Resources