пятница, 28 ноября 2014 г.

DevOps best practices: рекомендации по организации конфигураций в TeamCity

DevOps (Development + Operations)
Принимая участие в разработке нескольких сотен сборочных, деплойных и иных автоматических конфигураций для поддержки процессов разработки ПО, рано или поздно начинаешь находить в них и выделять общие решения, концепцию, архитектуру, схему взаимодействия конфигураций между собой. Предлагаю вам некоторые рекомендации в области разработки конфигураций, подходы и схему организации процессов сборки и тестирования ПО. Эти подходы были успешно опробованы мной и моими коллегами: Александром Паздниковым, Ярославом Акимовым и Алексеем Соловьёвым, для большого числа IT-проектов, на базе системы непрерывной интеграции TeamCity.

Частично вопросы организации процессов сборки и тестирования уже были рассмотрены в статье "TeamCity triggers & dependencies: построение процессов разработки и тестирования". В статье ниже приведена терминология основных понятий, используемых при описании конфигураций, рекомендуемый набор конфигураций для произвольного проекта, а также схема взаимодействия конфигураций для релизных и нерелизных сборок, деплоя, функционального тестирования. 


Терминология CI-процессов в TeamCity

Дадим определения основных понятий TeamCity, используемых при описании CI-процессов на различных проектах:

Проект (подпроект, группа проектов) - Project/Subproject в терминах TeamCity - это механизм TeamCity для организации иерархии проектов, группировки конфигураций, хранения шаблонов конфигураций, мета-раннеров, глобальных переменных и VCS для всех подпроектов.
Конфигурация (билд-, тест-, деплойная-, тулзовая-) - Build Configuration в терминах TeamCity - это описание действий, приводящих к требуемому результату: сборки проекта, инсталляции (деплоя) проекта на тестовых стендах, запуску авто-тестов, получению артефакта сборки, загрузки файлов в репозиторий Артифактория, запуску каких-либо вспомогательных инструментов и т. п.
Шаблон (темплейт) конфигурации - Build Configuration Templates в терминах TeamCity - это общая схема сборки или запуска множества конфигураций, унаследовавших этот шаблон. Любая конфигурация может быть создана на основе существующего шаблона, быть подключена к шаблону позже, а также шаблон можно извлечь из уже имеющихся конфигураций.
Раннер (билд-, тест-, деплойный-, тулз-) - это механизм запуска конфигурации, доступный пользователю TeamCity. Это web-интерфейс для проекта с кнопкой Run и окном запроса параметров запуска для сборки, деплоя, тестов или инструмента.
Мета-раннер - Meta-Runner в терминах TeamCity - это "раннер в раннере", произвольная конфигурация, сохраненная в виде одного отдельного шага, который затем возможно добавить к другим конфигурациям.
Промоутер - Build Promouter - специальная конфигурация или метараннер для "продвижения" сборки релиз-кандидата из тестового репозитория проекта (Projectname.snapshot) в репозиторий для протестированных сборок (Projectname, без постфикса .snapshot). Продвижение может выполняться вручную, либо автоматически, после прохождения определённого QA-группой набора авто-тестов.
Репозиторий проекта - VCS, VCS-root, Version Control System в терминах TeamCity - это описание настроек внешней системы контроля версий, поддерживаемой TeamCity. В дальнейшем VCS-root подключается к конкретной конфигурации и служит для автоматического check-in кода на стороне Агента TeamCity.
Репозиторий Артефактория - Artifactory repo - это выделенное хранилище сборок и иных артефактов проекта на контроллере Artifactory.Обычно там содержатся уже скомпилированные бинарные файлы, nuget-пакеты, zip-архивы со скриптами, PDB-файлы, то есть, готовые к дальнейшему тестированию программы и данные. 
Артефакт раннера - любые файлы, полученные в процессе работы раннера и сохранённые на контроллере TeamCity. Они доступны на вкладке Artifacts для конкретного запуска раннера и могут быть использованы в других конфигурациях через механизм зависимостей.
Билд-артефакт - как правило, это файл, архив, nuget-пакет или иной инсталляционный пакет, полученный в процессе запуска билд-конфигурации. Обычно билд-артефакты не хранятся в TeamCity в артефактах раннера, а выкладываются в репозиторий Артефактория.
Контроллер Teamcity - это выделенный сервер, который обеспечивает создание конфигураций, их запуск и хранение результатов. Предоставляет интерфейс для запуска конфигураций и анализа результатов.
Агент TeamCity (билд-, тест-, деплойный-) - это сервис, устанавливаемый на выделенной машине, который обеспечивает исполнение шагов конфигураций и отправку данных о результатах на контроллер TeamCity. Агенты для билд-серверов обычно полностью находятся на поддержке группы DevOps, а для тест-агентов и деплойных агентов чаще всего используются машины, предоставленные самими командами и находящиеся на поддержке у них.
Релизная ветка - ветка в репозитории, которая имеет следующий формат:
*release*majorver.minorver* или *release*majorver.minorver.patchver*
где majorver, minorver и patchver - числа версий мажора, минора и патча, разделённые точками, вместо * могут подставляться любое количество алфавитно-цифровых символов, слеш и дефис. Примеры классических имён релизных веток: release-7.1, release/6.0, support/release-7.0. Ограничения:
- в имени релизных веток нельзя использовать пробелы и спец-символы,
- имена никаких других фича-веток, не должны содержать части имён релизных веток,
- в имени релизной ветки точки могут использоваться только для разделения чисел версий.
Нерелизная или фича-ветка - любая ветка в репозитории, которая не соответствует формату релизной ветки. Примеры: develop, master, feature/custom_1.
Информационная конфигурация, CI INFO builder - это вспомогательная конфигурация, запускаемая для сборки любой нерелизной ветки. Состоит только из шагов сборки и юнит-тестирования модулей кода. Отличается от других конфигураций тем, что никакие артефакты, получаемые в процессе сборки, обычно не сохраняются ни на контроллере TeamCity, ни во внешних репозиториях. Запуск такой конфигурации, как правило, настраивается автоматически на каждый push в репозиторий в любую нерелизную ветку. Значение имеет только факт успешной сборки и прохождение всех юнит-тестов. Используется разработчиками для мониторинга изменений кода в своих фича-бранчах.
Девелоперская конфигурация, developer's builder - это конфигурация, запускаемая для сборки любой нерелизной ветки. Состоит из шагов сборки, юнит-тестирования, подготовки артефакта и выкладывания его в специальный репозиторий Артефактория для дальнейшего функционального тестирования. Обычно такой репозиторий имеет постфикс к имени проекта: Projectname.snapshot. Такие сборки используются только для срочной проверки и тестирования новых фич. Они не выходят за пределы команды: никогда не попадают в релизы, в общие интеграционные сборки и инсталляционные пакеты. Запуск такой конфигурации, как правило, осуществляется вручную с возможностью выбора произвольной нерелизной ветки для сборки. Имя билд-артефакта всегда формируется по шаблону: ProjectName.Major.Minor.BuildNumber-BranchName.Extension.
Релизная конфигурация, release builder - это конфигурация, запускаемая для сборки любой релизной ветки. Состоит из шагов сборки, юнит-тестирования, подготовки артефакта и выкладывания его в специальный репозиторий Артефактория (с постфиксом .snapshot) для дальнейшего функционального тестирования. Артефакт при этом считается релиз-кандидатом. В случае успешного прохождения функциональных авто-тестов и тестирования со стороны QA-группы, только сборки этой конфигурации могут быть продвинуты через промоутер в репозиторий для протестированных сборок (без постфикса .snapshot). После продвижения артефакт может считаться успешным релизом. Запуск релизной конфигурации, как правило, осуществляется автоматически на каждый push в любую релизную ветку. Имя билд-артефакта всегда формируется по шаблону: ProjectName.Major.Minor.BuildNumber.Extension.
Деплойная конфигурация - это конфигурация, которая позволяет получить любой собранный артефакт из репозитория Артефактория и задеплоить (распаковать, подготовить, установить, запустить) его на указанном тестовом стенде. После успешного деплоя проекта на стенде, все его сервисы должны быть полностью готовы к использованию человеком или к прохождению наборов BVT, Smoke, функциональных, нагрузочных, интеграционных и прочих видов авто-тестов.
Релизные авто-тесты - это выделенная группа конфигураций, которые содержат в себе автотесты, выбранные QA-группой: как минимум, BVT, Smoke. Обычно тесты запускаются автоматически после успешной релизной сборки и деплоя проекта на тестовых стендах. Они должны завершаться за приемлемое время и позволять QA-группе и разработчикам принимать решение о продвижении релизной сборки через конфигурацию промоутер в репозиторий для успешно протестированных сборок.



Типичная схема взаимосвязи конфигураций

Схема взаимодействия конфигураций укладывается в цепочку: Build - Deploy - Testing - Promotion


Рекомендуемый для каждого проекта набор конфигураций:


1. Информационная конфигурация - для определения возможности сборки и получения результатов по юнит-тестам после каждого изменения кода разработчиками. Должна автоматически запускаться на каждый push в нерелизную ветку.

2. Девелоперская конфигурация - для возможности быстрого получения разработчиками артефакта с новой фичей, которую можно передать тестировщикам в QA-группу. Должен быть обеспечен ручной запуск сборки из нерелизных веток с указанием требуемых параметров.

3. Релизная конфигурация - для полностью автоматического получения артефактов из релизных веток.

4. Деплойная конфигурация - для инсталляции сервисов и подготовки тестовых стендов. 

