Введение: почему 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 был быстрым и надежным, следуйте этим рекомендациям: