C# / .NET .NET в SDLC: CI/CD, релизы, безопасность зависимостей и лучшие ресурсы
0%

.NET в SDLC: CI/CD, релизы, безопасность зависимостей и лучшие ресурсы

.NET в SDLC и лучшие ресурсы

Заключительная статья связывает всё воедино. Язык и фреймворк — лишь инструменты; ценность возникает, когда они встроены в здоровый жизненный цикл разработки ПО (SDLC): от идеи до работающего в проде и обслуживаемого сервиса. Разберём, как .NET проходит каждый этап, и дадим карту ресурсов для дальнейшего роста.

SDLC глазами .NET-инженера

  • Требования и дизайн. Здесь решается граница сервисов, доменная модель (см. статью про архитектуру), контракты API (OpenAPI/Swagger — ASP.NET Core генерирует спеку автоматически). ADR (Architecture Decision Records) фиксируют «почему» решений.
  • Разработка. Ветвление (обычно trunk-based или короткие feature-ветки), pull request-ы, обязательное code review, .editorconfig и анализаторы держат единый стиль без споров.
  • Тесты и CI. На каждый PR — сборка, формат, анализаторы, юнит- и интеграционные тесты (статья про тестирование). Красная сборка блокирует мёрж.
  • Релиз и CD. Сборка иммутабельного артефакта (контейнера), продвижение по средам, выкатка (статья про деплой).
  • Эксплуатация. Наблюдаемость, алерты, on-call, разбор инцидентов, обратная связь в требования. Цикл замыкается.

Ключевая идея DevOps: границы между этапами размываются, а инженер отвечает за фичу «от коммита до прода и дальше». .NET хорошо это поддерживает единым тулчейном.

Code review: на что смотреть

Ревью — не про стиль (это делают анализаторы), а про суть:

  • Корректность и краевые случаи — что при null, пустой коллекции, отмене, гонке.
  • Конкурентность — нет ли sync-over-async, async void, потерянных Task, гонок (см. статью про конкурентность). Это самые дорогие баги.
  • Границы и зависимости — не течёт ли инфраструктура в домен, правильны ли времена жизни DI.
  • Тесты — покрыта ли новая логика, проверяют ли тесты поведение, а не реализацию.
  • Наблюдаемость — логируются ли ключевые события структурно, есть ли метрики/трейсы для нового пути.
  • Безопасность — валидация ввода, нет секретов в коде, параметризованные запросы.

Держите PR маленькими — большие ревью проходят формально и пропускают баги.

Пример CI/CD пайплайна

Ниже — реалистичный GitHub Actions workflow: сборка, проверки качества, тесты, сборка и публикация контейнера. Тот же принцип переносится на GitLab CI, Azure Pipelines.

name: ci-cd
on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read
  packages: write

jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '9.0.x'

      # Воспроизводимое восстановление по lock-файлу
      - run: dotnet restore --locked-mode

      # Качество: формат и анализаторы (TreatWarningsAsErrors уже в csproj)
      - run: dotnet format --verify-no-changes
      - run: dotnet build -c Release --no-restore

      # Тесты + покрытие (Testcontainers работает — Docker есть на runner'е)
      - run: dotnet test -c Release --no-build --collect:"XPlat Code Coverage"

      # Аудит уязвимостей в зависимостях — блокируем при находках
      - run: dotnet list package --vulnerable --include-transitive 2>&1 | tee audit.txt
      - run: if grep -q "has the following vulnerable" audit.txt; then exit 1; fi

  publish-image:
    needs: build-test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with: { dotnet-version: '9.0.x' }
      # Сборка образа средствами SDK, без Dockerfile
      - run: |
          dotnet publish src/MyApp.Api -c Release \
            -t:PublishContainer \
            -p:ContainerRegistry=ghcr.io \
            -p:ContainerImageTag=${{ github.sha }}

Принципы хорошего пайплайна:

  • Быстрая обратная связь. Держите PR-пайплайн в пределах нескольких минут; тяжёлое выносите в отдельные джобы/ночные прогоны.
  • Один артефакт через все среды. Собрали образ один раз, тегировали SHA коммита, продвигаем один и тот же бинарник dev → staging → prod. Не пересобирайте на каждую среду.
  • Иммутабельность и трассируемость. Тег = SHA коммита; всегда знаете, что именно в проде.

Релизные стратегии

  • Semantic Versioning для библиотек/NuGet-пакетов; инструмент MinVer/Nerdbank.GitVersioning выводит версию из git-тегов автоматически.
  • Blue-Green — две среды, переключение трафика; мгновенный откат.
  • Canary / поэтапная выкатка — новую версию сначала на 1–5% трафика, наблюдаем метрики, потом расширяем.
  • Feature flags (например, через Microsoft.FeatureManagement) — отделяют деплой от релиза: код в проде, но фича включается флагом. Позволяет катить чаще и безопаснее.

Общий принцип: деплой должен быть рутинным, обратимым и наблюдаемым событием, а не героическим ночным подвигом.

Безопасность цепочки зависимостей

Большинство кода в вашем приложении — не ваш, а из NuGet-пакетов. Это поверхность атаки.

  • Аудит уязвимостейdotnet list package --vulnerable --include-transitive в CI (см. пайплайн выше). Данные — из GitHub Advisory Database.
  • Lock-файлы + --locked-mode — воспроизводимость и защита от неожиданной подмены транзитивной версии (статья про тулчейн).
  • Dependabot / Renovate — автоматические PR на обновление зависимостей.
  • Проверка происхождения пакетов. Предпочитайте пакеты с подписью и от проверенных авторов; включите NuGet package signature validation. Опасайтесь тайпсквоттинга имён.
  • SBOM (Software Bill of Materials) — генерируйте перечень зависимостей для аудита и соответствия требованиям.
  • Секреты — никогда в коде/репозитории; сканеры секретов (gitleaks) в пре-коммит и CI. В проде — Key Vault / Secrets Manager.
  • Статический анализ безопасности — SonarAnalyzer, security-scan, GitHub CodeQL.

