From the course: .NET Deep Dive: NuGet Package Manager
Package versioning - NuGet Tutorial
From the course: .NET Deep Dive: NuGet Package Manager
Package versioning
- [Instructor] Packages follow a standardized versioning scheme. Let's learn more about it. A specific package is always referred to by its package identifier and an exact version number. This unique combination makes it possible to always get the exact package you need for a project. When creating a package, you assign the project ID and a precise version number. Each subsequent release of the package has the original package ID, but a new version number. When consuming a package on the other hand, you can specify either a precise version number or range of acceptable versions. When creating a package, the version information can be gleaned from the project files. For simple packages, the information can gleaned from the .csproj, .vbproj, or .fsproj files. For more control over what is placed in a package, a .nuspec file can be used. Most packages have dependencies on other packages. The publisher indicates the acceptable version range for each dependency. We'll look at dependency resolution in more detail later in the course. It's one of the trickiest problems to solve in package managers. NuGet, like many package managers, prefer semantic versioning which describes a release in terms of its backwards compatibility with the last release. Basically, semantic versioning provides a signal from the publisher to the consumer on how risky and update is. Or saying it another way, how likely will updating to a higher version break your application. A specific NuGet version is in the form of Major.Minor.Patch. In this example, 3.1.4. or another alternative is Major.Minor.Patch-suffix. In this case, 4.2/.5-prerelease. Before digging into the details, let's explore semantic versioning, also known as SemVer, and why it's useful for package managers. The different digits that comprise a SemVer version number, each have a meaning, which is where the semantic designation comes from. The major number is the leftmost. Package publishers release major versions when the new release will absolutely break something in the application code, unless the developer changes the code to accommodate the changes. So incrementing this number means a breaking change. The minor number is in the center. Incrementing this number indicates new features are included in the package, but there are no breaking changes. The new features add functionality in a backwards compatible way, which means that the added features don't require users of the previous version to change their code. Patch is the rightmost number. A patch version is a release with a backwards compatible bug fix. For example, a new security fix for an exploit found after the package was published. There are no new features and no breaking changes. Categorizing releases by risk allows the consumer to understand when it is safe to update a package. We can make rules around this knowledge. For example, we might have a policy to automatically update any package with a higher patch number, because we assume that we want any bug fixes available. A package with a suffix is considered a prerelease package. Packages without a suffix are considered stable releases. Suffixes are optional. They are useful for indicating an experimental, a beta, or a preview version of the package. Here's an example from one of the Microsoft packages. If you look at the top line, the version number is 2.2.0-preview1-35029. If you look at the bottom of the list, there is another version that's 2.1.0-preview2-final. The takeaway? Suffixes signify a prerelease, but the publisher can choose a suffix name that fits their naming conventions. In most cases, the first time you add a package to a project, you'll choose the precise version you need. There are more considerations when a package update appears in the gallery. We can always review the release notes and update the package manually if we consider it a prudent choice, or we can ignore it and keep the original version. This is where the semantic versioning is useful. If it's a patch, then it's probably wise to update. If it's a major release, then we should evaluate the breaking changes before proceeding. If it's a patch or a minor update, it might be safe to automate the updates. Automation in NuGet can take many forms, so there are various mechanisms to apply the updates and specify what rules apply for automated updates. This gets more complicated with dependencies. What happens when there is a patch in a dependency package, but no changes in the main package? Patches are bug fixes, so it seems reasonable that we would want to update them as they appear. This is one of the main features and pain points of package managers. When it works, automating this process is invaluable. However, packages with lots of nested dependencies are more complex. We should talk about how dependencies work in NuGet. Before we do that. here's a summary of what we've learned so far. Every package has a package ID. In most cases, this is synonymous to the package name. Then every release of that package gets a version number. It's a good practice to use semantic version numbers for this, but it's not a strict requirement. When consuming a package, you can choose an exact version number, or you can specify a range of acceptable numbers.
Contents
-
-
-
-
-
-
Package versioning5m 55s
-
(Locked)
Package dependencies5m 9s
-
(Locked)
Enable Package Restore in Visual Studio47s
-
(Locked)
Edit version number in PackageReference5m 2s
-
(Locked)
How Package Restore installs packages42s
-
(Locked)
Run Package Restore manually1m 46s
-
ASP.NET and client-side package managers3m 59s
-
-
-
-
-
-
-
-