GitHub Actions: automatically push NuGet package

I’m trying to configure my Github repository in order to automatically have a NuGet package built and pushed to both nuget.org and github.com. So what I want is that each time a commit is made on the master branch, or another branch is merged into the master, github publishes a new Nuget package of the head of the master to both Nuget and Github.

NuGet

  1. On my nuget organization account, I generated an access token (username - API keys - Create)
  2. On Github (select your organization - View organization - Settings tab - Secrets) I added a secret with the name PUBLISH_TO_NUGET_ORG and my nuget access token

Github

  1. On my personal account, I generated an access token (Account - Settings - Developer settings - Personal access tokens - generate)
  2. On Github I added a secret with the name PUBLISH_TO_GITHUB_COM and my github access token

These are the scopes for my Github access token:

Scopes for my Github access token

Setup

In my github repository I’ve setup an action to restore, build, test, pack and publish:

name: .NET Core

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 3.1.301
    - name: Install dependencies
      run: dotnet restore
    - name: Build
      run: dotnet build --configuration Release --no-restore
    - name: Test
      run: dotnet test --no-restore --verbosity normal
#    - name: Publish
#      uses: brandedoutcast/publish-nuget@v2.5.2
#      with:
#          PROJECT_FILE_PATH: MintPlayer.SeasonChecker/MintPlayer.SeasonChecker.csproj
#          NUGET_KEY: ${{secrets.PUBLISH_TO_NUGET_ORG}}
#          INCLUDE_SYMBOLS: true
    - name: Pack
      run: dotnet pack --no-build --configuration Release MintPlayer.SeasonChecker/MintPlayer.SeasonChecker.csproj --output .
    - name: PushNuget
      run: dotnet nuget push *.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{secrets.PUBLISH_TO_NUGET_ORG}} --skip-duplicate
    - name: AddGithubSource
      run: dotnet nuget add source --username PieterjanDeClippel --password ${{secrets.PUBLISH_TO_GITHUB_COM}} --name github https://nuget.pkg.github.com/MintPlayer/index.json
    - name: PushGithub
      run: dotnet nuget push *.nupkg --source github --skip-duplicate

The push to nuget.org works fine, but the push to my GitHub feed fails with an Unauthorized error.

I’ve taken a look at some plugins like this one, and I want to embed this into my action in order not to build my project multiple times.

First take:

dotnet nuget push *.nupkg --source https://nuget.pkg.github.com/MintPlayer/index.json --api-key ${{secrets.PUBLISH_TO_GITHUB_COM}} --skip-duplicate

Result:
warn : Your request could not be authenticated by the GitHub Packages service. Please ensure your access token is valid and has the appropriate scopes configured.

warn : Your request could not be authenticated by the GitHub Packages service. Please ensure your access token is valid and has the appropriate scopes configured.

Second take with multiple commands:

dotnet nuget add source --username PieterjanDeClippel --password ${{secrets.PUBLISH_TO_GITHUB_COM}} --name github https://nuget.pkg.github.com/MintPlayer/index.json
dotnet nuget push *.nupkg --source github --skip-duplicate

This one fails with the following (obvious) message:

error: Password encryption is not supported on .NET Core for this platform. The following feed try to use an encrypted password: 'github'. You can use a clear text password as a workaround.
error:   Encryption is not supported on non-Windows platforms.

Does anyone have any experience with automated publishing of Nuget packages to Github?

Link to action configuration file

Edit

I tried sending a POST request:

And I’m getting my user information, so my access token definitely works.

Also when I visit https://nuget.pkg.github.com/MintPlayer/MintPlayer.SeasonChecker/index.json in my webbrowser, I get a login prompt and after signing in with a PAT (and not my password) I get the information for my NuGet package. So my PAT definitely works.

Does anybody have an idea how to solve this?

Hi @PieterjanDeClippel,

