Continuous Delivery: Продолжение

в 11:28, , рубрики: .net, ASP, C#, continuous delivery, continuous integration, teamcity, Веб-разработка

2 года назад в статье Continuous Delivery & Sitecore: наша реализация я представлял нашу систему автоматической доставки веб-приложений основанных на Sitecore. Это были первые маленькие шаги в направлении мира полной автоматизации.

За прошедшее время проект не только не умер, но разросся и заматерел. Более того, он все еще развивается и вбирает в себя все больше и больше инструментов и возможностей. Пожалуй, единственное, что осталось без изменений – это система контроля версий (GIT) и система ветвления.

Крупные изменения, постигшие проект (на каждом я остановлюсь подробно):

  • Доставка через SSH является основной только для проектов, живущих на Linux и Windows 2003. Проекты, которые хостятся на Windows 2008 R2 и выше, используют Web deploy.
  • Так как помимо веб-приложений на CMS Sitecore, мы стали разрабатывать на Umbraco, Episerver и просто ASP.NET веб-приложения, сервисы и приложения – теперь CD работает также и с ними
  • Внутренняя Nuget галерея и обновление разрабатываемых нами open-source библиотек на Nuget.org также доставляется при помощи TeamCity

SSH доставка Linux php проектов

На самом деле тут все проще простого. Так как PHP не требует компиляции, то доставка заключается в том, чтобы забрать исходники из Гита, и, подцепившись по SSH к целевому серверу – залить их.
В TeamCity для это есть специальный плагин – deploy-runner, который, собственно говоря, и занимается всей доставкой. В будущем, к данному типу билдов мы планируем прицепить интеграционные и юнит тесты. На данный момент используются только для внутреннего тестирования.

Nuget, SymbolSource, упаковка и обновление

