Are Best Practices Ruining Your CI/CD NuGet Pipelines?


Crista Perlton

Crista Perlton


Do I really need to leave .NET Framework for .NET 8? 13th September, 2023

Demystifying Microsoft .NET Long Term Support (LTS) in 2024 30th August, 2023


Are Best Practices Ruining Your CI/CD NuGet Pipelines?

Posted on .

No. Not for the reasons you think.

Obviously, keeping with NuGet best practices (authoringversioning, vulnerability scanningand so on) is best for your organization. It helps set and keep standards and allows a team to scale up quickly.

So why does following CI/CD best practices create a CI/CD loop when applied to NuGet packages?

NuGet with CI creates multiple packages to deal with, a lot more library changes, more CI builds, and more difficulty keeping track of all the version numbers that are coming from CI. Trying to apply an application pipeline to NuGet will never work since NuGet packages are unusable until publishing.

This article will quickly touch on some NuGet best practices that get in the way of the CI/CD pipeline.

Packages are Immutable

We’ve mentioned it on our blogs many times, and in a couple of our tutorials toopackages are immutable. Once they are published, a package file cannot be modified. You cannot edit the version number, or change its status, or make any changes because the package is Read Only – e.g. immutable.

Likewise, much of the data you’d want to change, version number or otherwise, is embedded into the package’s metadata file (the .nuspec file).

Breaking the immutability rule (for example, by downloading and overwriting packages) will cause chaos in your private repository. You’ll need to respect immutability to implement a successful CI/CD pipeline.

Untested code shouldn’t be deployed

Instead of renaming a package, why not rebuild a package with the same components?

This line of thinking will cause trouble down the line. Rebuilding a NuGet package can produce different software due to wildcard version dependencies. Regardless of your confidence in an “identical” rebuilt package, you need to test the code you’ve built before you can deploy it.

Drifting from this best practice could unintentionally introduce vulnerabilities to your applications. For a successful CI/CD pipeline, you’ll need a method to create a new package from an existing package, using completely identical contents while changing the version number and tracking the change.

Only deploy stable packages

We hope this best practice is clear: it doesn’t make sense to deploy prerelease packages to a production environment. Only stable versions should ever be released with your application.

You may have tried to make a pipeline by adding pre-release labels to the end of your package (e.g. -ci.1, -ci.2, ci.11). The package is then tested in the application and when it passes, is ready to be released to production.

Do not do this. Don’t use unstable versions of a package in your application – especially if you’re following CI/CD best practices. 

Again, you’ll need a way to push an existing pre-release package to a release candidate, to a stable release, all while tracking changes. 

What’s the solution to NuGet and CI/CD Pipelines?

In order to escape the “CI/CD Loop,” you need package immutability, Semantic Versioning, and Continuous Integration for your NuGet packages.

This is known as “repackaging.”

You can do it manually by downloading the package, opening it as a zip, and editing the .nuspec file. OR you can rely on a specialized tool, either within your pipeline like with BuildMaster or via a package server like ProGet.

Did you find this article helpful? Are you using NuGet to make your .NET packages? Learn how to optimize your NuGet in the Enterprise; sign up for our free NuGet guide:

Crista Perlton

Crista Perlton