Express transitive dependency in MSBuild without Importing PackageReference - msbuild

I have a project MySdk.csproj that I'm packing at build time via dotnet pack. I want to express that this project has a transitive dependency on Trans.nupkg, but I don't actually want to import all the assets from Trans.nupkg during the build of MySdk.csproj. I DO want a consumer (call it Consumer.csproj) of MySdk.nupkg to get all the assets from Trans.nupkg.
If I ExcludeAssets for Trans.nupkg from MySdk.nupkg then the nuspec and nupkg for MySdk.nupkg reflects the exclusion and when Consumer.csproj references MySdk.nupkg it won't get the transitive assets.
Is there a way to accomplish this?
Thanks.
UPDATE:
If I try to set PrivateAssets to None and ExcludeAssets to build for Trans.nupkg reference from MySdk.csproj like this:
<PackageReference Include="Trans" Version="1.0.*" PrivateAssets="None" ExcludeAssets="build" />
the generated nuspec in MySdk.nupkg looks like this:
<dependency id="Trans" version="1.0.0" include="Runtime,Compile,Native,ContentFiles,Analyzers" />
which means that when Consumer.csproj adds a reference like this:
<PackageReference Include="MySdk" Version="1.0.0" />
the transitive reference back to Trans.nupkg won't include the custom build targets, which is the opposite of what I'm trying to accomplish.

While ExcludeAssets controls which assets the MySdk.csproj will consume, PrivateAssets specifies which assets will not flow across a transitive dependency.
The default for PrivateAssets is contentfiles;analyzers;build which is the reason that the Consumer.csproj will not get built-time assets (.pros/.targets files), roslyn analysers and content files by default.
To change, this reference the Trans package setting PrivateAssets to none which will make Consumer.csproj behave as if it directly referenced the Trans package (example also excluding build-time dependencies from the MySdk project):
<PackageReference Include="trans" PrivateAssets="none" ExcludeAssets="contentfiles;build" />
For more information see Controlling dependency assets.

Related

How to address (suspected) outdated external package dependencies?

We have a .Net Core 6.0 solution and two of the projects have NuGet package references set to Azure.Storage.Blobs 12.14.1 (the latest version at the time of writing):
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
</ItemGroup>
Today a new security scanning tool that IT are testing flagged up a "critical" issue:
System.Text.Encodings.Web Remote Code Execution (RCE) CVE-2021-26701
CVSS 9.8 Critical
Introduced through: project
› Azure.Storage.Blobs 12.14.1
› System.Text.Json 4.7.2
› System.Text.Encodings.Web 4.7.1
I looked at the nuget.org page for Azure.Storage.Blobs and it shows System.Text.Json (>= 4.7.2) which implied to me (perhaps wrongly) that Blobs should work just fine with later versions of Encodings.Web:
I'm only referencing Azure.Storage.Blobs, so does this mean that Azure.Storage.Blobs itself is referencing an out-of-date package?
I'm keen to avoid creating my own dependency on the nested packages when they're not directly used. My research showed that NPM has a way around these issues, but I've been unable to find a NuGet-based solution.
Can anyone please explain what the solution is to ensure that my dependencies are kept secure here?
Central package management offers a feature called transitive pinning to manage (the versions of) transitive/indirect dependencies, without making them direct dependencies.
From the documentation
Starting with NuGet 6.2, you can centrally manage your dependencies in your projects with the addition of a Directory.Packages.props file and an MSBuild property.
You can automatically override a transitive package version even without an explicit top-level by opting into a feature known as transitive pinning. This promotes a transitive dependency to a top-level dependency implicitly on your behalf when necessary.
First enable central package management.
Add a Directory.Packages.props file to e.g. the root of your repository (near your .sln file).
Set ManagePackageVersionsCentrally to true.
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
Include any direct NuGet packages using PackageVersion tags; notice the difference with PackageReference tags.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Azure.Storage.Blobs" Version="12.14.1" />
</ItemGroup>
</Project>
Adjust your .csproj file(s) by removing the version indication from any PackageReference tags since this will now be managed centrally, although you can still override if needed.
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" />
</ItemGroup>
</Project>
Next enable transitive pinning by setting ManagePackageVersionsCentrally to true.
Add below tag in a PropertyGroup.
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
Then include the concerning packages.
In your case you can e.g. upgrade and pin System.Text.Json or System.Text.Encodings.Web to a higher version, e.g.:
<PackageVersion Include="System.Text.Json" Version="6.0.7" />
You need to figure out which version applies for your concrete case.
Full Directory.Package.props example.
The transitive dependencies don't need to be in a separate ItemGroup, but it might be more insightful.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Azure.Storage.Blobs" Version="12.14.1" />
</ItemGroup>
<!-- Transitive packages -->
<ItemGroup>
<PackageVersion Include="System.Text.Json" Version="6.0.7" />
</ItemGroup>
</Project>

Can't figure out how to include the source code into the nuget package that gets generated

I have several projects in a solution that i want to be packaged to be used as libraries in other solutions. The goal is to make development and debugging seamless, as if it was all in the same solution.
Specifically, I want to be able to ctrl + click on something from the library and be able to view the original source code and not the decompiled code.
I am using PackageReference to include the libraries to the application. What I have noticed is that when I unzip either the nupkg or snupkg, there is no source files anywhere. On that note, I have searched all over the internet and found conflicting things about where the source files go in the nupkg. I have seen mentions of the following folders in the nupkg: lib, src, content, and contentFiles. Which one should actually contain the source code?
When I unzip the nupkg (or snupkg) the only things I have in it are _rels, lib, package, [Content_Types].xml, and PROJECTNAME.nuspec.
I see that the lib folder contains the dll and the pdb file but no source code.
Furthermore, I noticed that the snupkg file is considerably smaller than the nupkg file which I find to be counter intuitive.
I have tried packaging using
msbuild -t:pack
msbuild -t:pack -IncludeSource=true
nuget pack
nuget pack -IncludeSource=true
and also building with visual studio but to no avail.
Here is my vbproj file
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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>
<ProjectGuid>{C64FB67B-64D0-4607-AE35-A21888FE79A2}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>ROOTNAMESPACE_HERE</RootNamespace>
<AssemblyName>PACKAGE_NAME_HERE.ROOTNAMESPACE_HERE</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>Windows</MyType>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<Deterministic>true</Deterministic>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<TargetFrameworkProfile />
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<version>1.0.0</version>
<RepositoryType>git</RepositoryType>
<Authors>COMPANY_HERE</Authors>
<BuildInParallel>false</BuildInParallel>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<IncludeSource>true</IncludeSource>
<PackageId>PACKAGE_NAME_HERE.ROOTNAMESPACE_HERE</PackageId>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
...
...
...
<ItemGroup>
<PackageReference Include="NuGet.Build.Tasks.Pack" Version="6.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>
I have also tried using a nuspec file as well but still no success.
I am using .net framework 4.8
I have spent the last 3 days banging my head against the wall over this and haven't been able to figure it out. I have googling non-stop and have even been using ChatGPT to help me try and trouble shoot and no matter what I try I cant get it to work.
Any help would be greatly appreciated!
It sounds like you want to publish nuget packages with SourceLink activated.
SourceLink will add metadata to the packaged assemblies that contains hints about where the original code from which the package was build can be found, e. g. a GIT repository URL and the particular commit SHA. The Visual Studio Debugger during debugging will read the metadata and thus be able to download the source from the repository and show it to you.
This will be the original source like you wanted.
See the docs at https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/sourcelink.
What you have to do is add SourceLink as a package dependency to the project from which the package will be built.
For github and an SDK-style project it looks like this:
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
<!-- alternatively, using the new GlobalPackageReference element -->
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
Since you seem to be using the old project format, you may need to do it differently. Visual Studio will most likely do the right thing for you when adding the package through the package manager UI.
Note that this is a build-time dependency only and will not add any libraries.
SourceLink by default will only do its job when some MSBuild properties are set. More on that below.
This is a snippet I use (again, SDK-style) to have SourceLink active on every release build:
<PropertyGroup>
<!-- ugly workaround because MSBuild apparently cannot set a bool property from the result of an evaluated expression -->
<TreatAsOfficialBuild>false</TreatAsOfficialBuild>
<!-- Abuse "Release" config as trigger for SourceLink, because I don't want to type -p:ContinuousIntegrationBuild every time
This should work as long as we do not locally debug release builds from commits that have not been pushed to github yet -->
<TreatAsOfficialBuild Condition="'$(Configuration)' == 'Release'">true</TreatAsOfficialBuild>
<PublishRepositoryUrl>$(TreatAsOfficialBuild)</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<ContinuousIntegrationBuild>$(TreatAsOfficialBuild)</ContinuousIntegrationBuild>
<DeterministicSourcePaths>$(TreatAsOfficialBuild)</DeterministicSourcePaths>
</PropertyGroup>
For the debugger to be able to download the source, the package must have been built from a commit that is available on the remote repo.
I trust you already know that you may not be able to debug into that source with breakpoints if the build you are debugging is optimized like in a "Release" build.
If you want to be able to debug through every line of the package's original source, you would have to build that package without optimization (like in a "Debug" build). For SourceLink to be active on debug builds too, you would need to adapt the criteria for the TreatAsOfficialBuild property accordingly.

