CI/CD for C# Projects: GitHub Actions from A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

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 normal

This 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 test

The 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 restore

Now, 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

Blogs

Book Recommendations