Внутри нашей сети мы развернули Nuget галерею (форк от https://github.com/NuGet/NuGetGallery), SymbolSource сервер для этой галереи (http://www.xavierdecoster.com/setting-up-your-own-symbolsource-server-step-by-step). Так как это также веб-приложения – Teamcity отвечает не только за их наполнение, но и за их обновления (следит за нашими форками репозиториев, и по обновлении форка – доставляет обновления на веб-приложение при помощи описанных далее шагов).
Также TeamCity отвечает за публикацию Nuget пакетов в галерею (как внутреннюю, так и внешнюю), обновляя пакеты при помощи встроенных в TeamCity инструментов для упаковки и публикации пакетов. Также каждый пакет публикуется в соответствующую галерею SymbolSource (внутреннюю или Symbolsource.org).

MsBuild, MsDeploy и все что крутится вокруг...

Собственно говоря, сама доставка и все, что с ней связано.
Хотелось бы сказать несколько слов о MsDeploy и о причине ухода от SSH. Несмотря на то, что доставка по SSH происходит довольно быстро, подготовительные операции требуют много времени и дорогих дисковых операций. Плюс ко всему, мы всегда в любой билд должны или сами заниматься дифференциацией файлов для доставки (с тем, чтобы уменьшить размер отправляемого пакета), или же всегда доставлять все приложение (что не совсем позитивно отражается на публикуемом пакете). Если же взять MsDeploy, который вызывается средствами Visual Studio или MsBuild – то доставкой файлов в веб-приложение занимается MsDeploy, он же оценивает – нужно ли обновлять/удалять/оставлять конкретный файл, что положительно отражается на скорости доставки. Также, в конфигурации по умолчанию, MsDeploy на себя берет и наведение порядка – если в IDE файл был удален/исключен – то и в целевом веб-приложении он не нужен.
Для обеспечения стабильной и управляемой работы доставки – весь процесс крутиться вокруг MsBuild движка, поведением которого управляет набор импортируемых проектов (targets файлов), унифицированных по выполняемым процедурам и отличающихся лишь по типу проекта (Sitecore, Umbraco, Episerver или веб-приложение без CMS).
На target файлах я остановлюсь поподробнее…

Sitecore

Sitecore.targets файл описывает следующие шаги:

  1. Подготовка приложения к доставке логических структур в базу данных – публикация конфигурационного файла, который разрешает использование любых символов и отключает наиболее ресурсоемкие операции, проводимые Sitecore при паблишинге. Этот шаг требует перезапуска приложения и потому вызывается только в том случае, если у нас есть что доставлять в базу данных
  2. Оживление приложения при помощи Wget после рестарта (по сути, просто запрос главной страницы сайта)
  3. Добавление сборки последней версии, реализующей CI в приложение
  4. Статическую трансформацию web.config файла, для уборки мусора, который остается в temp папке после доставки, средствами самого Sitecore
  5. Импорт sharedtargets файла, который отвечает за все остальные операции во время билда, при помощи своих таргетов. А очередность выполнения целей в sharedtargets файле управляется при помощи AfterTargets и BeforeTatgets директив.
  6. Какие папки удалять во время билда приложения (список можно расширять в csproj файле самого приложения) – это необходимо из-за того, что мы не используем самоочистку файлов (SkipExtraFilesOnServer = true), для того, чтобы не очищать контентные файлы, потенциально созданные приложением

EpiServer

Episerver.targets файл описывает следующие шаги и требования к доставке:

  1. Добавление сборки последней версии, реализующей CI в приложении
  2. Импорт sharedtargets файла, который отвечает за все остальные операции во время билда, при помощи своих таргетов. А очередность выполнения целей в sharedtargets файле управляется при помощи AfterTargets и BeforeTatgets директив.
  3. Какие папки удалять во время билда приложения

Umbraco

Umbraco.targets файл описывает следующие шаги и требования к доставке:

  1. Добавление сборки последней версии, реализующей CI в приложении
  2. Какие папки удалять во время билда приложения
  3. Импорт sharedtargets файла, который отвечает за все остальные операции во время билда, при помощи своих таргетов. А очередность выполнения целей в sharedtargets файле управляется при помощи AfterTargets и BeforeTatgets директив.
  4. Обновление версии приложения в ClientDependency.config (Umbraco хитро кеширует статические ресурсы)

Сам билд

Все билды унифицированы и могут отличаться лишь по требованиям CMS либо потребителя. Тут я постараюсь разобрать все шаги по порядку (в скобках в начале описания шага буду указывать, если данный шаг специфичен для какого-то таргета)

  1. Информационный e-mail, отсылаемый группе о том, что билд запускается. Содержит в себе следующую информацию:
    — для какого проекта и какой среды запускается билд
    — кто запустил билд
    — какие изменения включены в билд (комментарий к чекинам в репозиторий, если комментарий начинается с #номер – то #номер обрамляется ссылкой на запрос в нашей трекинговой системе)
  2. (Sitecore) Проверка, есть ли в билде пекеджи (логические элементы базы данных Sitecore для доставки). Если есть – обновляем приложение (положить специальный конфигурационный файл, обновит CI сборку) и оживляем ее.
  3. (Sitecore) Доставка пекеджей при помощи WCF сервиса
  4. (Sitecore) Паблиш при помощи WCF сервиса
  5. (Microsoft Network Load Balancer) Если приложение хостится на нескольких серверах, и траффик балансируется при помощи Microsoft NLB – то в этом шаге мы выключаем приложение из балансировки при помощи Drainstop (новый траффик на приложение не попадает. Заканчиваем обслуживание тех пользователей, что были на момент начала Drainstop)
  6. Доставка App_offline.htm в корень приложения (чтобы пользователи не пугались ошибок) и отключение сервисов облачного мониторинга (чтобы Uptime не падал, так как ASP.NET приложение с App_offline.htm в корне, хоть и демонстрирует красивую картинку и надпись, но возвращает HTTP статус 503). Какие сервисы мониторинга отключать — контролируется параметрами билда
  7. Nuget restore – несмотря на то, что можно и нужно включать Nuget restore на уровне солюшена, некоторые сборки меняют сам процесс билда (например, Microsoft.Bcl.Build)
  8. MsBuild Publish – тут то и происходит вся магия...
    Я не буду описывать все, что делает MsBuild, а лишь опишу те изменения, что вносятся sharedtargets.target файлом.
    1) Если специфичный для приложения target файл добавляет CI файлы – они добавляются в самом начале (мы их виртуально помечаем как Content c мета данными CopyToOutputDirectory=Always)
    2) AddVersionTxt – добавляет в корень веб-приложение файл version.txt, который содержит в себе номер билда и дату (удобно для тестеров и третьих лиц – что сейчас опубликовано). В Sitecore оно еще и в информации о приложении видно
    3) (Sitecore) Статический трансформ для удаление файлов из temp папки
    4) Еncrypt – если в приложении в конфигурируемую папку добавлен RSA ключ, и флаг EncryptWebConfigOnTeamcityBuild=true, то во время билда TeamCity зашифрует appSettings и connectionStrings секции в web.config (можно добавить еще секции на уровне csproj файла приложения)
    5) Если в приложении используется дополнительная база данных – то вызывается SqlUpdaterSupportTarget. Так же как и второй шаг, он проверяет, были ли изменения в сконфигурированной папке и если были – средствами MsDeploy обновляет сконфигурированную в TeamCity базу данных. Умеет работать как с MSSQL, так и с MySQL. Пока что умеет обновлять лишь одну базу данных. Если их несколько – надо добавлять дополнительный шаг перед удалением App_offline
  9. (EpiServer) Так как Episerver складывает файлы, необходимые для CMS вне рута веб приложения в папку AppData и ходит к ним через VirualPathProvider – мы должны проверить, были ли изменения в этой папке, и если были – то тоже залить их на сервер
  10. Удаление App_offline, оживление приложения и включение сервисов мониторинга обратно
  11. Оживление веб-приложения – Wget пробегает по всем страницам первого уровня сайтов, указанных в конфигурации билда.
    В скором времени, вместо конфигурации билда, планируется эту задачу вынести в WCF сервис.
    Также, на этом шаге, сохраняются числовые значения (сколько времени на него понадобилось). В дальнейшем будем проводить весьма приблизительный анализ производительности веб-приложения (ламерская, но метрика :) )
  12. Анализ опубликованного web.config при помощи OWASP (репорт доступен в отчетах Teamcity)
  13. Стандартные проверки веб-приложения и отсылка email с результатами проверок и билда группе.
    На данный момент, в стандартные проверки входит только проверка наличия robots.txt, его анализа при помощи парсера https://code.google.com/p/robotstxt/, а также валидация sitemap.xml.
    Этот шаг должен и будет расширяться различного рода интеграционными и юнит-тестами

