Continuous Delivery: Продовження

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, що відсилається групі про те, що білд запускається. Містить таку інформацію:

- для якого проекту і якого середовища запускається білд

- хто запустив білд

- які зміни включено до білда (коментар до чекін у репозиторій, якщо коментар починається з # номер - то # номер обрамляється посиланням на запит у нашій трекінговій системі)

  1. (Sitecore) Перевірка, чи є в білді пекеджі (логічні елементи бази даних Sitecore для доставки). Якщо є - оновлюємо програму (покласти спеціальний конфігураційний файл, оновить CI збірку) і оживлюємо її.
  2. (Sitecore) Доставка пекеджів за допомогою WCF сервісу
  3. (Sitecore) Пабліш за допомогою WCF сервісу
  4. (Microsoft Network Load Balancer) Якщо додаток хоститься на декількох серверах, і трафік балансується за допомогою Microsoft NLB - то в цьому кроці ми вимикаємо додаток з балансування за допомогою Drainstop (новий трафік на додаток не потрапляє. Закінчуємо обслуговування тих користувачів, що були на момент початку Drainstop)
  5. Доставка App_offline.htm в корінь програми (щоб користувачі не лякалися помилок) і відключення сервісів хмарного моніторингу (щоб Uptime не падав, оскільки ASP.NET додаток з App_offline.htm в корені, хоч і демонструє красиву картинку і напис, але повертає HTTP статус 503). Які сервіси моніторингу відключати - контролюється параметрами білда
  6. Nuget restore - незважаючи на те, що можна і потрібно включати Nuget restore на рівні солюшену, деякі збірки змінюють сам процес білда (наприклад, Microsoft.Bcl.Build)
  7. MsBuild Publish - тут те і відбувається вся магія...

Я не буду описувати все, що робить MsBuild, а лише опишу ті зміни, що вносяться sharedtargets.target файлом.

1) Якщо специфічний для програми target файл додає CI файли - вони додаються на самому початку (ми їх віртуально позначаємо як Content з метою даними CopyToOutputDirectory = Always)

2) AddVersionTxt - додає в корінь веб-додаток файл version.txt, який містить в собі номер білда і дату (зручно для тестерів і третіх осіб - що зараз опубліковано). У Sitecore воно ще й в інформації про додаток видно

3) (Sitecore) Статичний трансформ для вилучення файлів з temp теки

4) Encrypt - якщо у програмі до налаштованої теки додано RSA ключ, і прапор EncryptWebConfigOnTeamcityBuild = true, то під час білда TeamCity зашифрує appSettings і connec  Strings секції у web.config (можна додати ще sprotings)

5) Якщо в програмі використовується додаткова база даних - то викликається SqlUpdaterSupportTarget. Так само як і другий крок, він перевіряє, чи були зміни в сконфігурованій папці і якщо були - засобами MsDeploy оновлює сконфігуровану в TeamCity базу даних. Вміє працювати як з MSSQL, так і з MySQL. Поки що вміє оновлювати лише одну базу даних. Якщо їх декілька - треба додавати додатковий крок перед видаленням App_offline

  1. (EpiServer) Оскільки Episerver складає файли, необхідні для CMS поза рутою веб програми до теки AppData і ходить до них через VirualPathProvider - ми повинні перевірити, чи були зміни в цій теці, і якщо були - то теж залити їх на сервер
  2. Видалення App_offline, пожвавлення програми і включення сервісів моніторингу назад
  3. Пожвавлення веб-додатку - Wget пробігає по всіх сторінках першого рівня сайтів, зазначених у конфігурації білда.

Незабаром, замість конфігурації білда, планується це завдання винести в WCF сервіс.

Також, на цьому кроці, зберігаються числові значення (скільки часу на нього знадобилося). Надалі будемо проводити досить приблизний аналіз продуктивності веб-додатку (ламерська, але метрика:) )

  1. Аналіз опублікованого web.config за допомогою OWASP (репорт доступний у звітах Teamcity)
  2. Стандартні перевірки веб-програми і відсилання 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: