Best Practices for Authoring Private NuGet Packages in the Enterprise
by Eric Seng, on Oct 6, 2021 3:17:00 AM
Microsoft's NuGet package authoring best practices is a fantastic resource for learning how to create free, open-source packages that you will publish to nuget.org. However, a lot of the advice doesn't translate very well to private packages that you will publish to a private NuGet server like ProGet.
In this article, we'll share best practices for authoring private NuGet Packages.
Create a NuGet Package in the Enterprise
While Microsoft has a pretty good step-by-step tutorial on how to create and publish a NuGet package with Visual Studio, the publishing steps are for nuget.org, and it doesn’t give any guidance for how to manage your project once it’s created.
In general, your NuGet project should follow the same conventions that other projects at your organization use.
- Single Project. This generally means having its own source code (git) repository and issue tracker… even if it’s a small library.
- Wiki Page. A wiki page will be especially important, even if it’s just a readme file inside your repository. This will help other developers use the library, and allow them to build-upon the documentation you start. At a minimum, it should have a brief description of the library, how to use/maintain the project, and have links to the issue tracker. Later on, as you make major new versions of the package, you can add upgrade notes to the wiki page.
- CI/CD Automation. Especially with tools like BuildMaster, it’s easy to create a CI/CD Pipeline for NuGet from the start so that even 1.0.0 is delivered as consistently as others.
Package Metadata in the Enterprise
Metadata is an important aspect of all NuGet packages. Standardizing which properties to use (and how) is important: the wrong metadata can lead to problems like confusion and wasted time for developers, or even deploying the wrong package to production.
You can set package metadata in Visual Studio (Project > [Project Name] Properties > Package), or directly in the project file. These will be added to the .nuspec file once the package is created.
Our general advice for Package Metadata in the enterprise is to keep it simple, and use only as few fields as necessary. Unlike many package authors on nuget.org, you're not trying to "sell" people on using your package, or win a popularity contest with the most downloads.
Package ID: Use company name
The NuGet package name is stored in the package's manifest file, which is stored within the package zip file itself. You can't just rename the file if you want to change the package name. It's like trying to change the title page of a PDF document by renaming the file - the contents of the file and the file name have no relation.
Microsoft has some good advice for writing unique package identifiers:
- Search existing feeds before choosing a name to ensure uniqueness
- Use namespace-like names using dot notation and not hyphens
- If you have a sample, be explicit with a “.Sample” suffix
You’re likely already using namespace-like names in .NET; that’s great – continue to do that with your NuGet packages. But unlike libraries in your applications, these packages should be unique across the entire organization and any expansion for years to come.
Start with the company name (“Kramerica”) to avoid conflict with public packages. Be sure to register your company’s name on nuget.org so you’re protected from dependency confusion attacks.
Next, consider standardizing with a division or business name after the company name (“Kramerica.Warehouse” vs. “Kramerica.Offshore”).
Keeping standards are incredibly important since packages are immutable. They cannot be renamed, changed, or edited so standardize, standardize, standardize.
You must create a new package with the same internal contents in order to "rename" a package. You’ll then have two packages: the "new" name one, and the "old" name one. And deleting those "old" packages is a bad idea because applications may be referencing that package.
Package Version: Use SemVer w/ Prerelease Labels
Our recent blog post about best practices for versioning NuGet packages goes into detail about proper versioning.
In a nutshell: Semantic Version (Version 2.0.0) using PreRelease tags is a must. You should always create a package with a pre-release tag, and then repackage later. The Prerelease tag signifies that the library within the package is untested, and shouldn’t be deployed to production.
Authors: only use Company name
Author is a required field, but it should be considered optional for private use in the Enterprise. Set one name as the author to keep with standard; either the company name or a team name (“Kramerica” or “Kramerica.DevOps”)
Description: use Internal Wiki
The Microsoft best practices come up short on description – ironic since we consider a short description key. The character limit is 4000, but it’s completely unnecessary to write that much. Use the description to link to the company Wiki page so you can maintain the most up to date information.
Be concise; reuse copy from the Wiki if necessary (likely to be pre-approved and reliable). NuGet Packages cannot be edited or update, so hyperlinking to internal documentation is best.
Repository: use Source Link
A Source Control Repository gives traceability to a NuGet package. There are four fields; type, url, branch, and commit. Source Link will automatically add repositoryURL and RepositoryType to the package metadata, saving time.
This property is complex, requiring a CI/CD pipeline for your NuGet packages.
Icon: Optional, quick visual cue
An Icon can be useful for quickly differentiating a NuGet package from others in a private repository on Visual studio. If you have an appropriate icon file feel free to include it, but it’s not necessary.
Note: “iconURL” is deprecated so use “icon”
Package Metadata Properties to Avoid
✗Copyright: Ignore, not needed
Your packages will be private or published on a private repository, so they don't need a copyright. If a project document doesn't need "(C) Kramerica" on them, neither does a private NuGet package.
✗Licensing: Ignore, not needed
Similar to Copyright, your packages will be private and therefore don't need a license file, licenseURL, or requiredLicenseAcceptance.
✗Project URL: Ignore, link to Internal Wiki
Following these guides, you will already include a link to the Wiki’s project page in the description, making this field redundant. If you think this field should be filled, use the same project page link in the description.
✗Tags: Ignore, worse than free-text search
Tags are a bad replacement for private use without a standardized system, especially compared to free-text searches. Creating tags and then maintaining their standards will also occupy a lot of time unnecessarily.
✗Release Notes: Ignore, redundant to Wiki
The Wiki’s project page should also link to issue trackers, give upgrade guidance, and other show release notes, making this field redundant to description.
In Visual Studio, some UI sections may display release notes instead of the description which can cause confusion, so it’s best to leave this field blank and rely on the description to do the heavy lifting.
✗Title: Ignore, not needed with ID
The title field is not shown in Visual Studio or on nuget.org. Generally, it’s not used for display purposes, so just use ID and leave this field blank.
✗ Summary: Ignore, redundant to description
The summary field is deprecated and shouldn't be used, plus it's redundant to description anyway. It has been replaced by title, but as seen above it’s not needed either. Leave this field blank.
✗Readme: Ignore, not needed with Wiki
Readmes are not where developers typically go for documentation. Guides for using a NuGet package should be included in the Wiki anyway, so a readme will be redundant. By sure to hyperlink to internal, up-to-date documentation that would be considered readme worthy.
Standardizing Metadata Usage
Standardizing your usage of NuGet metadata will ultimately help everyone stay organized.
Keeping property usage to a minimum will make it easier for developers to create and contribute, while avoiding headaches down the line.