In Azure DevOps you can have your own private NuGet feed and I’m using that extensively. But sometimes authentication there is a pain.
This time I run into authentication issue while executing
dotnet publish for a probject that used that private feed:
Unable to load the service index for source https://mycompany.pkgs.visualstudio.com/DefaultCollection/_packaging/MyFeed/nuget/v3/index.json. [D:\a\1\s\src\MyProject.csproj]
error : Response status code does not indicate success: 401 (Unauthorized). [D:\a\1\s\src\MyProject.csproj]
The reason for that is that
dotnet publish does restore by itself, even though all the packages have been restored previously via
The solution for this is to do the obvious thing: don’t restore on publish vis
But that gave me more errors:
error NETSDK1047: Assets file 'D:\a\1\s\src\MyProject\obj\project.assets.json' doesn't have a target for '.NETCoreApp,Version=v2.0/win-x64'. Ensure that restore has run and that you have included 'netcoreapp2.0' in the TargetFrameworks for your project. You may also need to include 'win-x64' in your project's RuntimeIdentifiers.
Solution for that was to add
<RuntimeIdentifier>win-x64</RuntimeIdentifier> in my csproj file.
The overall process goes like this:
dotnet restore MyProject.csproj --configfile D:\a\1\Nuget\tempNuGet_2089.config --verbosity Detailed
tempNuget file is configured by Azure DevOps and contains the credentials for the private feed.
dotnet build MyProject.csproj
dotnet publish MyProject.csproj --configuration Release --output D:\a\1\a\MyProject -r win-x64 --no-restore
And my csproj file looks like this:
In the last couple years I’ve built a few libraries for public and internal consumption. Mostly these have been internal things, but they are not much different from OSS libraries.
So far the most popular libarary I’ve released open-sourced is Cake.SqlServer but I’m mostly proud of NSaga though it is not as used, mostly due to lack of marketing effort on my part. Both of these are still on v1.x though these are young libraries – both under 1 year of age at the moment of writing.
In a sense libraries for internal consumption are easier to build – you can break things and then fix the broken things in the downstream projects (or tell people how to fix). If your library is publicly released you need to be much more careful in how you handle breaking changes and how you define your public API surface. Semantic versioning is supposed to help you manage the breaking changes, but you still need to minimise the possibilities of breaking things for other people. If you are not careful and break a lot of stuff, people will be pissed off and eventually move away from your library.
While building OSS libraries I had to excersise a lot of care to cater for wider audience and rules I draw below are mostly coming from OSS. So here they are:
.Net Framework Versions
You need to consider what framework version you build for. Nature of .Net framework – every version is an increment on the previous, so library built for v4.5 will work in v4.6.1. But not the other way. So you need to pick the lowest version of .Net you’d like to work with and stick with it. I think it is fare to say that no currently developed project should be below v4.5. There is no reason to stay on lower version and upgrade from v3.5 is relatively painful. So my rule of thumb is to target v4.5 as a baseline, unless I need framework features that are only available in later versions.
Honestly, VSTS private NuGet feeds will be a most blogged topic in this blog! I’ve already mentioned them at least twice. Here goes another post:
This time I’m building in VSTS Core application and the build literally goes:
- dotnet restore
- dotnet build
- dotnet test
- dotnet publish
And this worked really well for the basic application – I had it set up in minutes and got the resuilt I was looking for.
But during the life of the application I needed NuGet packages from my private feed and
dotnet restore had no idea about my private feeds.
Even if supplied with
nuget.config file I was getting
401 Unauthenticated – this is because I was not keeping my password(token) in this file.
Solution was to add this feed globally on the agent for every build. And this turned out to be easier than I thought.
In your build add a new task called