Build Pipeline - rpapub/WatchfulAnvil GitHub Wiki
📖 Writing a CI/CD Pipeline Task for .NET Library Versioning Using GitVersion
📌 Overview
When designing a CI/CD pipeline task (e.g., GitHub Action, Azure DevOps Pipeline, GitLab CI) for building and versioning a .NET library, you must consider:
- How GitVersion will be used to generate consistent versions.
- Ensuring correct version propagation across
dotnet build
anddotnet pack
. - Handling branches, tags, and pre-releases.
- Publishing NuGet packages with correct versioning.
🔹 Key Considerations
✅ 1. Ensure GitVersion Runs Early
- GitVersion must run before
dotnet build
. - Extract versioning information once per run.
- Store it in environment variables or pipeline artifacts for reuse.
💡 Example: Running GitVersion in a Pipeline
- name: Install GitVersion
run: dotnet tool install --global GitVersion.Tool
- name: Determine Version
run: echo "VERSION=$(dotnet-gitversion /output json | jq -r '.FullSemVer')" >> $GITHUB_ENV
dotnet build
✅ 2. Pass Version Information to GitVersion provides:
FullSemVer
→ Used for assembly and package versioning.NuGetVersionV2
→ Used for NuGet package versions.AssemblySemFileVer
→ Used for FileVersion.AssemblySemVer
→ Used for AssemblyVersion.
💡 Example: Injecting Versions into dotnet build
- name: Build .NET Project
run: |
dotnet build --configuration Release \
/p:Version=${{ env.VERSION }} \
/p:FileVersion=${{ env.VERSION }} \
/p:AssemblyVersion=${{ env.VERSION }}
✅ 3. Use Correct Versioning for NuGet Packages
When running dotnet pack
, ensure:
PackageVersion
matchesGitVersion.NuGetVersionV2
.- No stale
.nupkg
files exist.
💡 Example: Running dotnet pack
with Correct Versioning
- name: Pack NuGet Package
run: |
dotnet pack --configuration Release --no-build \
/p:PackageVersion=${{ env.VERSION }} \
/p:Version=${{ env.VERSION }} \
/p:FileVersion=${{ env.VERSION }}
develop
, release/*
, and main
Differently
✅ 4. Handle Each branch should produce the correct versioning:
Branch | Expected Version | Notes |
---|---|---|
develop |
X.Y.Z-alpha.N |
CI builds, unstable pre-releases |
feature/* |
X.Y.Z-feature.BranchName.N |
Feature builds, not for release |
release/* |
X.Y.Z-beta.N |
Release candidates |
main |
X.Y.Z |
Stable versions only when tagged |
hotfix/* |
X.Y.Z-hotfix.N |
Urgent fixes for releases |
💡 Example: Detecting Branches and Handling Versions
- name: Determine Git Branch
run: echo "GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV
- name: Set Pre-Release Label for `develop`
if: startsWith(env.GIT_BRANCH, 'develop')
run: echo "VERSION=${{ env.VERSION }}-alpha.${{ github.run_number }}" >> $GITHUB_ENV
✅ 5. Publish to NuGet Only on Stable Releases
- Push
develop
builds to a pre-release NuGet feed. - Only push
main
builds when a tag is present (vX.Y.Z
).
💡 Example: Conditional NuGet Push
- name: Publish NuGet Package (Pre-release)
if: github.ref == 'refs/heads/develop'
run: dotnet nuget push "**/*.nupkg" --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
- name: Publish NuGet Package (Stable)
if: startsWith(github.ref, 'refs/tags/v')
run: dotnet nuget push "**/*.nupkg" --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
🚀 Full Example: GitHub Actions Workflow
name: Build and Publish .NET Package
on:
push:
branches:
- main
- develop
- release/*
- hotfix/*
tags:
- 'v*' # Run on version tags
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0 # Required for GitVersion
- name: Install GitVersion
run: dotnet tool install --global GitVersion.Tool
- name: Determine Version
run: echo "VERSION=$(dotnet-gitversion /output json | jq -r '.FullSemVer')" >> $GITHUB_ENV
- name: Build .NET Project
run: |
dotnet build --configuration Release \
/p:Version=${{ env.VERSION }} \
/p:FileVersion=${{ env.VERSION }} \
/p:AssemblyVersion=${{ env.VERSION }}
- name: Pack NuGet Package
run: |
dotnet pack --configuration Release --no-build \
/p:PackageVersion=${{ env.VERSION }} \
/p:Version=${{ env.VERSION }} \
/p:FileVersion=${{ env.VERSION }}
- name: Publish NuGet Package (Pre-release)
if: github.ref == 'refs/heads/develop'
run: dotnet nuget push "**/*.nupkg" --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
- name: Publish NuGet Package (Stable)
if: startsWith(github.ref, 'refs/tags/v')
run: dotnet nuget push "**/*.nupkg" --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
🔥 Final Checklist for Versioning in CI/CD
✅ Run dotnet-gitversion
at the beginning of the pipeline.
✅ Pass Version
, FileVersion
, AssemblyVersion
to dotnet build
.
✅ Ensure PackageVersion
matches NuGetVersionV2
.
✅ Use different versioning for develop
, main
, release/*
.
✅ Publish pre-release versions (alpha
, beta
) only from develop
and release/*
.
✅ Publish stable versions only on main
when a tag (vX.Y.Z
) exists.
🚀 Follow this guide to ensure your .NET library always has the correct versioning in GitHub Actions, Azure DevOps, or any CI/CD system! 🎯