You can host software packages in GitHub Packages and share them privately to a repo or organization or publicly share with anyone. However, when writing this book, shared public repo packages could be accessed only by creating a personal access token with read permission, which is not the ideal setup for a package hosting service. GitHub Packages can host NuGet, npm, RubyGems, Apache Maven, and Gradle.
This chapter explores creating a NuGet package, pushing it to GitHub Packages using an action workflow, using the package to develop another application, and learning how package management works with GitHub Actions packages.
Creating a NuGet Package with dotnet pack
You can package a NuGet package using the dotnet pack command locally and in GitHub actions. Let’s create a simple NuGet sample code to learn how to create a GitHub action workflow and publish a NuGet package to GitHub Packages.
Create a GitHub repo and clone it to the development machine. VS Code generates a class library project with the following command.
dotnet new classlib
In the class library project, you can add simple demo code to show how a NuGet package is used. For example, you can create a class with the following code.
using System;
namespace mydotnetpacknugetpkg
{
public class DemoPackageDotnetPack
{
public string HelloWorldNugetDemo()
{
return "Hello world! Welcome to nuget packages with dotnet pack!";
}
}
}
When we generate the class library project, it initially contains the information shown in Figure 7-1.
Figure 7-1
csproj contents
To enable dotnet pack to create the NuGet package, which is publishable to GitHub Packages, you need to add the following to the csproj file’s PropertyGroup section.
<PackageId>mydotnetpacknuget</PackageId>
<VersionPrefix>1.0.0</VersionPrefix>
<VersionSuffix>$(VersionSuffix)</VersionSuffix>
<Authors>chamindac</Authors>
<Company>My Company</Company>
<PackageDescription>NuGet package sample with dotnet pack!</PackageDescription>
The package ID defines the name of the NuGet package to be created. The version prefix is the first part of the package version. A suffix can be applied with the dotnet pack command. To enable the suffix, <VersionSuffix>$(VersionSuffix)</VersionSuffix> needs to be in the csproj file’s PropertyGroup section.
You need an author and a description of the package. You may add a company name as well. You must add the GitHub repository URL to ensure that the NuGet package can be deployed to the GitHub Packages (see Figure 7-2).
Figure 7-2
csproj updated for dotnet pack support
You can commit and push the code to a GitHub repo and add the workflow to the repo to build and package the code as a NuGet package, which can be used by other projects.
First, let’s add a workflow that runs on a push and a job running on the ubutnu-latest runner.
on: [push]
jobs:
dotnetpack_nugetpush_job:
runs-on: ubuntu-latest
Next, you need to set up variables in the workflow job to be used in the job steps.
The csproj project path is used to build, publish, and package steps. The build configuration is for configuration in building and packaging a NuGet package. The output path folder is the place where the build creates the NuGet package, which can be later used to locate the package in an action for uploading the package to the registry. The GitHub workflow run ID is the package version suffix.
You can use the run ID in the build step to ensure that the project’s assemlyinfo is updated with the same version number as the NuGet package. This ensures that the DLL files in the NuGet package have the same version number. A GitHub token secret authenticates pushing the package to the repository. The URL is kept in another variable. These variables should be defined at the job level. Get information from default environment variables such as a GitHub token or a workflow run ID since run command lines in action steps may not evaluate them as expected. However, by using job environment variables, you can apply values in steps as expected.
The first step is to check out the repo.
steps:
- uses: actions/checkout@v2.3.4
Then you need to set up the .NET framework SDK.
- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: '5.0.101'
Next, restore packages and execute the build step. The project path is set via a variable. A version suffix is applied to the assemblies with the workflow run ID.
Once the package is created, it can be pushed to GitHub Packages with the dotnet nuget push command, providing authentication with a GitHub token available to the workflow (see Figure 7-4).
Once the pipeline executes, the pushed package is available in the repo (see Figure 7-5).
Figure 7-5
Package in GitHub repo
This section explored how to package a NuGet package using the dotnet pack command in a GitHub Actions workflow and push it to GitHub Packages.
Creating a NuGet Package Using a nuspec File
You can utilize a nuspec file and package as a NuGet package, and then push it to GitHub Packages to share the package. Let’s set up each GitHub Actions workflow step to use a nuspec file to package a class library as a NuGet package and push it to GitHub Packages.
First, you need to create a class library using the following command.
dotnet new classlib
Then add the following class as a sample implementation of the reusable NuGet package code.
using System;
namespace mynuspecnugetpkg
{
public class DemoPackageNuspec
{
public string HelloWorldNugetDemo()
{
return "Hello world! Welcome to nuget packages with nuspec!";
}
}
}
In this class library’s csproj file, add <VersionPrefix>1.0.0</VersionPrefix> to apply a version suffix to the DLL (see Figure 7-6).
Figure 7-6
The class library csproj file
You dynamically add a nuspec file in a GitHub Actions workflow; therefore, you only have to push the class library code to the repo. Once the code is pushed, you can create the workflow.
You can set the workflow to run on a push and create a job to run on an ubuntu-latest runner.
You are setting the package name, the project path to build, the nuspec file path, the configuration to build, the build output path, the package output path, the GitHub token, the GitHub package registry URL, the workflow run ID, and the GitHub repo URL, which are set in the nuspec file as variables.
The first step is to check out the repo, and then set up the .NET SDK.
steps:
- uses: actions/checkout@v2.3.4
- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: '5.0.101'
Then you can restore packages and build the class library project providing version suffix as GitHub Actions workflow run ID. The runid suffix maintains unique package versions.
You need to create a nuspec file in the path where the build output is available. You set the version in the nuspec file to act as a version prefix for the package (see Figure 7-7).
- name: Create nuspec file
shell: pwsh
run: |
$nuspec = '<?xml version="1.0"?>
<package >
<metadata>
<id>mynuspecnuget</id>
<version>1.0.0</version>
<authors>chdemo</authors>
<description>NuGet package sample with nuspec!</description>
Next, a NuGet package is created with the nuget command using the nuspec file and the build output. The new NuGet package’s version is applied with a suffix, which is stored in the package’s output path (see Figure 7-8).
The package is pushed to GitHub Packages once the workflow is executed (see Figure 7-10).
Figure 7-10
Package pushed to GitHub Packages
This section explored the steps required to create a NuGet package via a nuspec file and push the package to GitHub Packages.
Using Packages in GitHub Packages
The purpose of creating packages and making them available in a registry is to enable them to be used by other projects. Let’s look at using the NuGet packages created in the previous sections in another .NET project.
You can create a console application in VS Code by executing the following command.
dotnet new console
Once the project is created, you must add a nuget.config file specifying the GitHub package registry information and access tokens. When writing this book, it was not possible to anonymously access the packages from GitHub, even if the package is in a public GitHub repo.
You need to set up a personal access token to access GitHub Packages. Go to Developer settings and create a personal access token (see Figure 7-11).
Figure 7-11
Generate token
Packages only need read access to the token (see Figure 7-12).
Once a token is created, copy it to a secure location because it can no longer be seen once closed. Then in the project, create a nuget.config file with the following content.
Once you execute the sample console application, the NuGet package is used and shows the correct message (see Figure 7-15).
Figure 7-15
Console app using NuGet pack from GitHub Packages
This section looked at referring to a NuGet package in GitHub Packages. As long as you are adding nuget.config files, you can do a normal dotnet restore and build for a console application using GitHub Actions workflows.
Summary
This chapter discussed creating a NuGet package and push packages to GitHub Packages using a GitHub Actions workflow. It also looked at using them in other projects.
The next chapter explores GitHub Actions workflow service containers and enhancing workflow capabilities.