Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors when building or running tests when PackageReference version is set in .targets file #4698

Closed
alejandro5042 opened this issue Apr 4, 2019 · 3 comments

Comments

@alejandro5042
Copy link

alejandro5042 commented Apr 4, 2019

Visual Studio Version: 16.0.0 Preview 5.0

Summary

Errors when building or running tests when we attempt to set the PackageReference Version metadata in a .targets file.

 System.ArgumentException: '' is not a valid version string.
   at NuGet.Versioning.VersionRange.Parse(String value, Boolean allowFloating)
   [...]

Why are we doing this? To centralize the nuget version for dozens of nugets in a 400+ project solution. We want the version to be blank in the csproj file and update it in a Directory.Build.targets file.

Steps to Reproduce

Setup:

  • Create an xUnit .NET Framework test project
  • Remove the Version metadata from a PackageReference
  • Update the Version metadata from a Directory.Build.targets file

Then:

  • Build --> Error when building begins
  • Test --> Error during test run

Example

UnitTestProject1.csproj:

  <ItemGroup>
    <PackageReference Include="xunit" />
    <PackageReference Include="xunit.runner.visualstudio">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

Directory.Build.targets:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <PackageReference Update="xunit" GlobalVersion="2.4.1" />
    <PackageReference Update="xunit.runner.visualstudio" GlobalVersion="2.4.1" />
  </ItemGroup>
  
<!--
    For any NuGet for which we want to centrally manage and update the version being used across projects, we do not specify the actual version in the .csproj file. Instead, there should be one or more files like above that add a GlobalVersion definition for each NuGet to be managed that way.

    This target "UpdateKnownPackageReferenceVersions" ensures that for each NuGet for which a GlobalVersion is defined, that any .csproj PackageReference for that NuGet does not define its own version. If this target detects that the version is defined in the .csproj file, then a build error is generated.

    Inspiration derived from: https://github.com/NuGet/Home/wiki/Centrally-managing-NuGet-packages-and-versions
  -->
  <Target Name="UpdateKnownPackageReferenceVersions" BeforeTargets="Build">
    <Error
      Text="Remove Version metadata from PackageReference '%(PackageReference.Identity)'. This version is set globally in '$(MSBuildThisFileFullPath)'. Refer to that file for more details."
      Condition="'%(PackageReference.GlobalVersion)' != '' and '%(PackageReference.Version)' != ''" />
    <ItemGroup>
      <PackageReference Condition="'%(PackageReference.GlobalVersion)' != ''" Version="%(PackageReference.GlobalVersion)" />
    </ItemGroup>
  </Target>
</Project>

Sample Project

I've completed these steps in this attached simplified solution. Simply run the one UnitTestProject1.UnitTest1.TestMethod2 test.

Expected Behavior

No errors.

Actual Behavior

Errors on build and on test discovery:

[4/4/2019 5:20:26 PM Informational] ------ Discover test started ------
[4/4/2019 5:20:26 PM Informational] [xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit Desktop .NET 4.0.30319.42000)
[4/4/2019 5:20:27 PM Informational] [xUnit.net 00:00:00.75]   Discovering: UnitTestProject1
[4/4/2019 5:20:27 PM Informational] [xUnit.net 00:00:00.86]   Discovered:  UnitTestProject1
[4/4/2019 5:20:27 PM Error] System.ArgumentException: '' is not a valid version string.
   at NuGet.Versioning.VersionRange.Parse(String value, Boolean allowFloating)
   at NuGet.PackageManagement.VisualStudio.VsManagedLanguagesProjectSystemServices.ToPackageLibraryDependency(PackageReference reference)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NuGet.PackageManagement.VisualStudio.VsManagedLanguagesProjectSystemServices.<GetPackageReferencesAsync>d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.<GetPackageSpecAsync>d__29.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.<GetPackageSpecsAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NuGet.VisualStudio.VsPackageInstallerServices.<GetPackagesPathResolverAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NuGet.VisualStudio.VsPackageInstallerServices.<>c__DisplayClass7_0.<<GetInstalledPackages>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Threading.JoinableTask.CompleteOnCurrentThread()
   at Microsoft.VisualStudio.Threading.JoinableTask`1.CompleteOnCurrentThread()
   at Microsoft.VisualStudio.Threading.JoinableTaskFactory.Run[T](Func`1 asyncMethod, JoinableTaskCreationOptions creationOptions)
   at NuGet.VisualStudio.VsPackageInstallerServices.GetInstalledPackages()
   at Microsoft.VisualStudio.TestWindow.VsAdapters.UnitTestExtensionDiscoverer.GetAllEnabledExtensions(ILogger log)
