Switching to NuGet trusted publishing
When the support for trusted publishing on NuGet was announced, I decided to try switching to it for my side project as soon as possible. The process ended up being very smooth.
As described in a previous blog post, I am publishing NuGet packages using GitHub Actions. Until now, I had a NuGet API key stored in secrets and used it to authenticate with NuGet:
- name: Publish NuGet package
if: startsWith(env.tag, 'v')
run: dotnet nuget push nupkg/*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://nuget.org
It worked perfectly fine for me. The only downside was having to update the API Key every year because the old one expired. Fortunately, NuGet reminds you about this in advance. It's only a couple of weeks since I had to do it last time, so I was very happy when I learned that I might not have to do it anymore.
The necessary steps are well described in the documentation.
First, a new policy has to be created in the Trusted Publishing section of your NuGet settings. You need to provide the following data:
- Policy Name: A name for the policy so that you will recognize it in the future. I used my project name.
- Package Owner: Your username or the name of the organization owning the package you will be publishing.
- Repository Owner: GitHub user or organization that owns the repository inside which the GitHub Actions workflow will be running.
- Repository: The name of the repository inside which the GitHub Actions workflow will be running.
- Workflow File: Name of the workflow (YAML) file inside
.github/workflows
directory for the workflow which will publish the package. - Environment: Name of the GitHub Actions environment from which the package will be published. Can be empty if you're not using environments.
Once you have created the policy, it's time to modify the workflow file. In my case I only had to:
Add a new step before the package publishing step to retrieve a temporary NuGet API key using OpenID Connect (OIDC). The NuGet Login action takes care of that. You only need to provide it your NuGet username (not email), preferably read from a secret (don't forget to add the secret to GitHub Actions if you use this approach):
- name: NuGet login (get temporary API key using OIDC) uses: NuGet/login@v1 id: login with: user: ${{secrets.NUGET_USER}}
Read the NuGet API key for the publishing step from the output of this new step instead of from a secret:
- name: Publish NuGet package if: startsWith(env.tag, 'v') run: dotnet nuget push nupkg/*.nupkg -k ${{ steps.login.outputs.NUGET_API_KEY }} -s https://nuget.org
After you commit these changes to your repository, the workflow should successfully publish the NuGet package using the trusted publishing flow instead of the long lived API key from the secrets. I tested the process by releasing a new patch version of my project.
When that succeeded, it was time for the final cleanup:
- I deleted the NuGet API key secret from GitHub Actions.
- I deleted the API key from the NuGet settings.
The trusted publishing flow was surprisingly simple to implement in a working GitHub Actions workflow for NuGet package publishing. The few changes that need to be done are well documented. I would recommend everyone who is publishing NuGet packages from GitHub Actions to replace the persisted API key with this new flow.