Publishing .net standard nuget package with GitHub Actions

Today I introduced CI/CD to my nuget package https://www.nuget.org/packages/Atl.Repository.Standard/ and was thinking about sharing how easily you can do that with GitHub Actions.

The steps are pretty simple. I already had my project written in .net core, targeting .net standard. All I needed was a GitHub Actions configuration. The steps are –

Get sources ready

I already had my sources. So nothing new here. In case you are starting from scratch just create your solution as you usually do. However, to keep things organized I would prefer to keep all the source codes under src folder.

Create the .github folder

The workflow configuration for GitHub Actions is actually configuration files that resides in a folder named .github inside your repository root folder. Lets create it, and also create a workflow folder inside it. Each workflow should have individual yaml file. I created two workflows – 1) For building all other branches 2) For the master branch, since I also want to deploy to nuget and only when merged to master.

Here is my workflow folder structure –

The workflows

The workflows are pretty simple. GitHub takes care of everything – all you need to mention is the platform and tech stack you are going to use to build your project. I am using .net core 3.1 on ubuntu and the way to configure it is this –

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1

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

That is it. No dockerfile to spawn my container, no agents to configure, nothing else. But if you want you can use your custom agents, but for a simple .net core project, you probably won’t.

If you want to know all about GitHub Actions jobs structure follow this link – https://help.github.com/en/actions

Now, I added few more commands to build and run unit test. The whole build-and-test workflow file looks like this –

name: Atl Generic Repository - Build & Test

on: 
  push:
    branches-ignore:
      - master

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1

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

    - name: Build
      run: dotnet build --configuration Release
      working-directory: ./src

    - name: Run unit tests
      run: dotnet test --configuration Release
      working-directory: ./src

Done. Now lets push it and see it in action. If all succeeds you will be able to see something like this in GitHub Actions –

How cool is that!!!

Publish Package – Add Nuget API Key

Now we got our package being built and tested. We need it to publish it as a nuget package. For that to work we need to have an API Key generated from nuget.org to be passed through while pushing the package. GitHub Actions gives you a very good & secure option of supplying that – Secrets. You can save values needed for the jobs and access them as needed. Secrets do have some limitations – read it about the here – https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets

so, I added my api key as a secret –

and while publishing I will put it inside an ENVIRONMENT VARIABLE and access it like this –

env:
  nuget_api_key: ${{ secrets.NUGET_API_KEY }}

Publish Package – Pack it & Push it

I am using the dotnet pack command to generate the nuget package. I also added package details inside my project file –

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <Copyright />
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <Version>1.1.1-alpha</Version>
    <PackageLicenseUrl></PackageLicenseUrl>
    <RepositoryUrl>https://github.com/Activehigh/Atl.GenericRepository</RepositoryUrl>
    <Authors>Mahmudul Islam</Authors>
    <Company />
    <PackageProjectUrl>https://github.com/Activehigh/Atl.GenericRepository</PackageProjectUrl>
    <AssemblyVersion>1.1.0.0</AssemblyVersion>
    <FileVersion>1.1.0.0</FileVersion>
    <PackageTags>Generic Repository, .Net Core 2 Standard Generic Repository, EF Core Repository, EF Core Generic Repository</PackageTags>
    <PackageLicenseExpression>MIT</PackageLicenseExpression>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.2.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>

So nothing more to do, just adding the command. –

- name: Generate nuget package
  run: dotnet pack --configuration Release -o nupkg
  working-directory: ./src

One thing to note here. I am using a separate output folder nupkg to store the generated package file. The reason behind is a very weird bug in .net core sdk. If you use dotnet nuget push *.nupkg it fails with an error all the time. You can read it about here https://github.com/NuGet/Home/issues/8148 . So instead of using *.nupkg I will have to enumerate the folder for packages and then generate the proper command using bash to push to nuget repository and the command I am going to use is this –

- name: Publish nuget package
      run: find . -name *.nupkg -type f -print0 | xargs -0 -I pkg dotnet nuget push pkg -k $nuget_api_key -s "https://api.nuget.org/v3/index.json" --skip-duplicate
      env:
        nuget_api_key: ${{ secrets.NUGET_API_KEY }}
      working-directory: ./src/nupkg

My deploy.yml file looks like this –

name: Atl Generic Repository - Deploy

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1

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

    - name: Build
      run: dotnet build --configuration Release
      working-directory: ./src

    - name: Run unit tests
      run: dotnet test --configuration Release
      working-directory: ./src

    - name: Generate nuget package
      run: dotnet pack --configuration Release -o nupkg
      working-directory: ./src

    - name: Publish nuget package
      run: find . -name *.nupkg -type f -print0 | xargs -0 -I pkg dotnet nuget push pkg -k $nuget_api_key -s "https://api.nuget.org/v3/index.json" --skip-duplicate
      env:
        nuget_api_key: ${{ secrets.NUGET_API_KEY }}
      working-directory: ./src/nupkg

Done. Now we can push package to nuget. If all is good you will see something like this –

Ignore the warning about duplicate package, cause I already pushed the package while testing … 🙂

And there you go.

How easy was that!!! So far I really liked GitHub Actions. I will probably going to use it to put all the packages in a ci/cd pipeline. It is free, easy and all your config stays with your code.

Go Ahead. Give it a try.

Oh wait, I almost forgot, you also get a badge of the build status and can integrate with your repo :). All you got to do is add the this link to your REDME –


![](https://github.com/<username>/<repo>/workflows/<urlencoded workflow name>/badge.svg)

And you get a status badge like below –

I would like to say something ...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.