Introduction: Why CI/CD is the Standard for Modern .NET Development
Modern development in C# and the .NET platform is unthinkable without automation. Manually running builds, tests, and deployments is a path to errors, wasted time, and release delays. CI/CD (Continuous Integration / Continuous Deployment) solves these problems, making the code delivery process predictable and fast.
GitHub Actions is a built-in automation tool on GitHub that is perfect for C# projects. It allows you to configure a pipeline directly in the repository using YAML files. In this article, we will cover the full cycle: from basic build to publishing a NuGet package and deploying a web application.
1. GitHub Actions Basics for .NET
What is a workflow and a job?
A workflow is an automated process that is triggered by an event (push, pull request, schedule). A workflow consists of one or more jobs that run on runners (a virtual machine with Ubuntu, Windows, or macOS).
Each job consists of steps, which can execute shell commands or use ready-made actions from the marketplace.
First workflow: building a .NET project
Create a folder .github/workflows in the root of your repository and a file build.yml:
name: Build .NET Project
on: push: branches: [ main ] pull_request: branches: [ main ]
jobs: build: runs-on: ubuntu-latest
steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '8.0.x' - name: Restore dependencies run: dotnet restore - name: Build run: dotnet build --no-restore --configuration Release - name: Run tests run: dotnet test --no-build --configuration Release --verbosity normalThis workflow runs on every push or pull request to main. It restores dependencies, builds the project in Release mode, and runs tests. If any step fails, the workflow stops, and you will see a red status in the PR.
2. Advanced Configuration: Build Matrix and Caching
.NET version matrix
To check compatibility with different .NET versions, use a matrix:
jobs: build: strategy: matrix: dotnet-version: ['6.0.x', '7.0.x', '8.0.x'] os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }}
steps: - uses: actions/checkout@v4 - name: Setup .NET ${{ matrix.dotnet-version }} uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ matrix.dotnet-version }} - run: dotnet build --configuration Release - run: dotnet testThe runner will execute the build for each combination of OS and .NET version in parallel. This saves time and ensures cross-platform compatibility.
Dependency caching
Restoring NuGet packages every time takes time. Enable caching:
- name: Cache NuGet packages uses: actions/cache@v4 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} restore-keys: | ${{ runner.os }}-nuget-
- name: Restore dependencies run: dotnet restoreNow, on subsequent runs, packages will be restored from the cache if the .csproj files have not changed.
3. Publishing a NuGet Package to GitHub Packages
If you are developing a C# library, you can automatically publish it to GitHub Packages when a release is created.
Workflow for publishing
name: Publish NuGet Package
on: release: types: [published]
jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4