Ensuring best practices for NuGet packages
Creating a NuGet package is as easy as dotnet pack
. But, you may not be aware of all the best practices that you should follow to ensure your package is as good as it can be. In this post, I describe how to ensure your NuGet packages follow best practices before publishing them to a repository such as nuget.org.
#Discoverability
You should make your package discoverable by adding the right metadata to your package. It will help users to find your packages from the search in NuGet.org or Visual Studio.
- Choose a unique package id (doc)
- If you plan to publish your package to nuget.org, choose a NuGet package id with a prefix that meets NuGet's prefix reservation criteria
- If the package is not intended for public distribution, choose a package id that is not already taken on nuget.org
- Include a short description, up to 4000 characters, to describe your package (doc)
- Include several tags related to your package to help the search algorithm find your packages (doc)
- Include an icon with your package (doc). The icon is displayed on nuget.org and in the NuGet Package Manager in Visual Studio.
- If some users use an older version of NuGet, you can set
icon
and the deprecatediconUrl
in your nuspec file to increase compatibility.
- If some users use an older version of NuGet, you can set
- Include a README file (markdown format) that provides an overview of what your package does and how to get started (doc). This file is displayed on nuget.org.
- Include a license file or a license expression (doc)
#Binaries
Most packages contain binary files (dll or exe).
- Build the binary files using the
Release
configuration - For libraries, include the xml documentation files in the package
- If you multi-target the library, make sure the same public types and methods are accessible through all compatible targets. For instance, a package that multi-targets for .NET 6 and .NET Standard 2.0 needs to ensure that code compiled against the .NET Standard 2.0 binary can run against the .NET 6 binary.
#Confidence
People want to be sure the package contains the advertised DLLs. If the project is open-source, you can check the source code, but how can you be sure the package is built with the sources you see?
- For open-source projects, include the repository URL and the commit in the package metadata (doc)
- Compile the package using deterministic builds, so people can reproduce the same binary from the source code. See enabling reproducible builds when building NuGet packages for more info.
- If you want to go further, you can sign your package to prove the identity of the author
#Debuggability
Consumers should be able to debug the code of the package if something doesn't work as expected.
- Include symbols (PDB) for your binaries
- Use
<DebugType>embedded</DebugType>
, include the PDbs in the package, or use a symbol package (snupkg)
- Use
- PDB should use the portable format to be compatible with all platforms. The file is also smaller than the Windows PDB format.
#Tools to validate NuGet packages
The SDK provides a tool to validate NuGet packages right after creating them. At the moment, it provides the following checks:
- Validates that there are no breaking changes across versions
- Validates that the package has the same set of public APIs for all the different runtime-specific implementations
- Helps developers catch any applicability holes
To enable it, you can add the following property to your project file:
<Project>
<PropertyGroup>
<EnablePackageValidation>true</EnablePackageValidation>
<!-- Optional: Detect breaking changes from a previous stable version -->
<PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion>
</PropertyGroup>
</Project>
Another tool to validate a NuGet package is NuGet Package Explorer. The UI tool shows you the package content and validates the package symbols are ok. This works on local packages and published packages. A CLI tool also exists to validate packages. You can add this tool to your CI pipeline to validate the packages before publishing them.
dotnet tool update --global dotnet-validate --version 0.0.1-preview.304
dotnet validate package local "mypackage.1.0.0.nupkg"
I also made a tool to validate the content of a package. It validates package metadata and symbols. It reports errors on the console using a JSON format. Also, it returns a non-zero code when a package is not valid. The source code is available on GitHub.
dotnet tool update --global Meziantou.Framework.NuGetPackageValidation.Tool
meziantou.validate-nuget-package "mypackage.1.0.0.nupkg"
#Additional resources
Do you have a question or a suggestion about this post? Contact me!