3
votes

Need advise on the following:

In my company I am developing .NET class libraries to be used by external stakeholders, and I am sharing them on a private NuGet feed to which the stakeholders have access.

The libraries are dependent on one core library as shown below. Currently I'm maintaining these libraries in a single VS solution, obviously into one Git repo. I'm following SemVer to version them.

CoreLibrary
CoreLibrary.Extension1 (references CoreLibrary as project reference)
CoreLibrary.Extension2 (references CoreLibrary as project reference)
...
There might be more of these extension libraries in the near future

Up until now I have always manually versioned them from within Visual Studio (manually setting the correct values in AssemblyInfo.cs whenever I need to bump a version) and used a batch file in each project to pack and push that specific library to NuGet.

But now I recently started looking into VSTS and my next undertaking is to automate builds and releases as much as possible, also with automatic versioning. I stumbled upon GitVersion which I think can help greatly with that last part.

But, here's the but. If I understand correctly, GitVersion operates at the repository level, so a given semver version calculated by GitVersion applies to ALL assemblies/libraries in a repository, right ?

So what are your suggestions for release and versioning strategies for these libraries ?

1) Keep everything like now in one solution and repo and whenever there is a change in one package that needs to be published (say CoreLibrary.Extension1), this generates a NuGet package for all other libraries too. So if all packages are on 1.0.0 and there is one small change in one of them, they all get bumped to v1.1.0 and all get packed and pushed ?

2) Create a git repo per project and let GitVersion work its magic on each repo separately. Reference the CoreLibrary via NuGet in the Extension libraries.

Option 2 is the cleanest I think and has the advantage that versioning and packaging is handled per project, but might be quite an overkill on the workload in terms of maintaining them, especially given the fact that I am the sole developer of these libraries.

What are your thoughts ? Which option would you opt for given the context ? Have I missed any other options that might be worth considering ?

Setting my first steps in automated builds and release so any advise is more than welcome.

Thanks

2
I think you understand well the problematic. And you should choose the solution depending on what seems the more important for you. If that's not overkill, I will choose 2). But seeing your description, I think it should be so I will choose 1) (and even with all the assemblies in the same nuget package) - Philippe
I went for option 1 for the time being and if the need arises I will reconsider option 2. Thanks for the suggestion. - tjeuten

2 Answers

3
votes

You must consider at least these two factors:

  1. Effort required to maintain multiple repo's/branches and release streams.
  2. Potential effort demanded of your customers when you make minor or major changes to just one or a small fraction of the libraries.

When a project is small and there's only one developer working on it, it's often easier to work entirely from within a single repository and cut a single package for all releases. Even for a single developer however, this will not scale well with the number of libraries. For one thing, VS is not particularly good at handling large projects, though it does continue to improve on this front, over time. Even so, there's a practical limit, but a single developer is unlikely to be productive enough to reach that limit in less than a few years.

Eventually, even a single developer, generally hopes to be successful enough to have a need for scale, either on the development side, or supporting customers. Consider the effect of being half-way through some major work on your extension2 when an important customer discovers a bug in extension1. Now you need to check-out an earlier commit, produce a quick fix, cut a new package, test, rinse/repeat, publish, return to the head of your repo, cherry-pick the bug fix, and continue. Had you been working in separate repo's or even branches in the same repo, the task is much easier to organize and get it right on the first try.

Now here's where I have a bone to pick regarding your assumption that you need separate repo's per Nuget package, or that GitVersion "operates at the repository level". Generally, most of the documentation and nearly all of the examples you'll find, definitely cater to the single product/package/repo format, and I'd probably recommend that in most cases, but it's not in fact a hard requirement. GitVersion functions at the branch level, and you should definitely be doing development for different libraries in different branches, if not different repo's. Having a master branch to merge everything, is probably also a good idea, but even master isn't required by Git or GitVersion. You can have multiple VS solutions and projects in a single git repo and you can produce multiple nuget packages therefrom. I am not saying you should, I am saying it is not an uncommon practice, at least for non-trivial product lines.

On the customer front, it really depends a lot on the nature of your products. Are all extensions necessary or even useful to every customer? Will you produce alpha/beta releases to early adopters? Is your code used on servers? Is it used on mobile devices? Generally, you don't want long upgrade times for any code that is run on servers, so you should think seriously about breaking up your product line into multiple, independently versioned packages. Client side has not been as critical in this areas in the past, but on mobile devices, download times become a major factor. Not everybody has unlimited free download bandwidth to work with either, so cost can be a major factor.

If you're going to produce a lot of prereleases, you'll probably want to break the product line out into separate packages. You can still produce the one package of packages, but you'll need the option eventually, to send out updates at the module level.

Once you go down the one repo/project/package/release-stream trail, you'll quickly develop the automation you need to help maintain it. It's like clean coding practices, a little painful when you first get started, but it eventually becomes second nature and the pay-off down the line can be enormous. Keep in mind that there isn't any reason why you can't have multiple repo's with their own solutions and projects and also have a VS solution at the parent directory one level above those, that gives you a fully integrated build. Just think of it as a hierarchy of build systems. You'll just need to learn how to use your .gitignore file or git sub-modules (I prefer the former, as the tooling for the later is weak).

-6
votes

I would strongly suggest against using any nuget package here. Nuget was intended as a way to manage third-party dependencies of a software project, not as a way to manage your interconnected code you build on a regular basis. For that, you'd do better to have a single repository, one visual studio solution and a single build stack you build/deploy from.

If you must use Nuget, just make a single package with a single version.