Category Archives: NuGet

Deploying my library to Github packages using Github actions

In my previous post I explained the steps to use Github actions to package and deploy your .nupkg to NuGet, but Github also includes support for you to deploy your package alongside your project sources.

If you take a look at the right hand of your project within Github (i.e. where you see your main README.md) you’ll notice the Packages section, if you click on the Publish your first package it tells you the steps you need to take to create and deploy your package, but it wasn’t quite that simple for me, hence this post will hopefully help others out a little if they hit similar issues.

The first thing you need to do is make sure you are using a version of the dotnet CLI that supports nuget commands (specifically the add command). Here’s a set-up step with a compatible version of dotnet CLI.

 - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 3.1.401

The version must be 3.1.401 or above. There may be another before this but I was using 3.1.101 and was getting the following failure in the build output

Specify --help for a list of available options and commands.
error: Unrecognized command or argument 'add'

So the first command listed in Publish your first package will fail if you’re not upto date with the version of dotnet. If you’re using ubuntu instead of Windows for your builds, then you need to include the –store-password-in-clear-text on your dotnet nuget add command. Also change GH_TOKEN to ${{ secrets.GITHUB_TOKEN }}

Hence your first command will look more like this now

dotnet nuget add source https://nuget.pkg.github.com/your_user/index.json -n github -u your_user -p ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text

Replace “your_user” with your GitHub username and if you’ve created a permission that you prefer to use in place of GITHUB_TOKEN, then replace that also.

The second line shown in Publish your first package is

dotnet pack --configuration Release

Thankfully this is worked without an issue, however the Step 3 from didn’t work for me. It requires that I set the API key, similar to way we do this with NuGet publishing but using GITHUB_TOKEN again, hence the third step for me to publish to GitHub is

