CI/CD для C# проектов на GitHub Actions: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему CI/CD важен для C# разработчика

В современной разработке программного обеспечения ручное тестирование и деплой — это неэффективно и рискованно. Каждый раз, когда разработчик пушит код в репозиторий, возникает потребность убедиться, что сборка не сломалась, тесты проходят, а приложение готово к развертыванию. Именно здесь на помощь приходит CI/CD (Continuous Integration / Continuous Deployment).

GitHub Actions — это встроенный инструмент автоматизации в GitHub, который позволяет создавать рабочие процессы (workflows) прямо в вашем репозитории. Он идеально подходит для C# (.NET) проектов, так как поддерживает как Windows, так и Linux раннеры, а также имеет богатую экосистему готовых действий (actions).

В этой статье мы разберем, как настроить полноценный пайплайн CI/CD для C# проекта с использованием GitHub Actions: от сборки и тестирования до публикации NuGet пакета или деплоя веб-приложения.

Основы GitHub Actions: YAML и структура workflow

Каждый workflow в GitHub Actions описывается в YAML-файле, который хранится в директории .github/workflows/ вашего репозитория. Рассмотрим базовую структуру:

name: .NET CI/CD

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Setup .NET
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: '8.x'

    - name: Restore dependencies
      run: dotnet restore

    - name: Build
      run: dotnet build --configuration Release --no-restore

    - name: Run tests
      run: dotnet test --configuration Release --no-build --verbosity normal

Ключевые элементы:

  • on — триггеры запуска (push, pull_request, schedule и т.д.)
  • jobs — набор задач, которые выполняются параллельно или последовательно
  • runs-on — операционная система для выполнения (ubuntu-latest, windows-latest, macos-latest)
  • steps — последовательность команд или готовых actions

Важно: для .NET проектов используйте action actions/setup-dotnet с указанием версии SDK. Это гарантирует, что среда будет содержать нужную версию .NET.

Настройка тестирования и линтинга C# кода

Качественный CI/CD не может обойтись без автоматических тестов и проверки стиля кода. Добавим в наш workflow этапы юнит-тестирования и статического анализа.

Юнит-тесты с xUnit и покрытие кода

Предположим, у вас есть проект с тестами на xUnit. Добавим шаг для генерации отчета о покрытии с помощью Coverlet:

- name: Run tests with coverage
  run: |
    dotnet test --configuration Release \
      --no-build \
      --verbosity normal \
      /p:CollectCoverage=true \
      /p:CoverletOutputFormat=opencover \
      /p:CoverletOutput=./coverage.xml

- name: Upload coverage to Codecov
  uses: codecov/codecov-action@v3
  with:
    files: ./coverage.xml
    flags: unittests
    fail_ci_if_error: false

Для этого в проект с тестами необходимо добавить пакет coverlet.collector. Пример команды:

dotnet add package coverlet.collector

Статический анализ с Roslyn Analyzers

Добавим проверку кода с помощью встроенных анализаторов .NET:

- name: Run Roslyn analyzers
  run: dotnet build --configuration Release --warnaserror -p:RunAnalyzersDuringBuild=true

Также можно использовать сторонние инструменты, например, SonarCloud:

- name: SonarCloud Scan
  uses: SonarSource/sonarcloud-github-action@master
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Не забудьте добавить SONAR_TOKEN в секреты репозитория (Settings → Secrets and variables → Actions).

Деплой C# приложения: NuGet пакет и веб-приложение

После успешного тестирования можно переходить к деплою. Рассмотрим два популярных сценария для C# проектов.

Публикация NuGet пакета

Если вы разрабатываете библиотеку, автоматическая публикация в NuGet.org спасет много времени. Пример workflow:

jobs:
  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Setup .NET
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: '8.x'

    - name: Pack
      run: dotnet pack --configuration Release -o ./nupkg

    - name: Push to NuGet
      run: dotnet nuget push ./nupkg/*.nupkg \
        --api-key ${{ secrets.NUGET_API_KEY }} \
        --source https://api.nuget.org/v3/index.json

Важно: версия пакета должна быть уникальной. Рекомендуется использовать GitVersion или ручное управление версиями в .csproj.

Деплой ASP.NET Core веб-приложения

Для веб-приложений можно настроить деплой на Azure App Service или собственный сервер через FTP/SSH. Пример с Azure Web App:

- name: Deploy to Azure Web App
  uses: azure/webapps-deploy@v2
  with:
    app-name: 'my-csharp-app'
    publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
    package: ./publish

- name: Publish artifacts
  run: |
    dotnet publish --configuration Release \
      --output ./publish \
      --runtime win-x64 \
      --self-contained false

Для деплоя на собственный сервер можно использовать action appleboy/scp-action или easingthemes/ssh-deploy. Пример с SCP:

- name: Deploy via SCP
  uses: appleboy/scp-action@v0.1.4
  with:
    host: ${{ secrets.HOST }}
    username: ${{ secrets.USERNAME }}
    key: ${{ secrets.SSH_KEY }}
    source: "./publish/*"
    target: "/var/www/myapp"
    strip_components: 2

Оптимизация и лучшие практики

Чтобы ваш CI/CD был быстрым и надежным, следуйте этим рекомендациям:

Блоги

Рекомендаций по книгам