Featured image of post Automating NuGet Publishing: Set It and Forget It

Automating NuGet Publishing: Set It and Forget It

Sharing code between microservices should be easy.

In the beginning, we made the classic mistake: copy-pasting the Contracts project between solutions. “It’s just one file,” we said. “It won’t change often,” we said.

Narrator: It changed often.

Then we grew up and started building NuGet packages. But manually packing and uploading to an internal feed is a drag. You forget to bump the version. You upload a debug build by mistake. It’s DLL Hell reinvented.

Automated Factory

For our public-facing Contracts library in MyProject, we decided to automate the entire lifecycle using GitHub Actions.

The goal:

  1. Developer modifies a contract.
  2. Developer pushes to main.
  3. GitHub Actions builds, packs, and pushes a new version to NuGet.org.
  4. I drink coffee.

The Workflow

Here is the secret sauce. We use a GitHub Action that triggers only when files in the specific project folder change.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
name: Publish NuGet Package

on:
  push:
    branches: [ "main" ]
    paths:
      - 'src/MyProject.Contracts/**' # <--- Only run if contracts change

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup .NET
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: 9.0.x
        
    - name: Pack
      run: dotnet pack src/MyProject.Contracts/MyProject.Contracts.csproj -c Release -o out
      
    - name: Push
      run: dotnet nuget push "out/*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json

Configuring Versioning

This workflow is great, but how do we handle version numbers? We found that simply updating the <Version> tag in the .csproj file before merging is the simplest way for now. The pipeline does the rest.

Now, our consuming apps can just run dotnet add package MyProject.Contracts and always get the latest definitions without me having to lift a finger.

All rights reserved
Built with Hugo
Theme Stack designed by Jimmy