-
Notifications
You must be signed in to change notification settings - Fork 258
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
design spec for version property in project reference #12348
base: dev
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# Allow users to define version ranges for ProjectReferences | ||
|
||
- [Martin Ruiz](https://github.com/martinrrm) | ||
- Start Date (2023-01-01) | ||
- [5556](https://github.com/NuGet/Home/issues/5556) | ||
|
||
# Summary | ||
|
||
Add a `Version` to `ProjectReference` tag in CSPROJ, to allow customers to specify the referenced project version in the `.nupkg` and `nuspec` files when doing a pack command. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about adding another As you can see in the below example, <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ClassLibrary2" Version="[1.0.0, 2.0.0)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ClassLibrary2\ClassLibrary2.csproj" />
</ItemGroup>
</Project> I didn't think about the pros/cons or possibilities of this approach. |
||
|
||
# Motivation | ||
|
||
When using `ProjectReference` there is no option to define a Version to the reference like in `PackageReference` and the version will always be defined as `>= ProjectVersion`, this results in customers manually modifying the nuspec file if they want to declare a different version than the project version. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you be able to add little bit more details on exactly what is the project version here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For project version I mean the value of About For example if ProjectA has a |
||
|
||
# Explanation | ||
|
||
Currently when adding a `ProjectReference` to a project, there is no property to specify which version(s) of it to be used when doing a pack. | ||
When doing a pack to a package with a `ProjectRefernce` it will always be added as a range, where the minumum version will be the ProjectReference version and with an open maximum version. | ||
martinrrm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
``` | ||
<ItemGroup> | ||
<ProjectReference Include="../MyReferencedPackage/MyReferencedPackage.csproj" /> | ||
</ItemGroup> | ||
``` | ||
|
||
Add a `Version` property to `ProjectReference` and store that value in the assets file when doing a restore so we can retrieve that information when doing a `pack command. | ||
|
||
If there is no `Version` information then the behavior should be the current one. | ||
|
||
## Example | ||
|
||
### .CSPROJ file | ||
``` | ||
<ItemGroup> | ||
<PackageReference Include="Newtonsoft.Json" Version="[9.0.0, 13.0.2)" /> | ||
<ProjectReference Include="../MyReferencedPackage/MyReferencedPackage.csproj" Version="[1.0.0, 2.0.0)" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the minimum version should not be allowed to be specified on the ProjectReference, and NuGet should always automatically fill in the min version from the project's version. This might not be popular with customers who want this feature, but this is for the protection of package consumers, especially since NuGet only selected minimum version in its dependency resolution graph. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With this I think we can take the customer suggestion and do something like this:
With this in mind, you think saving this as a version range in the assets file (like the initial proposal) or change it to be different properties? Option 1 (I like this one more) :
Option 2:
I currently have an mvp for this in branch There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently I forgot to reply to this 😕
That's not valid MSBuild syntax. While project files are XML, MSBuild has a strict syntax, and diverging from it will require changes to MSBuild if we feel stongly enough that it's needed to support a customer scenario (in which case you'd also need to consider what potential bugs it could introduce to non-NuGet scenarios if the syntax was extended). Anyway, MSBuild items are basically NuGet's However, I think another scenario that some customers may want, is to limit the package dependency to the exact version of the project when it's being packed. VersionRange defines this as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @zivkan I like the idea of doing
What if we do something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per our docs on version ranges,
Yes, that works with MSBuild's syntax. Something to keep in mind, although it's very unlikely, is that customers might have build custom build scripts, so if any customer already uses Customers are more likely to already be familiar with All this to say, I don't have an obvious answer/solution. Get more feedback from others. Perhaps my
How? What would the syntax be for "use the referenced project's version as the max" be? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. magic word maybe?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Today, the I don't love it though. It feels like the most completely way without misuse risk, but it's kind of ugly. |
||
</ItemGroup> | ||
``` | ||
|
||
### assets file | ||
``` | ||
"frameworks": { | ||
"net6.0": { | ||
"targetAlias": "net6.0", | ||
"projectReferences": { | ||
"C:\\Users\\mruizmares\\source\\repos\\ConsoleApp1\\MyReferencedPackage\\MyReferencedPackage.csproj": { | ||
"projectPath": "C:\\Users\\mruizmares\\source\\repos\\ConsoleApp1\\MyReferencedPackage\\MyReferencedPackage.csproj", | ||
"version": "[1.0.0, 2.0.0)" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this change be compatible with old version tools? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tested doing a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My guess is that because it's additive it should work. |
||
} | ||
} | ||
} | ||
}, | ||
``` | ||
|
||
### nuspec file | ||
``` | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"> | ||
<metadata> | ||
<id>ConsoleApp1</id> | ||
<version>1.2.4</version> | ||
<authors>ConsoleApp1</authors> | ||
<description>Package Description</description> | ||
<dependencies> | ||
<group targetFramework="net6.0"> | ||
<dependency id="MyReferencedPackage" version="[1.0.0, 2.0.0)" exclude="Build,Analyzers" /> | ||
<dependency id="Newtonsoft.Json" version="[9.0.0, 13.0.2)" exclude="Build,Analyzers" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May I know if there is any behavior change for package reference? Or will this change only impact project reference? Thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now, we consider ProjectReferences as packages when doing pack, so this code is shared. Since PackageReference's can handle ranges, I think the behavior is going to be the same. Currently we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to switch from legacy short string to short string? |
||
</group> | ||
</dependencies> | ||
</metadata> | ||
<files> | ||
<file src="C:\Users\mruizmares\source\repos\ConsoleApp1\ConsoleApp1\bin\Debug\net6.0\ConsoleApp1.runtimeconfig.json" target="lib\net6.0\ConsoleApp1.runtimeconfig.json" /> | ||
<file src="C:\Users\mruizmares\source\repos\ConsoleApp1\ConsoleApp1\bin\Debug\net6.0\ConsoleApp1.dll" target="lib\net6.0\ConsoleApp1.dll" /> | ||
</files> | ||
</package> | ||
``` | ||
|
||
### nupkg | ||
``` | ||
Metadata: | ||
id: ConsoleApp1 | ||
version: 1.2.4 | ||
authors: ConsoleApp1 | ||
description: Package Description | ||
Dependencies: | ||
net6.0: | ||
MyReferencedPackage: '>= 1.0.0 && < 2.0.0' | ||
Newtonsoft.Json: '>= 9.0.0 && < 13.0.2' | ||
|
||
Contents: | ||
- File: _rels/.rels | ||
- File: [Content_Types].xml | ||
- File: ConsoleApp1.nuspec | ||
- File: lib/net6.0/ConsoleApp1.dll | ||
- File: lib/net6.0/ConsoleApp1.runtimeconfig.json | ||
- File: package/services/metadata/core-properties/a638a18cb3b1449185ce67e16a13ebaf.psmdcp | ||
``` | ||
|
||
# Drawbacks | ||
|
||
I don't think there are drawbacks to this implementation when doing a `pack` command. For restore I'm not sure if adding a new propert to the assets file can affect the performance. | ||
|
||
# Rationale and alternatives | ||
|
||
# Unresolved Questions | ||
|
||
# Future Possibilities |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason, I think
Version
attribute doesn't belong toProjectReference
because it refers to the package version range. Looking at the schema forProjectReference
element https://github.com/dotnet/msbuild/blob/main/src/MSBuild/MSBuild/Microsoft.Build.CommonTypes.xsd#L643-L722, I thinkPackageVersion
might be more appropriate. The schema hasPackage
as sub element forProjectReference
but there are no comments to understand more about its usage. I noticed that there is alsoSpecificVersion
attribute forProjectReference
element to specify whether the exact version of the assembly should be used.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI - There is an MSBuild property
PackageVersion
allowing customers to specify package version in the csproj file if the project is packed as nupkg.https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices#package-metadata