Treat ProjectReference as PackageReference or allow PackageReference to local csproj

I have a netstandard2.0 csproj (let's call it MyPackage) that is packed at build time (as specified by GeneratePackageOnBuild) into a nuget package. This nuget package has custom props and targets in the build directory (so referencing projects get these imported).
I have another project (let's call it MyConsumer) in the same solution for testing MyPackage. I want MyConsumer to have the build asset props and targets imported from MyPackage at build time, just as if it were consuming it as a PackageReference from some remote nuget source.
How can I get this working (most simply)?
I have been able to do it via a very convoluted method where I have MyConsumer add a PackageReference to MyPackage and override the RestoreSources in MyConsumer to point to the bin directory of MyPackage. This gets very weird when running dotnet build or Visual Studio build of the sln, because project metadata is generated upfront for all projects during Restore and thus MyPackage doesn't exist at that point. The resolution was to add nested calls to MSBuild within the MyConsumer project, but then this becomes even worse, since Visual Studio restores operate quite differently than that automatic restores performed by dotnet build.
Is there any simple way of doing this?
This is what I have now
<Project>
<Target Name="Build">
<Message Text="Running inner build" Importance="high" />
<!--
Need to call MSBuild twice, once to restore, then again to restore and build to get the restore of the Sdk to work
because of this bug in MSBuild: https://github.com/Microsoft/msbuild/issues/2455
Note the trailing Prop=1 is required to get MSBuild to invalid it's cache of the project target imports
-->
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Restore" Properties="Configuration=$(Configuration);Version=$(Version);IsInnerBuild=true;Prop=1" />
<!-- Have to use dotnet build instead of another call to MSBuild because of another bug that prevents proper imports within the same physical process -->
<Exec Command="dotnet build /p:Configuration=$(Configuration) /p:Version=$(Version) /p:IsInnerBuild=true" />
<Message Text="Finished inner build" Importance="high" />
</Target>
<Target Name="Restore" />
<Target Name="RemoveBin">
<RemoveDir Directories="bin" />
</Target>
<!-- Don't do real cleans old rebuild since it breaks MSBuild due to the same above bug -->
<Target Name="Rebuild" DependsOnTargets="RemoveBin;Build">
</Target>
</Project>
Treat ProjectReference as PackageReference or allow PackageReference to local csproj
If I understand you correct, you want to generate the package with project MyPackage, then install it to the test project MyConsumer and have the build asset props and targets imported from MyPackage at build time.
To accomplish this goal, you need to complete the following few things:
Make sure the project MyPackage build before the project MyConsumer.
Set the package into the packager source
Add the package MyPackage.nupkg to the test project MyConsumer during the build time.
Details for above:
Make sure the project MyPackage build before the project MyConsumer.
Since you wan to test the package which generated by the project MyConsumer, you should make sure this package grnerate before test project using it, so we need set the project MyConsumer reference the the project MyPackage.
Set the package into the packager source
You can use a post-build event for the project MyPackage to copy the package MyPackage.nupkg to the local feed, or you can just add the bin directory of MyPackage.nupkg to the package source.
Add the package MyPackage.nupkg to the test project MyConsumer during the build time.
Using VS 2017 and the PackageReference style of the test project MyConsumer, you can set a Directory.Build.props file into the root of your solution containing the test project MyConsumer you need:
<Project>
<ItemGroup>
<PackageReference Include="MyPackage" Version="1.0.* />
</ItemGroup>
</Project>
This will add these NuGet packages to the test project MyConsumer in the solution, it will be used as a PackageReference from some remote nuget source.
Check the Martin`s answer for some more details.
Hope this helps.

MSBuild nuget RestoreOutputPath how to make it work?

New msbuild csproj format have got integrated nuget commands. It's possible to change default path where project assets will be restored by using <RestoreOutputPath>obj\profile7</RestoreOutputPath> command in project file.
But if I add <RestoreOutputPath>obj\profile7</RestoreOutputPath> to csproj file consequent commands
dotnet restore myproj.sln
dotnet build myproj.sln
produce build errors
obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
How to tell MSBuild to get nuget assets from this obj\Profile7 path during the build command?
The restore output path needs to be the same as MSBuildProjectExtensionsPath so that the nuget generated props and targets files will be imported by the common props and targets. as well as BaseIntermediateOutputPath will be the default for composing the path to ProjectAssetsFile.
At least for the NuGet imports, it is important that MSBuildProjectExtensionsPath or BaseIntermediateOutputPath is set before the SDK props file is imported.
The simplest way to solve all of these issues is to set BaseIntermediateOutputPath very early in the project so that all components will take its value as a default base path - this is essentially redirecting obj to somewhere else.
This conflicts with the <Project SDK="..."> syntax since there is no way to set properties before the SDK's props file. To work around this, the project can be changed like this:
<Project>
<!-- This needs to be set before Sdk.props -->
<PropertyGroup>
<BaseIntermediateOutputPath>obj\SomeSubDir\</BaseIntermediateOutputPath>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<!-- other content -->
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>
An alternative would be to create a Directory.Build.props file that will be automatically imported early enough, but this would apply the value to all projects in the directory and take away the ability to specify the value per project.

MSBuild multiple dll in a single NuGet package

I have a Visual Studio 2017 solution that contains two projects:
Foo.csproj
Foo.Core.csproj
Both of these projects target multiple frameworks: net452;netstandard1.2
Foo.csproj includes a project reference to Foo.Core.csproj:
<ItemGroup>
<ProjectReference Include="..\Foo.Core\Foo.Core.csproj" />
</ItemGroup>
When I generate a NuGet package for Foo.csproj, I want the nupkg file to include both of these assemblies.
What is currently happening is that the NuGet package that gets created has Foo.dll and then a NuGet dependency on Foo.Core (which doesn't exist).
How can I generate a single NuGet package using msbuild that will include both assemblies?
For reference this is the command I am currently using (which is not working how I want it to):
msbuild /p:restore,pack Foo.csproj
This is currently not directly supported by NuGet out of the box. You can follow this GitHub issue for updates.
However, there are a few ways to create such NuGet package.
Use the "Nugetizer 3000"
This is an newly developed tool to build NuGet packages from projects and works by installing the NuGet.Build.Packaging nuget package. You can find some documentation on it on its GitHub wiki page but since it is a very new project, there isn't much documentation or community knowledge around it yet(!) (but the team developing it is very helpful, you could file GitHub issues if you get stuck).
Adding a custom target in the project (2.0.0 tooling / VS 2017 15.3+): Create an item in the csproj that will include the referenced project's output DLL
This approach is very hacky as it relies on an internal MSBuild item that the pack targets use. It works by first marking the <ProjectReference> to not be referenced from the created nuget package like this:
<ProjectReference Include="..\libA\libA.csproj" PrivateAssets="All"/>
Then you can add this to the project to include the generated libA.dll in the nuget package:
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeP2PAssets</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="IncludeP2PAssets">
<ItemGroup>
<BuildOutputInPackage Include="$(OutputPath)\testprivatelib.dll" />
</ItemGroup>
</Target>
Note that this requires you to add all the <PackageReference> items of the referenced project to the project you generate the package from since they would be missing from the generated package since you effectively disabled the transitive reference behaviour.
Create a custom .nuspec file
At the time of writing, this is probably the most "supported" way, but also the most complex. NuGet allows you to disable the automatic generation of the resulting .nuspec file and automatic collection of files by setting the <NuspecFile> property in your project, along with a <NuspecProperties> property that allows you to pass replacement tokens for parsing the .nuspec file.
This works by modifying the project file like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<NuspecFile>$(MSBuildThisFileDirectory)$(MSBuildProjectName).nuspec</NuspecFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LibB\LibB.csproj" />
</ItemGroup>
<Target Name="SetNuspecProperties" BeforeTargets="GenerateNuspec">
<PropertyGroup>
<NuspecProperties>$(NuspecProperties);id=$(AssemblyName)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);config=$(Configuration)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);version=$(PackageVersion)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);description=$(Description)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);authors=$(Authors)</NuspecProperties>
</PropertyGroup>
</Target>
</Project>
This will automatically look for a .nuspec file with the same name as the project (somelib.csproj => somelib.nuspec) and pass some properties along to it. The properties are created in a target in order to be able to access fully resolved and defaulted properties like PackageVersion.
The .nuspec file could look like this:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$authors$</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<dependencies>
<group targetFramework=".NETStandard1.4">
<dependency id="NETStandard.Library" version="1.6.1" exclude="Build,Analyzers" />
</group>
</dependencies>
</metadata>
<files>
<file src="bin\$config$\netstandard1.4\*.dll" target="lib\netstandard1.4\" />
</files>
</package>
Note that you must add all referenced NuGet packages as a <dependency> element in the .nuspec file since these are no longer automatically generated from the <PackageReference> items in your project file. Refer to the NuSpec Reference for more details.
I have recently created an example project on GitHub demonstrating the use of a custom .nuspec file for exactly this purpose.
The second option that Martin Ullrich mentioned is the only one that works out of the box with .NET Standard that allows to "Generate NuGet package on build" as an integral part of the build.
However like he mentions it has a "hard coded" dependency on a dll with an exact name that you expect to be there (on the output folder) which might bite you in the future. I've found a better alternative which worked for me in .NET Standard without the need of any other modification on this post.
I'll quote it here for completeness.
First you edit your csproj and define the PrivateAssets tag for the reference that you'd like to include:
<ItemGroup>
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
</ItemGroup>
Then you add this to your csproj:
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="#(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'all'))" />
</ItemGroup>
</Target>
That post also shows how to include the PDBs in the NuGet package option if necessary (which I omitted here).
Been struggling with the same issue and none of the suggested workarounds worked (https://github.com/NuGet/Home/issues/3891) and I couldn't change the csproj to use the new SDK coming with .netcore.
Luckily the nuget pack command comes with the -IncludeReferencedProjects option (ref: https://learn.microsoft.com/en-us/nuget/tools/cli-ref-pack) which does exactly that:
"Indicates that the built package should include referenced projects either as dependencies or as part of the package. If a referenced project has a corresponding .nuspec file that has the same name as the project, then that referenced project is added as a dependency. Otherwise, the referenced project is added as part of the package."
Regardless of the *.nuspec file (not needed here) , add -IncludeReferencedProjects to the pack command and the referenced project dlls will be included along with the nuget dll.
nuget.exe pack yourProject.csproj -IncludeReferencedProjects
I have recently discovered that you CANNOT set defaults for the Nuspec Properties you want to replace in the msbuild command line e.g. if a metadata value is set in the .csproj file of "<Version>2.0.0</Version>" and you run:
msbuild myproject.csproj -t:pack -p:Configuration=Release -p:NuspecProperties=Configuration=Release;PackageVersion=1.2.3
Your .nupgk file will have the version 2.0.0 still. Annoyingly the MS documentation is not clear on this and no error is displayed.