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

[Feature]: Tool Packages should display differently than library packages #9015

Open
jzabroski opened this issue Feb 23, 2022 · 8 comments
Open
Assignees
Labels
feature-request Customer feature request
Milestone

Comments

@jzabroski
Copy link

jzabroski commented Feb 23, 2022

Related Problem

If you go to nuget.org/packages/Wyam , you will see the following informational messages :

  • Frameworks tab:

    There are no supported framework assets in this package.

    Learn more about Target Frameworks and .NET Standard.

  • Dependencies tab:

    This package has no dependencies.

Screenshot_20220223-070514_Samsung Internet

Screenshot_20220223-081717_Samsung Internet

The Elevator Pitch

Nuget.org is really confusing even to people with 20 years experience like me. This is one example that always confuses and confounds me.

Additional Context and Details

There are likely at least 3 types of Tool packages:

  • nuget v1 - v2.1 style packages us old timers used to use before .NET Global Tools came out
  • .netcoreapp2.1 tools
    • I believe these are referenced with the MSBuild Item DotNetCliToolReference . Attempting to install DotNetCliToolReference with local manifest json fails.
  • .netcoreapp3.0 tools
    • I believe these are created with <PackAsTool>true</PackAsTool>
@jzabroski jzabroski added the feature-request Customer feature request label Feb 23, 2022
@joelverhagen
Copy link
Member

Hey @jzabroski, thanks for the detailed bug report. I agree with your "tool taxonomy" 😃.

.netcoreapp3.0 / DotnetTool

For .netcoreapp3.0 tools, I assume you mean packages with the DotnetTool package type. These actually work by design in the Frameworks tab. You can find examples with our package type search:
https://www.nuget.org/packages?packagetype=dotnettool&sortby=relevance&q=&prerel=True

image

.netcoreapp2.1 / DotnetCliTool

For .netcoreapp2.1 tools, I assume you mean packages with the DotnetCliTool package type? I am not sure about the specifics of this tool type but from looking at examples (e.g. https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Tools.DotNet/) it appears that the Frameworks tab indeed shows no supported frameworks. I am not sure of the prevalence of this tool type (some GitHub issues on dotnet/sdk indicate that perhaps it is deprecated or at least fallen out of favor?) but I think we should either hide the tab (like we do for template packages) or add support similar to DotnetTool packages.

NuGet V1 tools a.k.a. the wild, wild west

The initial "tools v1" concept was very much ad hoc and had no concrete indicator that it was a tool specifically -- unless we made a guestimate like package has: stuff under tools dir + no other assets + no package type. Generally speaking, these are not packages that follow any well-defined schema (it might just be .exe files directly under tools directory) so I think it would be hard or at least someone error prone for us to show supported frameworks.

To give you a look at the top "tools v1" on NuGet.org, here are the latest versions of the top 10 packages on NuGet.org that have assets under tools but no other assets (no lib, no build, etc) and no package type (i.e. my best attempt at representing your tools v1 bucket):

Id Sample
NuGet.CommandLine tools/NuGet.exe
Microsoft.TestPlatform tools/net451/Common7/IDE/Extensions/TestPlatform/testhost.net472.exe.config
NUnit.Extension.NUnitV2ResultWriter tools/net20.engine.addins
NUnit.Extension.TeamCityEventListener tools/teamcity-event-listener.dll
NUnit.Extension.NUnitV2Driver tools/nunit.core.dll
NUnit.Extension.VSProjectLoader tools/vs-project-loader.dll
NUnit.Extension.NUnitProjectLoader tools/nunit-project-loader.dll
Microsoft.TestPlatform.Portable tools/net451/cs/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll
FAKE tools/FluentMigrator.Abstractions.resources.dll
NuGet.Build tools/NuGet.targets

As you can see, there is a mix of having framework directory and not. There's a mix of asset types. I am not sure if NuGet.org could make a useful guess about what frameworks, OS, or platform these tool packages support.

The Wyam package

Would it make sense to mark this package as DotnetTool? It would get the Frameworks tab support then. I don't know much about this package or why it has no package type on it. I do see Wyam.Tool which has the tab working well (at first glance):
https://www.nuget.org/packages/Wyam.Tool/

image

@jzabroski
Copy link
Author

jzabroski commented Feb 24, 2022

@joelverhagen Thanks for your thoughtful reply.

DotnetTool

Yes, this mostly works correct, I think. See discussion of DotNetCliTool at the bottom of next section for some food for thought on what is arguably still wrong with this, even though you can argue its outside the Nuget feifdom / castle walls.

DotnetCliTool

An example of a DotNetCliToolReference-compatible package would be Microsoft.DotNet.Xdt.Tools Version 2.0.0 (which Microsoft has basically abandoned despite many PRs to try to fix various bugs with it).

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.DotNet.Xdt.Tools" Version="2.0.0" />
  </ItemGroup>

I realize this is an edge case, but it's technical debt Microsoft created and should track and think about one day sunsetting. I believe this edge case for Microsoft.DotNet.Xdt.Tools is probably the same edge case as Wyam, but I am honestly not sure. However, if you view Wyam in Nuget Package Explorer, you will see its just got /tools/netcoreapp2.1 folder. But I can tell you the major change was from using the MSBuild element DotNetCliToolReference to DotNetToolReference. The exact reason for this change, I have no idea, to be honest. I do recall this thread: dotnet/sdk#3115

Note, subsequent versions of this source code lineage ended up moving to a new nuget package, dotnet-xdt, and that dotnet-xdt package supports modern tool references. - Although, on the dotnet side, it is a shame the dotnet-tools.json manifest doesn't track what runtime the command is supposed to run against.

DotNetTool & DotNetCliTool shared tree of woe

My understanding for why this shameful lack of metadata problem exists on the other side is that Microsoft felt dotnet CLI tools should not be used in production, and thus were intended for whatever SDK the developer was working with. Probably more information than you need to know for this ticket, but I think these "we aren't gonna need it" mistakes are common in building an MVP around some new .NET feature, and then we're stuck with it. Rather, food for thought: if Nuget had a better metadata structure, consumers could get this for free - that's what restful protocols like OData give clients - self-describing metadata that they can choose to use or ignore. It would also have prevented a lot of EntityFrameworkCore bugs where people installed earlier versions of the EFCore CLI tool, upgraded their SDK when the new major version of .NET Core / .NET 5 / .NET 6 came out, and suddenly they get data conflicts across which versions of an assembly the CLI tool uses and the SDK knows about to build their migration assemblies. From one sin, many have fallen. Hopefully, you take notice and don't repeat the generational sin. The people who left Microsoft after working for the "COM is love" and SOAP guy who built two failed communication technologies, well, they learned REST deeply and never looked back.

wild wild west

Yes, although the wild wild west is still existing in parts of the world. For example, Octopus Deploy, which we use for continuous deployment, requires that packages follow the wild wild west format. Nuget.org itself probably doesn't have many of these types of packages, since they're really just fancy zip files that are transferred via the nuget protocol and have to therefore follow the nuget version numbering scheme. Other than that fancy protocol stuff, they're zip files.

Another example is MSBuild Tasks nuget packages. For example, FluentMigrator.MSBuild for the project I maintain.

Another , more recent, wild west scenario is packing net48 Websites while using the new NET SDK csproj format, since they dont have a FrameworkReference, etc. You typically need to create a custom nuspec or it wont package correctly.

Another wild west scenario is anything where you're using non-standard SDKs, like the NoTargeting SDK. I use the NoTargeting SDK for things like addressing the issue where Nuget wont let you pack projectreference transitively, and that also requires a custom nuspec to fix-up the contents so it's clear where stuff should get written to for unpacking later.

Another example is nuget packages that are "fat binaries", where there are no dependencies because the nuget package is treated as an artifact for upload to an artifact server that uses the nuget.org tools & protocol to persist build artifacts. Since it's a build artifact, the idea is that by flattening all dependencies and putting all dlls in a single nupkg, you avoid questions about repeated retrieval of the file contents, e.g., if you re-deploy a version of a "artifact package" to a new server, it should be identical to the previous server. I am pretty sure this is the same example as Octopus Deploy, but figured I would list it as its own use case..

If Octopus Deploy is the cowboy approach to packages, then Elmah is the Indian approach to packages - they invented this country :)

https://nuget.info/packages/elmah/1.2.2 - if you look here, this old package has web.config.transform file under /content/ folder that actually told nuget to apply the transform file to the web.config files. The actual elmah dll is shipped in a dependency package, ironically, so that policy + mechanism were kept separate. This one package used to be the top package on nuget.org 14 years ago, because it made it easy for programmers who understand nothing about package management or software configuration management or application logging frameworks to add logging to their applications.

I think that pretty much covers it all, but, since you asked:

The Wyam package

Would it make sense to mark this package as DotnetTool?

I'm not 100% sure I understand the question. I think you meant DotnetCliTool going by the taxonomy we're using, and that is a totally forgivable typo given the weird vocabulary :) In which case, yeah, I think it probably makes sense to say if the only folder is this stuff, its a DotnetTool. In other words, tools that were killed by dotnet/sdk#3115 - I think these require special treatment, because you can't just run dotnet tool install wyam w/ ,NET >5 SDK, as it will fail with an error message.

@jzabroski

This comment was marked as outdated.

@joelverhagen

This comment was marked as outdated.

@jzabroski
Copy link
Author

@joelverhagen I added a new issue for SDK packages. So, this is sort of another category of Tools - Tool Frameworks - that I did not consider in the above. But I felt it was a separate issue and likely has dependencies on other teams.

The lack of good nuget metadata really makes your job suck some days. Hopefully you can get buy in from teams at Microsoft to not just do whatever the heck they please, or at least write aggressive package validation rules that block people from hacking stuff left and right.

@jzabroski
Copy link
Author

@joelverhagen See also #9085

I don't understand why all these edge cases occur?

@joelverhagen
Copy link
Member

@joelverhagen Joel Verhagen FTE See also #9085

I don't understand why all these edge cases occur?

Generally speaking, the Frameworks tab is built for Dependency packages and for DotnetTool packages. Dependency packages are assumed to be Dependency packages if they have no package type. This assumption is necessary for backwards compatibility but causes a world of problems for these "edge case" packages like the AsyncFixer package you mentioned.

Up until this point, we have not used the folder structure as a hint to what type of package it is. We only use package type for this purpose. Ideally, I'd like to keep it that way since any heuristics on folder structure would undoubtedly have their own edge cases.

@jzabroski
Copy link
Author

Ideally, I'd like to keep it that way since any heuristics on folder structure would undoubtedly have their own edge cases.

Unfortunately, you are probably right, especially given there are Nuget MSBuild variables that allow mucking with directory paths. I was actually thinking the right solution is to reify the relative paths into the metadata structure. It's honestly not something I care to explain, but, for example, you can specify <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> in a csproj and provide a custom nuspec file that overrides the default pack metadata. There is a few bugs related to the fact Nuget itself doesn't have any clue what these packages are or the consuming tools dont know what to do on restore when the paths aren't as expected.

@keylime-unicorn keylime-unicorn added this to the Backlog milestone Aug 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Customer feature request
Projects
None yet
Development

No branches or pull requests

5 participants