[4/4/2019 5:20:28 PM Informational] ========== Discover test finished: 1 found (0:00:01.6550075) ==========
[4/4/2019 5:20:37 PM Informational] ------ Run test started ------
[4/4/2019 5:20:38 PM Informational] [xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit Desktop .NET 4.0.30319.42000)
[4/4/2019 5:20:38 PM Informational] [xUnit.net 00:00:00.72]   Starting:    UnitTestProject1
[4/4/2019 5:20:39 PM Informational] [xUnit.net 00:00:01.08]   Finished:    UnitTestProject1
[4/4/2019 5:20:39 PM Informational] ========== Run test finished: 1 run (0:00:01.6330125) ==========
[4/4/2019 5:22:16 PM Informational] ------ Discover test started ------
[4/4/2019 5:22:17 PM Informational] [xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit Desktop .NET 4.0.30319.42000)
[4/4/2019 5:22:17 PM Informational] [xUnit.net 00:00:00.69]   Discovering: UnitTestProject1
[4/4/2019 5:22:17 PM Informational] [xUnit.net 00:00:00.81]   Discovered:  UnitTestProject1
[4/4/2019 5:22:18 PM Error] System.ArgumentException: '' is not a valid version string.
   at NuGet.Versioning.VersionRange.Parse(String value, Boolean allowFloating)
   at NuGet.PackageManagement.VisualStudio.VsManagedLanguagesProjectSystemServices.ToPackageLibraryDependency(PackageReference reference)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NuGet.PackageManagement.VisualStudio.VsManagedLanguagesProjectSystemServices.<GetPackageReferencesAsync>d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.<GetPackageSpecAsync>d__29.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.<GetPackageSpecsAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NuGet.VisualStudio.VsPackageInstallerServices.<GetPackagesPathResolverAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NuGet.VisualStudio.VsPackageInstallerServices.<>c__DisplayClass7_0.<<GetInstalledPackages>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.Threading.JoinableTask.CompleteOnCurrentThread()
   at Microsoft.VisualStudio.Threading.JoinableTask`1.CompleteOnCurrentThread()
   at Microsoft.VisualStudio.Threading.JoinableTaskFactory.Run[T](Func`1 asyncMethod, JoinableTaskCreationOptions creationOptions)
   at NuGet.VisualStudio.VsPackageInstallerServices.GetInstalledPackages()
   at Microsoft.VisualStudio.TestWindow.VsAdapters.UnitTestExtensionDiscoverer.GetAllEnabledExtensions(ILogger log)
[4/4/2019 5:22:18 PM Informational] ========== Discover test finished: 1 found (0:00:01.6210112) ==========
[4/4/2019 5:22:20 PM Informational] ------ Run test started ------
[4/4/2019 5:22:21 PM Informational] [xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit Desktop .NET 4.0.30319.42000)
[4/4/2019 5:22:22 PM Informational] [xUnit.net 00:00:00.71]   Starting:    UnitTestProject1
[4/4/2019 5:22:22 PM Informational] [xUnit.net 00:00:01.09]   Finished:    UnitTestProject1
[4/4/2019 5:22:22 PM Informational] ========== Run test finished: 1 run (0:00:01.6570069) ==========

User Impact

Build and tests still complete but errors show up in logs.

Workaround

Setting the version to * gets us around the issue, but doesn't seem right.

Possibly Related Issues

@dmondrik
Copy link

dmondrik commented Apr 5, 2019

It turns out there is further impact. In VS 2019 when you right-click "Migrate package.config to PackageReference" it fails the operation. It gets as far as removing the old references, but then shows the same failing call stack in the 'Package Manager' output window:

System.ArgumentException: '' is not a valid version string.
at NuGet.Versioning.VersionRange.Parse(String value, Boolean allowFloating)
at NuGet.PackageManagement.VisualStudio.VsManagedLanguagesProjectSystemServices.ToPackageLibraryDependency(PackageReference reference)

At this point the operation terminates without any error. Inspecting the .csproj file shows the old references gone but without any PackageReference elements at all.

The workaround is to unload all other projects (at least all those that are dependencies that have been converted) and then do the migration. That does succeed.

@davkean
Copy link
Member

davkean commented Apr 18, 2019

What you are trying to do would work with the new SDK-based project system, assuming you changed BeforeTargets from Build to CollectPackageReferences. This however, will not work in traditional .NET Framework projects. It only ever reads PackageReference during evaluation and does not run targets to collect them, so your code that sets the version of the PackageReference never gets run.

For that project system, you'll need to do something similar to https://github.com/davkean/maket, where the Update is added during evaluation. I'm not sure the benefit of the GlobalVersion metadata item? Is that so that you can verify that its not set in project file?

@davkean
Copy link
Member

davkean commented Jun 28, 2019

Closing this. We do not have intentions on extending the support any further in the legacy project system, all of our investments are in the new project system, of which this already works.

@davkean davkean closed this as completed Jun 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants