How to create a NuGet package and publish it to NuGet.org

When you are writing code for your application, sometimes you encounter something that you’re using across multiple projects, or that may be valuable to other software developers you know. In .NET, the «right» way to share those things is by packaging an assembly for NuGet and uploading it to NuGet.org.

If you’re a good software engineer, and you probably are since you’re reading this, you also know the value of continuous integration (CI). MyGet provides a free solution for running builds against your codebase and makes it easy to deploy your NuGet packages to NuGet.org.

I was in need of a validation library that I could easily use in my domain project without polluting it with references to my persistence layer or ASP.NET. I took the opportunity to write Espalier.Validate and learn how to set up CI, complete with unit tests, for the project. If you want to dive into the current state of the code, visit the GitHub repository and jump in!

Technologies and services used to create a NuGet package and publish it to NuGet.org

GitHub

If you do not know what GitHub is, you should probably go hand in your software engineering badge, dust off your resume, and turn it in at McDonald’s. MyGet integrates nicely with GitHub, so I highly recommend using GitHub to host your code.

MyGet

MyGet provides convenient build services, solid integration with GitHub, and an easy way to push your NuGet packages to NuGet.org. Oh, and they do all that for free if your project is public.

NuGet.org

If you are a .NET developer, you know what NuGet is and why your packages need to end up there. Enough said.

.NET Core

Microsoft decided to throw away all their old code and build a cross-platform, decoupled, generally better version of .NET. They decided to call that .NET Core. All you need to know is that it’s dead easy to build libraries that target multiple framework versions using .NET Core.

Get your .NET Core project ready to build and create a NuGet package

Add NuGet packaging options to your project.json file

First, set the packOptions. Pack options tell the dotnet build tool what metadata to use when creating your NuGet package.

{
  "version": "1.0.3-*",

  "packOptions": {
    "description": "Validation attributes, fluent interface, and extensions to validate models and throw rich exceptions.",
    "authors": [ "Jereme Evans" ],
    "licenseUrl": "https://github.com/jeremeevans/Espalier.Validate/blob/master/LICENSE.md",
    "projectUrl": "https://github.com/jeremeevans/Espalier.Validate/",
    "tags": [ "validation" ],
    "requireLicenseAcceptance": false,
    "owners": [ "Jereme Evans" ]
  },...
}

Configure your target frameworks

Make sure your project.json has all the frameworks you want to target specified. If you don’t do this, adding the NuGet package will be inconsistent across various project types. Espalier.Validate currently has the following frameworks:

  "frameworks": {
    "netstandard1.6": {
      "imports": "dnxcore50"
    },
    "net45": {
      "frameworkAssemblies": {
      }
    },
    "net451": {
      "frameworkAssemblies": {
      }
    },
    "net452": {
      "frameworkAssemblies": {
      }
    },
    "net46": {
      "frameworkAssemblies": {
      }
    },
    "net461": {
      "frameworkAssemblies": {
      }
    }
  }

Add a build.bat to build your project and create the NuGet package

MyGet can build your project using a build.bat your provide. Place it at the root level of your repository. The built.bat in Espalier.Validate looks like this:

@echo Off

dotnet restore .\Espalier.Validate.Tests\project.json
dotnet restore .\Espalier.Validate\project.json

dotnet test .\Espalier.Validate.Tests\
if not "%errorlevel%"=="0" goto failure

dotnet build .\Espalier.Validate\project.json --configuration Release
if not "%errorlevel%"=="0" goto failure

dotnet pack .\Espalier.Validate\project.json --configuration release

:success
exit 0

:failure
exit -1

MyGet knows how to use the dotnet build tool by default. This batch file:

  1. Restores the NuGet packages for your projects.
  2. Runs the NUnit tests that are in Espalier.Validate.Tests.
  3. Builds release bits of Espalier.Validate.
  4. Creates a NuGet package with all the assemblies/frameworks in it.

Setting up your accounts

I’m going to assume that you already have a useful project, and unit tests that test the important things in your project. My focus will be on setting up the various integration points so your fancy project will have CI, be able to create a NuGet package, and make it easy to push it to NuGet.org. If you already have accounts on MyGet, NuGet, and GitHub, you’re golden. Otherwise, go and create them, and get your codebase into a GitHub repository already!

Configuring MyGet

There are a few things to configure in MyGet. Overall, it is fairly quick and painless to set up MyGet to create and push your NuGet packages for you. Let’s go over the steps to set that up.

Create a feed in MyGet

The first thing you’ll need to do on MyGet is create a feed for your project. Fill in the feed URL and description and leave it as a public feed:

Creating a NuGet feed in MyGet

Add a build service

Now that you have a feed, add a build service for your GitHub repository:

Create a NuGet package from your GitHub repository

Edit the build source and tell MyGet to «Automatically patch AssemblyInfo.cs / project.json / VSIX manifest / package.json.» That will give you a finer grain of control over your package version within MyGet:

Set the version when you create a Nuget package

Build your project

Go ahead and kick off a build now. MyGet will use the build.bat you created earlier to run your build and create a NuGet package.

Push your package to NuGet.org

Now head over to the Package Sources and edit the NuGet.org information and supply the credentials for your NuGet.org account, along with your API key:

To create a NuGet package, you need to specify your NuGet.org credentials

If your build was successful earlier, you should be able to go to the Packages section, click on «Push Latest» and choose «Nuget package» to initiate pushing your package to NuGet.org.

Push a NuGet package to NuGet.org

By default, this will push a pre-release package. If you want it to be a release version, you can edit the package and remove the pre-release version:

Clear the pre-release field to push a releast version

Set up some build notifications

If you’re like me, and you want to know any time a build finishes, you can configure MyGet to send you an email in the Web Hooks section of the feed for your project. Click «Add web hook» and choose «Email» then fill out the SMTP information for your email provider. You should now start receiving emails for the events you chose:

Get notified when your project has been built

Conclusion

There you have it! You now have a project with source code on GitHub that is using continuous integration to create NuGet packages that are easy to publish to NuGet.org. If you have any questions or suggestions, feel free to comment below or send me an email.

Thank you for reading!

If you enjoyed this article, please share it with your friends! I'm super excited to be writing these articles for you. This is a fairly new website, and any way you can help get the word out is much appreciated. Facebook, Twitter, Google Plus, Email... I don't discriminate. And maybe a unicorn will bless you with a wish for each person you share this with. Hey, it's worth a try!