dotnet nuget push your_path/bin/Release/*.nupkg --skip-duplicate --api-key ${{secrets.GITHUB_TOKEN}} --source "github"

Replacing “your_path” with the path of your package to be published. Use –skip-duplicate so that any change to your code will not fail when a build is triggered, as without this option the command tries to publish an existing/unchanged package, causing a failure. Also set the –api-key as shown.

As I am already creating a package for NuGet and want to do the same for GitHub, we can condense the commands to something like

run: |
  dotnet nuget add source https://nuget.pkg.github.com/your_user/index.json -n github -u your_user -p ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
  dotnet nuget push your_path/bin/Release/*.nupkg --skip-duplicate --api-key ${{secrets.GITHUB_TOKEN}} --source "github"

Don’t Forget

One more thing, in your nuspec or via the Properties | Package tab for your project, ensure you add a Repository URL to your source code. The Github package will fail without this.

For example in the SDK style csproj we have

<RepositoryUrl>https://github.com/putridparrot/PutridParrot.Randomizer.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>

The RepositoryType is not required for this to work, just using RepositoryUrl with https://github.com/putridparrot/PutridParrot.Randomizer worked fine.

Within a nuspec the format is as follows (if I recall)

<repository type="git" url="https://github.com/putridparrot/PutridParrot.Randomizer.git" />

Finally you’ll want to add https://nuget.pkg.github.com/your_user/index.json to you nuget.config to access Github’s NuGet package management from a project using this file and you will need a permission set up to access to API to pull in your package, alternatively simply download the package from Github and set-up a local nuget repository.

Deploying my library to NuGet using Github actions

I have a little library that I wanted to package up and make available on nuget.org. It’s nothing special, seriously it’s really not special (source available here PutridParrot.Randomizer).

Note: at the time of writing the library is very much in an alpha state, so don’t worry about the code etc., instead what we’re interested in is the .github/workflows/dotnet-core.yml.

Setting up NuGet

  • If you don’t already have a NuGet account then go to NuGet Register and sign up.
  • Next, click on the top right hand account name drop down. Clicking on this will display a drop down, from here select API Keys.
  • Click the Create option, and give your library a key name and ensure Push is checked and Push new packages and package version is selected, finally in the Glob Pattern just enter an *
  • Finally click the Create button to generate an API key

The API key should be kept secret as it will allow anyone who has access to it to upload package to your account. If for any reason you need to regenerate it, then from the Manage option on the API keys screen, click Regenerate.

Creating our deployment action

I’m using Github actions to build and then deploy my package. As you’ve seen, we need to use an API key to upload our package and obviously we do not want this visible in the build/deployment script, so the first thing we need to do is create a Github secret.

  • Go to the Settings for your project on Github
  • Select the Secrets tab on the left of the screen
  • Click New Secret
  • Give your secret a name, i.e. NUGET_API_KEY
  • In the value, of the secret, place the API key you got from NuGet

This secret is then accessible from your Github action scripts.

Note: You might be thinking, “didn’t this post say the key was to be kept secret”, I’m assuming as Microsoft owns Github and NuGet that we’re fairly safe letting them have access to the key.

Now we need to add a step to package and then a step to deploy to nuget to our Github workflow/actions.

We’re not going to be doing anything clever with our package, so not creating a nuspec for the project or signing it (at this time). So we’ll just use the dotnet CLI pack option. Here’s the addition to these dotnet-core.yml workflow for step

- name: Create Package
  run: dotnet pack --configuration Release
- name: Publish to Nuget
  run: dotnet nuget push /home/runner/work/PutridParrot.Randomizer/PutridParrot.Randomizer/PutridParrot.Randomizer/bin/Release/*.nupkg --skip-duplicate --api-key ${{secrets.NUGET_API_KEY}} --source https://api.nuget.org/v3/index.json

In the above, we have a step “Create Package” to create our package using the dotnet CLI’s pack command using release configuration. If (as I am) you’re using an ubuntu image to run your workflow this will be stored a a folder similar to this one listed below

/home/runner/work/PutridParrot.Randomizer/PutridParrot.Randomizer/PutridParrot.Randomizer/bin/Release/

Where you replace PutridParrot.Randomizer with you project name. Or better still, check the build logs to see where the output should show where the .nupkg was written to.

As you can see from the “Publish to Nuget” step, you’ll also need to reuse the path there where we again use the dotnet cli to push our nupk file to NuGet using the secret we defined earlier as the API key. In this usage we’re also not pushing if the package is a duplicate.

That’s it.

_Note: One side note – if you go onto nuget.org to check your packages, they may by in “Unlisted” state initially. This should change automatically after a few minutes to Published._

Creating a nuget package (revisited)

I’ve covered some of this post previous in my post Creating Local Packages with NuGet, but I wanted to drill down a little more into this here.

Part of the reason for a revisit is that I wanted to look at creating the relevant .nuspec for a couple of projects I’ve put on github and I wanted to cover the .nuspec files in a little more depth.

Before we start

Before we start you’ll probably want to grab the latest nuget.exe from Available NuGet Distribution Versions. The current recommended version is v4.9.4 and this should be placed in your project folder (or ofcourse wherever you prefer in the path).

Generating a nuspec file

We can now run

nuget spec

in my case, this produced the following

<?xml version="1.0"?>
<package >
  <metadata>
    <id>Package</id>
    <version>1.0.0</version>
    <authors>PutridParrot</authors>
    <owners>PutridParrot</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2019</copyright>
    <tags>Tag1 Tag2</tags>
    <dependencies>
      <dependency id="SampleDependency" version="1.0" />
    </dependencies>
  </metadata>
</package>

As you can see, it’s supplied the basics along with an example of a dependency. The dependencies are the package our project is dependent upon. The id can be found via the nuget website or from the nuget packages section within Visual Studio. The versions can also be found in the same way.

If we wish to add files to our nuspec we add a files section after the metadata end tag. For example

  </metadata>

   <files>
      <file src="" target="" />
   </files>

</package>

The src is the relative location of the files to add (maybe we’re adding a README.txt for example). The target is where the file should be copied to. Using content as the start of the target will added file to the content folder.

Naming conventions

The next thing I want to touch on is naming conventions, which I think becomes important if you’re intending the deploy on the NuGet site (as opposed to local to your organization or the likes).

The Names of Assemblies and DLLs discusses some possible conventions. Obviously the <Company>.<Component>.dll is a very sensible convention to adopt as we will need to ensure our assemblies are as uniquely named as possible to stay away from name clashes with others.

Obviously using such naming conventions will tend to push towards namespace etc. naming conventions also, so have a read of Names of Namespaces also.

Generating our NuGet package from a project

Before we look at the nuspec file itself, let’s cover the simple way of generating our NuGet package, as this might be all you need if the component/code you want to package is fairly self-contained.

Before we create the package, let’s create a bare bones .nuspec file because otherwise, the nuget tool will generate one along these lines

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata>
    <id>PutridParrot.Collections</id>
    <version>1.0.0.0</version>
    <title>PutridParrot.Collections</title>
    <authors>PutridParrot</authors>
    <owners>PutridParrot</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Description</description>
    <copyright>Copyright © PutridParrot 2017</copyright>
    <dependencies />
  </metadata>
</package>

Note: the project I ran this against was PutridParrot.Collections.csproj

So lets take this and change it a little – create a .nuspec named after your project, i.e. mines PutridParrot.Collections.nuspec and paste the below, into it (change names etc. as you need).

<?xml version="1.0"?>
<package >
  <metadata>
    <id>Your Project Name</id>
    <version>1.0.0.0</version>
    <title>Your project title</title>
    <authors>Your Name</authors>
    <owners>Your Name</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Your Description</description>
    <releaseNotes>First Release</releaseNotes>
    <copyright>Copyright 2017</copyright>
    <tags>collections</tags>
  </metadata>
</package>

Note: The tags are used by the NuGet repos, so it’s best to come up with several (with a space between each) tags for your project.

Now we’ve got a nuspec file this will be embedded into the package by nuget.

From the command line, (easiest from the folder containing the project you want to package) run

nuget pack <project-name>.csproj

Note: as the package is zipped, just append .zip to it to open using File Explorer in Windows, so you can see how it’s laid out. Don’t forget to remove the .zip when relocating to local host of remote host.

Autogenerating parts of the nuspec from AssemblyInfo

We can actually tokenize some of our nuspec and have nuget use our project’s AssemblyInfo.cs file, see Replacement tokens.

This means, for example version might be written like this

<version>$version$</version>

and will have this value automatically replaced and the nupkg will be named with that same version.

Multiple files or how to use nuget pack with the csproj

Running nuget pack against a project is useful but what if you want to handle multiple projects and/or non-project files? Then we would be better off editing the nuspec file to pull in the files we want.

Here’s an example of the previous nuspec which now includes more than one version of the project’s DLL.

<?xml version="1.0"?>
<package >
  <metadata>
    <id>Your Project Name</id>
    <version>1.0.0.0</version>
    <title>Your project title</title>
    <authors>Your Name</authors>
    <owners>Your Name</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Your Description</description>
    <releaseNotes>First Release</releaseNotes>
    <copyright>Copyright 2017</copyright>
    <tags>collections</tags>
  </metadata>
  <files>
    <file src="bin\Release\PutridParrot.Collections.dll" target="lib\net40" />
    <file src="bin\Release\PutridParrot.Collections.dll" target="lib\netstandard1.6" />
  </files>  
</package>

Now run

nuget pack PutridParrot.Collections.nuspec

Notice we’re running nuget pack against our nuspec file instead and this will bring in two DLL’s and make them available to lib\net40 and lib\netstandard1.6 thus targetting two different .NET frameworks.

The following gives a list of valid Supported frameworks that we can assign.

Solution specific NuGet repository locations

Whether we’re making our code available to others or want to simply implement solution specific changes to our NuGet repository locations, we can create a NuGet.config file which is stored in the same location as our solution. Here’s a simple example of a NuGet.config which adds a local NuGet location

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <packageSources>
       <add key="Local" value="c:\Development\LocalNuGet" />
    </packageSources>
</configuration>

References

Configuring NuGet behavior

NuGet and proxy servers

What you need to configure to use NuGet with a proxy server.

nuget.exe config -set http_proxy=http://my.proxy.address:port
nuget.exe config -set http_proxy.user=mydomain\myUserName
nuget.exe config -set http_proxy.password=myPassword

See http://stackoverflow.com/questions/9232160/nuget-behind-proxy for more information on this.

How to reference an existing NuGet package from a new project

So the scenario is this…

I’ve created a solution, added my projects, added some NuGet packages and all’s good with the world. Then I need to add a new project and reference some NuGet packages which I’m already using.

What’s the best way to do this?

In the past I’d go to the “Manage NuGet Packages” on the references section of a project and add the package again. However here’s the problem with this solution – unless you specify a specific version (you’ll be doing this through the Package Manager Console), you may find a different version of a package installed into your solution, which has its obvious downsides.

What about referencing the assemblies you require directly, i.e. use Add Reference and browse for them? I don’t actually know (at this time) whether this causes problems for NuGet with updates etc. but it’s not a great way when a package requires multiple assemblies, which make up a package.

What we really want is a way to say, reuse this package (already downloads and installed in the solution file system) in my new project.

The solution is simple, but I never noticed it before (how embarrassing)

One of the projects I’m working on has NuGet packages hosted in-house and they change often (hey its continuous deployment, that’s cool). So when I create a new project, all I want to do is get NuGet to somehow reference my existing package(s) and have NuGet handle all the references etc.

Well it’s actually all there, built into NuGet/Visual Studio.

  • Select the solution in solution explorer
  • Right mouse click and select Manage NuGet Packages for solution…
  • Select Installed packages
  • Locate the package that’s already installed
  • Click the Manager button
  • Now simply locate your new project and tick the checkbox next
  • Click OK, sit back and relax

Creating Local Packages with NuGet

NuGet allows us to download and install packages to our solutions using the NuGet manager in Visual Studio (or from the command line using nuget.exe) from a remote server – for example, nuget.org. But what if you want to host your own packages locally or remotely (outside of nuget.org) for example due to workplace policies or simply not wanting to publish your own libraries to a public server.

All the information contained in this post was gleaned from the references below. These are fantastic posts and I would urge anyone visiting this site to go and read those resources. What I want to do here is just distill things down to some basics to remind myself how to quickly and easily reproduce packages and spec for packages

Getting Started

Let’s start of by creating a local (i.e. on your development machine) NuGet package folder.

  1. Simply create a folder on your machine which will be used to store your packages, let’s call it LocalPackages
  2. In Visual Studio 2012, select Tools | NuGet Package Manager | Package Manager Settings
  3. In Package Sources you’ll see the nuget.org source, click the + button, give your source a name such as “Local Feed” and set the Source to the location of your LocalPackages folder
  4. Press OK and we’ve now added a new package source

At the point we now have Visual Studio set up to read from our packages folder – now we need to create some packages.

Creating a package

So we need to create a nupkg file (which is basically a compressed file which includes binaries and configuration – change the extension to .zip and open with your preferred zip editor/viewer to see the layout). This can be created using the Package Explorer GUI or via a nuspec file and nugget.exe.

If you don’t already have it, download and install the command line version of NuGet which can be found here see Command Line Utility. I placed mine in the folder I created previously, LocalPackages, as I will run it from here to work with the nupkg files etc.

As I prefer to let tools do the heavy lifting for me, I’ve downloaded the clickonce application, Package Explorer GUI.

With the package explorer we can easily create nupkg files without a care in the world for what’s inside them :)

So let’s create a package very quickly using the Package Explorer GUI

  1. If you haven’t already done so, download/run the Package Explorer Gui
  2. Create a new package
  3. We can now edit the meta data or meta data source from the UI – the metadata editor gives us, a simple GUI with input fields and the meta data source is basically an text editor (well it’s a little better than that but you get the idea). For now let’s stick with the GUI meta data editor with it’s nice input fields
  4. Enter an Id – this is the package name, it’s the name used when installing the package
  5. Supply a version. NuGet allows us to download specific package versions. The version should be in the format 1.2.3
  6. Now supply a human friendly title, if none is supplied the Id is used instead
  7. Now enter a comma separated list of authors
  8. I’m not going to step through every UI element here – check out the Nuspec Reference for a complete list of fields and what’s expected
  9. We can add any framework assemblies and both dependencies and assmebly references via the GUI, but also we need to actually add our assemblies, i.e. what the package has been created to deploy. We drag and drop those into the right hand pane of the GUI tool
  10. We can right click on the right pane to add files and folders and more, all of which are a little beyond this first post
  11. For now just drag and drop an assembly you wish to package and accept the defaults
  12. Save the nupkg file to the LocalPackages folder

If you now attempt to open this nupkg file, you’ll find it’s a binary file. If you prefer you can save the file as a nuspec (An XML file) via the GUI using the File | Save Meta data as… option and then when you are ready you can use

NuGet Pack MyPackageName.1.0.0.nuspec

However you may well find that this fails because the assemblies added may need updating to the actual locations on your hard drive, so open the nuspc file and check the src paths. See the GUI made things easy.

Also when running the NuGet command line tool with Pack you may get a warning about the location of your assmebly, for example mine was by default stored in lib, but running the command line I find it is warning that I should move the file to a framework-specific folder.

For now we’ll not worry about this. Instead let’s see our nuget package being used.

Is our nuget package available

We can now open Visual Studio (if not already opened) and assuming you’ve added your local package as outlined previously.

  1. Go to Tools | NuGet Package Manager | Package Manager Console
  2. Your should see “Package source” in the console, select “Local Feed” or whatever name you gave for your local package location
  3. Type
    Get-Package -ListAvailable
    

    and you should see the package you created

Adding a local nuget package to our application

  1. Create yourself a new application to test your nuget package in
  2. Now we can add our package using the Package Manager Console, for example
    Install-Package MyPackage
    

    or from the References folder on your solution, right mouse click and select Manage NuGet Packages, from Online, select your Local Feed and select your packages as normal and install

Remote Packages

Check out the excellent post Hosting Your Own NuGet Feeds. The section on “Creating Remote Feeds” get’s you up and running in no time at all.

But let’s list the steps anyway

  1. Creating a empty web application
  2. Add the NuGet.Server package using NuGet
  3. Change the WebConfig packagesPath value to match the path to your packages
  4. Run the app – yes it’s that simple
  5. In Visual Studio 2012, select Tools | NuGet Package Manager | Package Manager Settings
  6. In Package Sources click the + button, give your remote source a name such as “My Package Feed” and set the Source to the URL of your server which you just created and ran

That’s is for now.

References

Nuspec Reference
Hosting Your Own NuGet Feeds
Using A GUI (Package Explorer) to build packages
Creating and Publishing a Package
Package Manager Console Powershell Reference