sdk icon indicating copy to clipboard operation
sdk copied to clipboard

The dotnet pack doesn't work together with -p:NuspecProperties when multiple properties provided

Open kordys opened this issue 5 years ago • 18 comments

When calling the

dotnet pack project.csproj -p:NuspecFile=project.nuspec -p:NuspecProperties="version=11.0.0;year=2021" --verbosity quiet --output c:/temp

command to pack a NuGet package providing multiple properties (version, year), only the first one is replaced in nuspec file with the provided value. Others are resolved as an empty string.

project.csproj file image

project.nuspec file image

nuspec file in resulted package image

Is there anything I am missing or there might be a bug in passing the properties?

Thanks.

kordys avatar Jan 25 '21 13:01 kordys

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost avatar Jan 25 '21 13:01 ghost

I can repro this on 5.0 and 6.0. @Forgind this isn't valid syntax, is it?

sfoslund avatar Jan 28 '21 21:01 sfoslund

MSBuild would interpret the command line to mean that the property NuspecProperties should have the value version=11.0.0;year=2021, but it doesn't do any more parsing initially, so there's presumably some parsing afterwards that converts it to real nuspec properties.

Have you tried reversing the order of the parameters (year=2021;version=11.0.0)? Version is given a default value if one isn't found, whereas year isn't. That might mean it was looking for version, and year would have to be set separately. Also, I'd try splitting version=11.0.0;year=2021 into two properties initially and seeing if you can pass them separately.

Forgind avatar Jan 28 '21 22:01 Forgind

When I reverse the order it's the same behavior - only the first parameter is replaced - the year in this case. SPlitting the properties this way:

dotnet pack project.csproj -p:NuspecFile=project.nuspec -p:NuspecProperties="version=11.0.0" -p:NuspecProperties="year=2021" --verbosity quiet --output c:/temp

doesn't help either. Unfortunately, the second argument value overrides the first one, so in this case, only the 'year' is replaced (Actually the pack fails because the version is empty since it is not replaced with the correct value).

So sadly nothing from the provided workarounds work.

kordys avatar Jan 29 '21 12:01 kordys

This sounds to me like a problem with the parsing where it knows to look for the NuspecProperties property, and it uses that to generate metadata later used to replace properties in the project.nuspec file, but the parser looks for the first = and doesn't parse the second part. @nkolev92, does that sound right? I suspected something in NuspecCoreReaderBase, but I couldn't find a smoking gun.

Forgind avatar Feb 03 '21 18:02 Forgind

Actually the problem is simpler than that :) dotnet pack is really just a wrapper around dotnet msbuild /t:pack.

NuspecProperties is a property, similar like the SpecialProperty example:

If you try this project:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <SpecialProperty>Set_In_Csproj</SpecialProperty>
  </PropertyGroup>

  <Target Name="SpecialTarget">
    <Message Text="Special property: $(SpecialProperty)" Importance="High" />
  </Target>
</Project>

And the output is:

C:\Users\Roki2\Code\packTest> dotnet msbuild /t:specialtarget                                                                                                                                                                                Microsoft (R) Build Engine version 16.9.0-preview-20611-06+5abf1ff7b for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Special property: Set_In_Csproj
C:\Users\Roki2\Code\packTest> dotnet msbuild /t:specialtarget /p:SpecialProperty="value"                                                                                                                                                     Microsoft (R) Build Engine version 16.9.0-preview-20611-06+5abf1ff7b for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Special property: value
C:\Users\Roki2\Code\packTest> dotnet msbuild /t:specialtarget /p:SpecialProperty="value" /p:SpecialProperty="value2"                                                                                                                         Microsoft (R) Build Engine version 16.9.0-preview-20611-06+5abf1ff7b for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Special property: value2
C:\Users\Roki2\Code\packTest>  

nkolev92 avatar Feb 03 '21 23:02 nkolev92

I completely misread the scenario. Let me take another look. I saw this comment https://github.com/dotnet/sdk/issues/15482#issuecomment-769773870 and complete focused on that.

nkolev92 avatar Feb 03 '21 23:02 nkolev92

Does it work if you specify the property in the project?

This can probably be transferred NuGet side if that doesn't fix it.

nkolev92 avatar Feb 04 '21 00:02 nkolev92

It looks like this approach works as you described.

The thing is I followed the documentation here: https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#packing-using-a-nuspec.

Where there is this statement: NuspecProperties: a semicolon-separated list of key=value pairs. Due to the way MSBuild command-line parsing works, multiple properties must be specified as follows: -p:NuspecProperties="key1=value1;key2=value2".

And since the values of the properties are in my case dynamically populated (evaluated as part of the build pipeline), I wanted them to be provided as dotnet pack arguments.

For now, I use plain string replace to provide the values to the nuspec file as a workaround.

Hopefully, it makes sense.

kordys avatar Feb 09 '21 17:02 kordys