Помимо веб-приложений, мы также разрабатываем дополнительные сервисы для Windows. И их также надо доставлять…
Для этого тоже есть отдельный билд, состоящий из следующих шагов:

  1. Nuget Restore
  2. Билд при помощи Visual Studio (Visual Studio (sln) runner)
  3. Остановка и удаление сервисов на целевом сервере при помощи MsDeploy runCommand провайдера
  4. Заливка файлов при помощи MsDeploy
  5. Установка сервисов на целевом сервере при помощи MsDeploy runCommand

Ну и еще один билд необходим, чтобы TeamCity построил для себя все те инструменты, которые описаны выше. Они все собраны в один солюшен, и по его изменению, запускается билд, состоящий из следующих шагов:

  1. Nuget Restore
  2. Visual Studio Build
  3. Powershell скрипт, который раскладывает результаты шага два по всем агентам

Помимо данных билдов, осуществляющих доставку кода, существует еще один TeamCity билд — не имеющий отношения к доставке кода, а являющийся просто сервисным. Он состоит из двух шагов и единственная его цель — вызвать recycle процесса, обслуживающего веб-приложение. Нужен он для того, чтобы иметь возможность быстро перезапустить веб-приложение

  1. MsBuild, при помощи встроенного в MsDeploy провайдера recycleApp, вызывает рестарт приложения
  2. Wget в режиме паука загружает первую страницу веб-приложения (для его скорейшего оживления)

Данный «билд» вызывается не часто, так как это крайняя мера.

Визуализация

Как финальный штрих, при помощи open-source тула Gource, я добавил визуализацию разработки CI:

Автор: akuryan

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js