My way of working with internal nuget packages
Tags: powershell, packaging, internalnugetpacka, dotnet
Published: 2018-11-26 15:48:29

---
title: My way of working with internal nuget packages
published: true
tags: powershell,packaging,internal-nuget-packa,dotnet
canonical_url: https://hackernoon.com/my-way-of-working-with-internal-nuget-packages-a30d3f71d47d
---

![](https://cdn-images-1.medium.com/max/1024/1*A4sh2W_Gt5OWFg3HHzwXPw.png)<figcaption>Picture borrowed from <a href="https://cdn.pixabay.com/photo/2013/07/13/10/22/box-157074_1280.png">https://cdn.pixabay.com/photo/2013/07/13/10/22/box-157074_1280.png</a></figcaption>

The company I’m working at is big enough to span over multiple development teams. To be able to share a common way of working and to prevent that the wheel is invented over and over we rely on shared [nuget](https://docs.microsoft.com/en-us/nuget/what-is-nuget) packages.

I am author of many packages and the main contributor of those and that requires me to spend some time maintaining them. To be able to do this I need a working method that enables me to do this efficiently.

In this post I’m going to share my way of doing this, step by step.

#### Version control

To version control the packages [git](https://git-scm.com/) is used. Git is a _de facto standard_ and need no further description :)

#### Naming

Decide on a good naming convention that will work for you. We use a prefix with our company separated by points narrowing down. For instance: CompanyA.AspNetCore.Mvc would be our own package with custom classes for ASP.NET Core MVC.

#### Project structure

To stay consistent a project structure should be used. I base mine on this [Gist](https://gist.github.com/davidfowl/ed7564297c61fe9ab814) by David Fowler. It is not strictly followed, but rather inspired by. For example, the test project is not separated into its own test folder, instead it is included in the src folder. This setup is done once, when I introduce additional packages I just copy the structure from another project. This structure could easily be extracted into a [dotnet template](https://docs.microsoft.com/en-us/dotnet/core/tools/custom-templates).

**Nuspec file**

Follow [this](https://docs.microsoft.com/en-us/nuget/reference/nuspec)reference by adding your nuspec file.

**Tests**

Make sure you cover your packages with unit tests. That will give you confidence that your code works as you expect it to work and will also help other contributors. I’m using [xUnit](https://xunit.github.io/) and in some projects [AutoFixture](https://github.com/AutoFixture/AutoFixture) to maximize maintainability and reduce code in the Arrange phase.

**Documentation**

Add a README.md to the project that explains how to use the package. More on the README.md below in the section about _Crafting the package_. I am considering looking into [Read the Docs](https://readthedocs.org/) as a complement.

#### How to introduce changes?

The workflow that is used is [Git Flow](https://nvie.com/posts/a-successful-git-branching-model/) which means that we do not directly push changes to the master branch, but rather to feature branches that we integrate against the develop branch. I am not going to go into detail about Git Flow here.

When a feature is done, a pull request is opened and stakeholders are invited. And hopefully the feature is merged back to develop and ready for the next upcoming release. The git tag should reflect the version to be released. I explain my process of doing this in the section _Crafting the package._

**Breaking changes or not?**

So, what is a breaking change?

> A change in one part of a [software](https://en.wiktionary.org/wiki/software) system that potentially causes other components to [fail](https://en.wiktionary.org/wiki/fail); occurs most often in shared libraries of code used by multiple applications — [Wikipedia](https://en.wiktionary.org/wiki/breaking_change)

If you alter the definition of an existing method that you are exposing to the consumer or remove properties from an object that is a breaking change. Please make sure you have a consuming test client targeting your packages so that you can verify that the changes you’ve made are correctly done.

When it’s time to update an already existing package you need to take your consumers into consideration. You need to ask yourself if it’s a breaking change or not that you are introducing. If it isn’t, then it’s fine. That change should then only alter the minor and/or patch version.

If you are about to introduce a breaking change you need to keep support for the deprecated feature at least one version before removing it. I tend to do it this way

1. Add the new feature
2. Deprecate the old feature by adding an [ObsoleteAttribute](https://docs.microsoft.com/en-us/dotnet/api/system.obsoleteattribute.message?view=netcore-2.1) and describe how the consumer should migrate.
3. Bump the minor version and release a new version

In the next major release, remove the obsoleted feature. In this way the consumer is given some time to migrate their existing code to use the new version.

#### Crafting the package

Before publishing a new package I make sure that

1. The dependencies in the nuspec file is updated and that the supported target frameworks are in place
2. The README.md is updated with new functionality and examples
3. Versioning is correct

**Dependencies in nuspec**

There is a section in the nuspec file manifest that enabled to specify the [dependencies](https://docs.microsoft.com/en-us/nuget/reference/nuspec#dependencies) that the package has. Even if packages only support one target framework they are included in a [dependency group](https://docs.microsoft.com/en-us/nuget/reference/nuspec#dependency-groups). That makes it easy in the future to add additional target frameworks.

**Updating the README.md**

To make sure that I update the README.md so that it is easy to follow I use [Markdown Live Preview](https://markdownlivepreview.com/) when editing it. That gives me a visual editor on how the file will be displayed. I then copy the content into my README.md and commit it.

**Versioning the package**

I’m using [semantic versioning](https://semver.org/). To version the package the numbers must be consistent in \*.csproj, .nuspec and in the git repository. For this I’m utilizing custom made PowerShell scripts.

{% gist https://gist.github.com/nengberg/839ed5593360c434d41949265b37b709 %}

This is executed by running it from the src folder.

.\bump-assembly-version.ps1 -Version 0.0.1

{% gist https://gist.github.com/nengberg/c4e7c1726ce6f4f4bfdfa969c8169683 %}

This is excuted by running it from the src folder.

.\bump-nuspec-version-ps1 -Version 0.0.1

I then commit those changes

git commit -am "Incremented project version"

Before pushing anything I make sure that my repository is tagged with the same version so that we have a tag that corresponds to the release

git tag -a 0.0.1 -m "Release 0.0.1"

_(All of the above could easily be built into one single script file. I still do it separately but might consolidate in the future :))_

And then push the tag

git push origin 0.0.1

And the code

git push

#### Publishing the package

There are different ways you can do this. Either locally using the nuget CLI to push the package to your feed, or let your CI service do this work.

I am letting [Azure DevOps](https://azure.microsoft.com/nb-no/services/devops/) and Azure Pipelines do this. The build process consist of standard .NET build / run tests tasks. If you are interested in how that might look you can find examples [here](https://github.com/MicrosoftDocs/pipelines-dotnet-core).

Finally the nuget package is crafted based on the nuspec file. The package is then pushed to our internal nuget feed. For this to work seamless a service connection to our nuget feed is added in Azure DevOps. The package manager that is used is [ProGet](https://inedo.com/proget).

When this package published I usually notify all the developers on Slack that new packages are available and take any further discussions from there.

This is a process that is working for me. If you have any opinions or other ways of doing this I’d like to hear. What features should be extracted into nuget packages really depends on your company and how you share code between team. I prefer to have a consistent way of doing things and I’ve noticed that we save a lot of time in our projects if we can reuse good things that others already have built.

If you liked the post, you know what to do! 👏

* * *