Безопасность — не отдельный этап в конце, а сквозная практика («shift left»): чем раньше поймали проблему, тем дешевле.

Управление зависимостями и версиями .NET во времени

Отдельная часть жизненного цикла — поддержание проекта в актуальном состоянии, чтобы он не превратился в легаси:

  • Планируйте обновление .NET. Сидите на LTS (.NET 8), закладывайте миграцию на следующую LTS в её окне поддержки. Обновление major-версии .NET обычно сводится к смене TargetFramework и прогону тестов — команда серьёзно относится к совместимости.
  • Инструмент апгрейда. Upgrade Assistant / dotnet upgrade помогает с миграцией старых проектов (в т.ч. с .NET Framework).
  • Держите зависимости свежими понемногу. Renovate/Dependabot и регулярные мелкие обновления дешевле, чем редкий болезненный «большой прыжок».
  • Читайте release notes. Каждая версия .NET приносит перф «бесплатно» — часто простой ребилд на новом рантайме ускоряет сервис на десятки процентов.

Технический долг по версиям — это риск безопасности (устаревшие рантаймы перестают получать патчи) и найма (мало кто хочет работать с мёртвым стеком). Обновление — не роскошь, а гигиена.

Документация как часть SDLC

  • API-контракты. ASP.NET Core генерирует OpenAPI-спеку; держите её актуальной, она — контракт с потребителями.
  • ADR (Architecture Decision Records) — короткие markdown-записи «что решили и почему». Спасают будущую команду от археологии.
  • README и runbook. Как запустить локально, как задеплоить, что делать при типовом инциденте. Runbook экономит часы во время сбоя в 3 часа ночи.
  • XML-doc комментарии (///) на публичном API библиотек — попадают в IntelliSense и генерируемую документацию.

Курированный список лучших ресурсов

Официальные (первоисточники)

  • learn.microsoft.com/dotnet — документация; образцовое качество, всегда актуальна.
  • devblogs.microsoft.com/dotnet — блог команды .NET; «почему» решений, ежегодные «Performance Improvements in .NET» от Stephen Toub.
  • github.com/dotnet — исходники runtime, ASP.NET Core, EF Core. Читать код BCL — лучший способ учиться.
  • .NET API browser — справочник по всему BCL.

Блоги экспертов

  • Stephen Clearyblog.stephencleary.com: абсолютный референс по async/await, ConfigureAwait, дедлокам, Channel.
  • Andrew Lockandrewlock.net: ASP.NET Core «в глубину», серия «ASP.NET Core in Action» (и одноимённая книга).
  • Steve Gordonstevejgordon.co.uk: внутренности ASP.NET Core, HttpClientFactory, производительность.
  • David Fowlergithub.com/davidfowl/AspNetCoreDiagnosticScenarios: обязательный AsyncGuidance.md — грабли async в проде от архитектора ASP.NET Core.
  • Nick ChapsasYouTube: Nick Chapsas: короткие практичные видео по современным фичам и производительности.
  • Konrad Kokosatooslowexception.com: память и GC.
  • Jimmy Bogardjimmybogard.com: архитектура, MediatR, DDD-подходы.
  • Vladimir Khorikoventerprisecraftsmanship.com: тестирование, DDD, Result vs исключения.
  • Milan Jovanovićmilanjovanovic.tech: архитектура, чистый код, практичные разборы.

Книги

  • «C# in Depth», Jon Skeet — как язык устроен изнутри.
  • «Dependency Injection Principles, Practices, and Patterns», Mark Seemann & Steven van Deursen — эталон по DI и архитектуре.
  • «Pro .NET Memory Management», Konrad Kokosa — всё про GC и память.
  • «ASP.NET Core in Action», Andrew Lock — веб-разработка на .NET.
  • «Unit Testing Principles, Practices, and Patterns», Vladimir Khorikov — как писать тесты, которые не мешают, а помогают.

Сообщество и новости

  • The .NET Docs Show и .NET Community Standup (стримы команды на YouTube).
  • Рассылки: The .NET Weekly (Milan Jovanović), .NET News (Cezary Piątek).
  • Reddit r/dotnet, r/csharp; конференции NDC, .NET Conf (бесплатная, онлайн).

Заключение курса

Вы прошли путь от установки SDK до эксплуатации наблюдаемого сервиса. Главное, что стоит унести:

  • Учите среду исполнения, а не только синтаксис — CLR и GC объясняют поведение.
  • Включайте всё, что двигает ошибки в компайл-тайм: nullable, анализаторы, TreatWarningsAsErrors.
  • Async — про освобождение потоков; уважайте CancellationToken и избегайте sync-over-async.
  • Держите домен чистым, зависимости — инвертированными, конфигурацию — типизированной.
  • Тестируйте пирамидой, наблюдайте тремя столпами, релизьте часто и обратимо.

Дальше — практика. Возьмите реальный сервис, пройдите весь цикл сами, читайте первоисточники из списка выше и код BCL. Так растёт инженер, а не только кодер.

Что дальше

Вернитесь к обзору курса, чтобы перечитать разделы, к которым захочется углубиться, или откройте официальную документацию learn.microsoft.com/dotnet и начните свой проект.

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов