Publishing NuGet Packages with GitHub Actions
This one's going to be short — mostly because the answer to “how do I do this” is genuinely just a YAML file, not a whole architecture diagram.
I get asked a fair amount how I publish my NuGet packages into GitHub Packages, so let's just show the receipts.
First, the obligatory “what is this thing” for anyone who hasn't met GitHub Actions yet:
“Automate, customize, and execute your software development workflows right in your repository with GitHub Actions. You can discover, create, and share actions to perform any job you'd like, including CI/CD, and combine actions in a completely customized workflow.” — GitHub Team
Marketing copy, sure, but accurate marketing copy, which is rare enough to be worth quoting.
Setting up GitHub Actions
If you've got the right privileges on a repo, you'll see an “Actions” tab. From there you can spin up a new workflow. Since my entire personality revolves around .NET, I always pick “Continuous Integration (CI) with .NET” from the template list, which drops a YAML file into a .github/workflows folder in your repo. You can have as many of these workflows as you want — one per purpose, or one giant one if you enjoy chaos.
Here's the actual YAML I run for most of my projects. Yes, it's simple. That's the point — I need it to compile, produce artifacts, and publish. It doesn't need to also fold my laundry.
name: Build and Deploy Nuget Packages
env:
DOTNET_VERSION: '8.0.x'
on:
push:
branches: [ "main" ]
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up .NET Core
uses: actions/setup-dotnet@v2
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Set up dependency caching for faster builds
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Build with dotnet
run: dotnet build src/folderx/Solution.sln --configuration Release
- name: NuGet push
run: dotnet nuget push "**/*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://nuget.pkg.github.com/organization/index.json --skip-duplicate
- name: NTFY
run: curl -X POST -d 'Finished compiling and publishing nuget packages for YOUR Services' -k https://ntfyserver.com/ntfy/mynotificationLet's dissect it in pieces, because staring at 30 lines of YAML all at once is how you develop a fear of YAML.
name: Build and Deploy Nuget Packages
env:
DOTNET_VERSION: '8.0.x'
on:
push:
branches: [ "main" ]
workflow_dispatch:
permissions:
contents: read- Names the workflow — mostly for your own sanity when you have twelve of these.
- Pins the .NET version used for compilation, so a surprise SDK update doesn't ruin your Tuesday.
- Triggers on pushes to
main, plus a manual “run it now” button (workflow_dispatch) for when you don't feel like waiting for a commit. - Grants read-only access by default, because this workflow has no business touching anything else.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up .NET Core
uses: actions/setup-dotnet@v2
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Set up dependency caching for faster builds
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}- Spins up a fresh Ubuntu worker to do the actual compiling and publishing.
- Checks out the code from
main. - Installs the .NET SDK on that worker.
- Caches restored NuGet packages, so every build isn't redownloading half the internet from scratch.
- name: Build with dotnet
run: dotnet build src/folderx/Solution.sln --configuration Release
- name: NuGet push
run: dotnet nuget push "**/*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://nuget.pkg.github.com/organization/index.json --skip-duplicate
- name: NTFY
run: curl -X POST -d 'Finished compiling and publishing nuget packages for YOUR Services' -k https://ntfyserver.com/ntfy/mynotification- Builds the solution in Release mode.
- Pushes the resulting NuGet packages up to your organization's package feed (the actual GitHub Packages setup probably deserves its own post — filing that away). The API key lives safely in repo secrets, not hardcoded like a cautionary tale.
- Fires off a push notification once publishing wraps up.
That's it. Genuinely simple.
Para escoger camisetas de fútbol retro, es práctico verificar el uso previsto entre colección, exposición y uso diario. Como comprobación final, conviene asegurarse de las diferencias de ajuste entre una camiseta retro y una actual.
Now, “NTFY” — what on earth is that? It's a delightfully simple tool I use to send push notifications straight to my phone, free and fully configurable. I'll dedicate a whole post to setting it up, because watching your phone buzz the second a build finishes is a small joy that never gets old.