A screenshot of the Library.Template github template repo.

It is amazing what the .NET SDK can enable you to build with so little code. But very soon you need to add a cloud build pipeline for CI builds and to validate PRs. You’ll want unit tests, and then you’ll want code coverage, and dumps when those tests hang or crash. You’ll need to figure out versioning. You may want to maintain a consistent coding style. Oh, and don’t forget analyzers to help guide you in the way of best practices and avoid common bugs.

Both as a software engineer at Microsoft and an avid OSS developer, I get a lot of experience setting up repos and pipelines. There are so many lessons to learn about what works well, and how to design the setup so that it will work both today and tomorrow when a new SDK comes out that would otherwise break your build. Microsoft has fairly uncommon requirements that include servicing some software for up to 10 years, so it’s vital that our repos are set up with as many external dependencies as possible pinned down so that we can reproduce the same build long after those dependencies are deprecated.

As I learn those lessons, I found I had to apply them to many repos. Each repo was more or less out-of-date with respect to certain patterns, and it was difficult to keep track of them all. I eventually decided to start a new repo that was for nothing but tracking all the best practices of repos where I could record all my ideas. But it became more than just a reference repo. It literally serves as a template for many new repos. I even developed a process by which existing repos can adopt its history into an existing repo’s history so that a simple git merge can update another repo as these patterns evolve.

The repo is itself OSS and I encourage you to take a look: AArnott/Library.Template: A template for a NuGet package with tests, stylecop, fxcop, versioning, and Azure Pipelines build ready to go. (github.com)

Your first reaction may be that the repo is surprisingly large for being just a starter without any code in it. The README in the repo explains some of the features and reasoning behind some of these files in more detail than I go into with this post. Every file and line in that repo has come from (sometimes painful) lessons learned in many other repos. Generally, I only add functionality to this repo when it is a common requirement for several other repos.

I hope you find it useful.