5. Конфигурации релизных автотестов - содержащие, как минимум, BVT и Smoke наборы авто-тестов.

6. Конфигурация промоутер - для продвижения релизных сборок.



Взаимосвязь конфигураций в TeamCity:





Обобщенная иерархия конфигураций

Рекомендуемая обобщенная иерархия для всех проектов в TeamCity включает в себя следующие конфигурации:

<ROOT project> - головной проект, содержащий все другие проекты. Используется для объявления глобальных переменных, шаблонов и мета-раннеров необходимых на всех проектах. С ним работает только команда DevOps.
  • <Название проекта> - общее имя проекта, над которым работает команда. Содержит в себе все подпроекты, относящиеся к сборке, деплою и тестированию.

    <Название подпроекта> - имена подпроектов, в случае, если разрабатываемый продукт состоит из нескольких отдельных частей или модулей.
    • Builds - все сборочные конфигурации должны размещаться здесь. Они также могут быть разбиты на подпроекты, в случае, если требуется кросс-сборка проекта под различные ОС.
      • Developer's builds - только девелоперские сборки из нерелизных веток:
        • <Префикс имени собираемого (под)-модуля> builder CI INFO <возможный постфикс с дополнительной информацией: разрядность, ОС и т. п.> - имя сборщика для информационных нерелизных билдов.
          Например: ProjectName CI INFO builder - win32.
        • <Префикс имени собираемого (под)-модуля> builder <возможный постфикс с дополнительной информацией: разрядность, ОС и т. п.> - имя сборщика для нерелизных билдов, который создаёт артефакт и выкладывает его в репозиторий Артифактория.
          Например: ProjectName builder - win32.
        • Release builds - только автоматически собираемые релизные ветки:
          • <Префикс имени собираемого (под)-модуля> release builder <постфикс дополнительной информации: разрядность, ОС и т.п.> - имя сборщика для релиз-кандидатов, которые затем автоматически деплоятся и тестируются при помощи авто-тестов из группы релизных тестов.
            Например: ProjectName release builder - win32.

            Здесь же могут находиться конфигурации-промоутеры, если они выделены отдельно для проекта. Формат имени для таких конфигураций: <Префикс имени собираемого (под)-модуля> build promouter
            Например: ProjectName build promouter.
      • Deploy - здесь должны храниться все деплойные конфигурации, которые предназначены для установки и настройки сборки продукта на тестовом стенде. Они также могут быть разбиты на подпроекты. Формат имени для таких конфигураций: <Префикс имени (под)-модуля> deploy runner
        Например: ProjectName deploy runner.

        Здесь же могут располагаться конфигурации-индикаторы корректности деплоя на тестовых стендах, проверки запущенных сервисов и т. п.
        Например: ProjectName services start indicator, ProjectName deploy indicator.
      • Tests - здесь содержатся билд-конфигурации для всех видов функциональных, интеграционных и нагрузочных тестов.

        На имена тест-раннеров нет ограничений, главное, чтобы они отражали суть запускаемых тестов.
        Например: BVT, Test case runner, Test Suite runner, Load runner и т.д.

        Тестовые конфигурации, которые запускают другие конфигурации, должны содержать префикс
        Runner.Например: Runner: All functional testsuites for ProjectName.
          • Release tests - в этом подпроекте должны содержаться тест-раннеры для тех наборов тестов, которые QA-группа выделила для автоматической проверки релиз-кандидатов сборок и деплоя.
            Например: Release Smoke-tests.

            Следующие подпроекты для тестов создавать не обязательно, только если вы хотите сгруппировать в них множества конфигураций:
            • Functional testing - возможное имя подпроекта для тест-раннеров функциональных тестов.
            • Load testing - возможное имя подпроекта для тест-раннеров нагрузочных тестов.
            • UI testing - возможное имя подпроекта для тест-раннеров тестов интерфейса.
          • Tools - здесь должы содержаться раннеры для всевозможных вспомогательных инструментов: запуск произвольных скриптов по расписанию, анализ данных по некоторому алгоритму, инструменты для сравнения отчетов и т. п.
            Например: Scanning tool, Diff models, Checking parameters.
          • Competitive Analysis - здесь могут размещаться билд-конфигурации для проведения конкурентного анализа и сравнения с другими продуктами. Это необязательная группа подпроектов.
            Например: Compare ProjectName with Product_XXX.
          Проект, построенный согласно предложенной схеме, в TeamCity будет выглядеть примерно следующим образом:


          Различные проекты, разумеется, могут содержать лишь некоторые из предлагаемых конфигураций. Организация конфигураций согласно указанной выше схеме подходит для большинства типичных проектов. Кроме того, она достаточно гибкая и расширяемая, в том числе для нестандартных проектов. А благодаря унификации схемы Build - Deploy - Testing - Promotion для всех проектов, отделу DevOps гораздо легче поддерживать и разрабатывать такие конфигурации.