We are running into exactly the same issue. This issue prevents us from using dotnet pack for packaging based on .nusepc files. It is a bit disappointing that this does not work as advertised on the posted link:

The thing is I followed the documentation here: https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#packing-using-a-nuspec.

Are there any plans to address this issue?

hvdbrand avatar Jun 07 '21 10:06 hvdbrand

So I decided to try using a .nuspec file to work around this issue, https://github.com/NuGet/Home/issues/3891 , and I ran into this issue of not being able to pass multiple key/value pairs to -p:NuspecProperties. It is especially frustrating because the docs continue to say that this is supported. Are there any plans to fix this?

CmTheLuke avatar Jul 26 '21 22:07 CmTheLuke

Just ran into this as well -- any plans to fix? If not, I may take a stab at opening a PR to fix this up.

Cpcrook avatar Nov 09 '21 19:11 Cpcrook

I also ran into the issue (.NET 6) but found a nice way that works. According to https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#pack-target many nuspec settings have now corresponding MSBuild properties and one can pass them directly via dotnet pack ... -p:PackageVersion=11.0.0 -p:RepositoryType=git. This may not work for all nuspec settings but it was enough for my use case.

crystalgreen avatar Jul 07 '22 10:07 crystalgreen

Facing the same issue. Cannot pass multiple parameters to NuspecProperties

-p:NuspecProperties="version=5.0.3;configuration=Release"

returns

"C:\Program Files\dotnet\sdk\6.0.303\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets(221,5): error : An error occured while trying to parse the value '5.0. 3;configuration=Release' of property 'version' in the manifest file."

s-krawczyk avatar Sep 12 '22 23:09 s-krawczyk

There are several levels to this problem.

  1. There's a bug in the SDK's CLI parsing when you pass the command dotnet build -p:NuspecProperties="a=1;b=2". The resulting command line is un-parsing the property's second value to a standalone MSBuild property: C:\Program Files\dotnet\sdk\7.0.101\MSBuild.dll --property:NuspecProperties=a=1 --property:b=2
  2. If you (reasonably) circumvent this by treating the property as a string, escaping the semicolon with %3B (which is the documented way of ensuring special characters round-trip on the MSBuild command line), then MSBuild interprets dotnet build -p:NuspecProperties="a=1%3Bb=2" as a single string, instead of breaking into separate values for the backing string[] Task parameter: image
  3. This is a known problem, and other places in the various targets add .Split('%3B') to the property use in their targets to handle just this scenario (see this target as an example).

Therefore, I think to finally solve this we should:

  • Add the Split to the NuGet targets' PackTask NugetProperties usage
  • Investigate why the CLI property parser is splitting this property up (unexpectedly?), though I fear this may have implications for other use cases we've run across already

baronfel avatar Dec 23 '22 22:12 baronfel

cc : @baronfel The solution that works for me is to use either update the .csproj or create a dynamic Directory.Build.props file (good for pipeline builds) and then add the nuspec properties NuspecFile , NuspecProperties there

<Project> <PropertyGroup> ....... <NuspecFile>app.nuspec</NuspecFile><NuspecProperties>version=$(PackageVersion);dateToday=$(dateToday);releaseName=$(releaseName)</NuspecProperties> </PropertyGroup> </Project>

app.nuspec file <version>$version$</version> ....... <description> ReleaseName :$releaseName$ date : $dateToday$ </description>

Then pass multiple parameters to csproj using below command:- dotnet pack "...\abcd.csproj" /p:PackageVersion=%version% /p:dateToday=%date:~10,4%%date:~4,2%%date:~4,2% /p:releaseName=%releaseName%

In this way I can use multiple Nuspec properties, however still not able to use it from the argument -p:NuspecProperties=.. when using dotnet pack command

BisNexus avatar Dec 24 '22 00:12 BisNexus

I still get this issue in .NET:

.NET SDK: Version: 8.0.204 Commit: c338c7548c Workload version: 8.0.200-manifests.7d36c14f

garfbradaz avatar May 17 '24 15:05 garfbradaz

I still get this issue in .NET:

.NET SDK: Version: 8.0.204 Commit: c338c7548c Workload version: 8.0.200-manifests.7d36c14f

I also struggeled with this problem in latest net8, but multiple properties are possible using this "style" in the project file (net sdk):

<PropertyGroup>
  <NuspecFile>my.nuspec</NuspecFile>
  <NuspecProperties>$(NuspecProperties);configuration=$(Configuration)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);version=$(Version)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);id=$(PackageId)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);author=$(Author)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);PackageProjectUrl=$(PackageProjectUrl)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);Description=$(Description)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);PackageReleaseNotes=$(PackageReleaseNotes)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);Copyright=$(Copyright)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);PackageTags=$(PackageTags)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);RepositoryType=$(RepositoryType)</NuspecProperties>
  <NuspecProperties>$(NuspecProperties);RepositoryUrl=$(RepositoryUrl)</NuspecProperties>
</PropertyGroup>

skeller1 avatar Oct 17 '24 09:10 skeller1