Instead of using, dotnet nuget add source, you can use the setup-dotnet to create the appropriate nuget.config file. For example"

    - uses: actions/setup-dotnet@v1.5.0
      with:
        dotnet-version: '3.1.x' # SDK Version to use.
        source-url: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
      env:
        NUGET_AUTH_TOKEN: '%NUGET_AUTH_TOKEN%'

    - name: Publish the package to GPR
      run: dotnet nuget push path/to/*.nupkg
      env:
        NUGET_AUTH_TOKEN: ${{ github.token }}

This should work to associate your package with the same repository as the workflow. You only need to create a PAT if you’re associating it with a different repository.

I hope that helps!

Hi,

I’ll try that. So if I understand correctly, the github.token variable is pulled from the action, and I don’t have to define it myself.

Sweet, It’s working now.

name: .NET Core

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1.5.0
      with:
        dotnet-version: 3.1.301
        source-url: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
      env:
        NUGET_AUTH_TOKEN: '%NUGET_AUTH_TOKEN%'
    - name: Install dependencies
      run: dotnet restore
    - name: Build
      run: dotnet build --configuration Release --no-restore
    - name: Test
      run: dotnet test --no-restore --verbosity normal
    - name: Pack
      run: dotnet pack --no-build --configuration Release MintPlayer.SeasonChecker/MintPlayer.SeasonChecker.csproj --output .
    - name: PushNuget
      run: dotnet nuget push *.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{secrets.PUBLISH_TO_NUGET_ORG}} --skip-duplicate
    - name: PushGithub
      run: dotnet nuget push *.nupkg --no-symbols --skip-duplicate
      env:
        NUGET_AUTH_TOKEN: ${{ github.token }}

Very nice implementation.

Thanks for the help.

The ${{ github.token }} is automatically created by the workflow and has write access to the home repository.

I’m glad it’s now working! Let me know if you notice any other issues.

It still doesn’t seem to be working correctly.

GitHub succeeded in pushing the package the first attempt. But when I made another change + version increment, the Action fails again, this time at the Install dependencies stage.

It appears that dotnet is trying to restore ALL packages from my own NuGet source now, instead of the source where they are hosted.

Determining projects to restore...
/opt/hostedtoolcache/dncs/3.1.301/x64/sdk/3.1.301/NuGet.targets(128,5): warning : Your request could not be authenticated by the GitHub Packages service. Please ensure your access token is valid and has the appropriate scopes configured. [/home/runner/work/MintPlayer.SeasonChecker/MintPlayer.SeasonChecker/MintPlayer.SeasonChecker.sln]
Retrying 'FindPackagesByIdAsync' for source 'https://nuget.pkg.github.com/MintPlayer/download/netstandard.library/index.json'.
Response status code does not indicate success: 401 (Unauthorized).
/opt/hostedtoolcache/dncs/3.1.301/x64/sdk/3.1.301/NuGet.targets(128,5): warning : Your request could not be authenticated by the GitHub Packages service. Please ensure your access token is valid and has the appropriate scopes configured. [/home/runner/work/MintPlayer.SeasonChecker/MintPlayer.SeasonChecker/MintPlayer.SeasonChecker.sln]

So dotnet looks for NetStandard.Library in my own NuGet feed.

How can I fix this?

What does your nuget.config file look like?

Right now there’s no nuget.config in my solution/project.

Are you aiming at defining my package sources for the action? Right now on my computer I’m using the system-wide package sources. So when I run

dotnet nuget list source

command from anywhere the list of sources is shown (including my own nuget feed).

Should I create a nuget.config like this containing my own nuget feed, and remove the source-url from the action?

Okay that was it.

I added a nuget.config to my solution folder

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
  </packageSources>
</configuration>

And now my deployment is working fine.

Thanks a lot for the help

@PieterjanDeClippel,

I think it was trying to restore from both, but GitHub Packages was failing because NUGET_AUTH_TOKEN wasn’t being passed.

Could you try changing the dotnet restore step to this and remove nuget.config?

    - name: Install dependencies
      run: dotnet restore
      env:
        NUGET_AUTH_TOKEN: ${{ github.token }}

BTW, it is possible to pass the token directly to actions/setup-dotnet, but I prefer to only pass the token to steps that need it. That way you’re only trusting dotnet restore and dotnet nuget with your token.

Piggybacking off of this. I have implemented a near identical solution that pushes multiple packages, but the --skip-duplicate flag is ignored while pushing and causes a failure. Is there a reason why that flag would be ignored?

1 Like

@joelrevans I switched from

dotnet nuget push *.nupkg --no-symbols --skip-duplicate

to

nuget.exe push "**/*.nupkg" -NoSymbols -SkipDuplicate

And now the step does not error when attemting to push a duplicate package.

image

I needed to switch to nuget.exe because of this

1 Like