Хотелось бы поделиться небольшим опытом автоматизации и стандартизации процесса разработки.
Статья не претендует на правду, но надеюсь, что будет интересным чтением к концу рабочей недели.
В начале было слово
Для начала расскажу немного о том, как все начиналось:- Репозиторий, в котором была только одна основная ветка.
- 5 проектов, которые должны взаимодействовать в единой экосистеме.
И еще несколько находятся в пути.
- Постоянно расширяющиеся требования, приводящие к необратимым изменениям протокола связи между всеми компонентами (не лучшая ситуация, но уже случалось).
- Каждый из проектов имел свой формат версии.
Некоторые основывались на редакции, другие на дате, третьи на том и другом.
- Отсутствие какой-либо согласованности между всеми компонентами (она была только на словах).
- Отсутствие какой-либо автоматизации процессов (она была, но незначительная).
- Отсутствие единого репозитория для всех дистрибутивов (некоторые хранились в svn, другие в Track Studio, третий каждый раз пересобирался из исходников (забавно было наблюдать, как тестировщики выгружали исходники приложений из svn и делали make clean all, чтобы получить новый бинарник для тестирования)).
Вначале было структурирование.
Самой большой проблемой было отсутствие каких-либо механизмов контроля согласованности функциональности между компонентами системы.
Не существовало ни одного критерия, на основании которого можно было бы с уверенностью сказать, что два компонента системы, взятые в какой-то момент времени, согласуются друг с другом.
Функционально согласованными мы называем компоненты, которые общаются друг с другом на одном языке и одной версии протокола.
В нашем случае версия протокола также тесно переплетена с бизнес-логикой.
Точнее, никакую новую бизнес-логику невозможно внедрить без изменения или расширения протокола.
В ходе долгих споров о том, «как правильно запускать svn», был выбран вариант с фиксацией тегов и сформулирован ряд требований/правил, которые следует соблюдать: Ствол
- может не совпадать по функциональности
- не подлежит ручному комплексному тестированию
- не подлежит внедрению в производство или объединению в филиалы
- все компоненты функционально согласованы
- функционал не меняется
- участвует в основном процессе тестирования
- После тестирования может быть помечен как Производство.
- Может быть заморожен и забыт (удален) после функционального тестирования.
- Исправление ошибок зависает в багажнике
- Из Trunk прошиваются только критические ошибки, выявленные в более ранних версиях.
Наши теги не являются такими тегами.
Но по сути они ближе к понятию «тег», чем к понятию «бранч».
На обсуждении был другой формат сопровождения SVN — вести основную разработку в ветках.
То есть.
если у нас есть серьезное изменение, то мы создаем отдельную ветку, внедряем туда это изменение и сливаем его в транк.
При этом ствол всегда должен быть устойчивым, чтобы в любой момент времени можно было взять все компоненты системы и они были как минимум согласованы по функционалу, а как максимум готовы к производству.
В нашем случае это не выглядит жизнеспособным.
Потому что иногда одно серьезное изменение может возникнуть в момент реализации другого.
Тогда нам пришлось бы создать для него отдельную ветку и переключиться на нее.
Проблемы начались бы в тот момент, когда нужно было бы объединить две ветки в ствол.
У нас очень длинный цикл разработки, и процесс перехода с версии на версию еще не опробован.
Поэтому, выпуская наш продукт для публичного тестирования, мы хотели бы иметь возможность вносить «горячие» исправления.
Но без наличия тега (ветви) для каждой финальной версии это было бы невозможно.
У нас также нет возможности сказать, что «это будет исправлено в следующей версии».
Далее в статье я буду использовать термин «тег» именно в том значении, которое я описал выше.
Срезаем скальпы
Теги были бы бесполезны, если бы все их компоненты не были функционально согласованными.Узким местом в данном случае является момент времени, когда мы отрезаем скальп и создаем метку.
Как правило, на одной из планировок мы решаем, что в течение ближайшей недели должны подготовить ствол для создания тега.
То есть каждый из проектов должен прийти в состояние, когда он функционально согласуется со всеми компонентами, с которыми он непосредственно взаимодействует. После этого создаем тег.
Что идет на тестирование.
Мы называем тег в специальном формате MAJOR_NUM.MINOR_NUM.
Формат единой версии
Следующим важным шагом было введение критерия, на основании которого мы могли бы с уверенностью сказать, что эти два компонента согласуются друг с другом.Мы решили, что этим критерием будет версия.
В этом случае сама версия должна содержать информацию, на основании которой можно понять, что два компонента согласованы.
Формат версии: MAJOR_NUM.MINOR_NUM.REVISION. Те.
первая часть версии также является номером тега.
И мы знаем, что все компоненты в теге согласованы.
Указание сразу двух цифр в имени тега позволяет сделать нормальный переход между основными версиями, т.е.
вместо 1.1.х, 1.2.х, 1.3.х, 2.4.х , у нас будет 1.1.х, 1.2.х, 1.3.х, 2.1.х .
Номер версии сохраняется и используется как обычно.
Это номер версии каждого отдельного компонента, а не только последняя версия тега.
Потом пришла автоматизация
Следующим шагом стал процесс внедрения CI (непрерывной интеграции).Выбор пал на, как мне кажется, известную CI-систему Jenkins. Выбор был между Cruise control, с которым у меня остался не самый приятный опыт, Team City, платным за обычное использование, и самим Jenkins, который бесплатен, широко распространен и хорошо документирован.
Фактор бесплатности был важен, так как страшно просить у начальства деньги на то, что не гарантированно приживется.
Я твой господин, ты мой раб
Компоненты нашей системы очень разнообразны и на данный момент используют 3 платформы для сборки: windows, linux и mac os. Получается один мастер и 2 слейва (больше не хочу повторять слово «слейв»).Вопрос где сделать мастер не возник, естественно на линуксе.
Была развернута первоначальная конфигурация из одного ведущего устройства (Linux) и одного ведомого устройства (Windows).
Начался процесс автоматизации сборки всех наших комплектующих.
В ходе работы уже появился тег 1.1 и количество задач в Jenkins превысило 10. И тут начались проблемы.
Однажды Дженкинс разбился.
Мы его подняли, он снова упал.
Снова.
И он продолжал падать, независимо от того, как мы запускали его через Tomcat или как сервис.
Независимо от машины JAVA, откройте JDK или SUN java. Независимо от текущей версии.
Вернее, разбился не сам Дженкинс, а JAVA-машина, на которой он разбился.
Я даже зарегистрировал отдельную ошибку в их баг-трекере ( ДЖЕНКИНС-16199 , хотя на этом все и заглохло).
Потратив полторы недели на то, чтобы понять, что происходит или хотя бы почему, было решено перенести мастера на систему Windows. И о чудо, в той же конфигурации всё стало стабильно работать.
Со временем количество задач увеличилось вдвое, но все продолжает работать.
В результате окончательная структура выглядит так: Мастер на Windows, два Слейва, на Linux и MacOS взаимодействие по SSH через публичные ключи.
Об имплантатах
Мы расширили стандартную поставку Jenkins следующими плагинами: Копировать плагин артефакта — Мы используем его для использования артефакта из одной сборки в другой.Есть один простой момент, где можно оступиться.
Если сохранить такой артефакт в одном из заданий
А в другом, используя этот плагин, загрузите этот арт
Тогда следует как минимум указать путь к нему так же, как и в первом случае, и не помешало бы установить опцию «Свести каталоги», чтобы отбрасывать ненужные пути и копировать только сам арт в то место, куда вам нужно.
это.
Плагин установки описания Jenkins — Позволяет указать некоторую информацию о каждой сборке в поле «Описание сборки».
Те задачи, у которых есть версия, отображают ее там.
Плагин дополнительных столбцов — позволяет добавить в представление поле «Описание сборки».
Публикация через SSH — Отличный плагин для загрузки файлов и выполнения команд на удаленной машине.
Правда, мы его пока не используем в связи с тем, что автотестирование еще не налажено.
Недостаток этого плагина в том, что он требует предварительной настройки всех SSH-соединений и в каждой задаче четко указано, какое соединение использовать на этапе ее создания.
Плагин Python — некоторые этапы сборки написаны на Python, потому что так проще.
В том числе есть отдельная задача, которая делает практически все то же самое, что и Публикация через SSH но позволяет только на лету настроить параметры доступа к удаленной машине.
Интеграция XCode — используется для сборки проекта на MacOS. Нам пришлось немало потрудиться, чтобы иметь возможность делать сборки для разных версий iOS. В результате машине сборки было разрешено использовать команду sudo xcode-select -switch без ввода пароля.
Особый, черный, магический
Я уже упоминал о необходимости удаленного заполнения и выполнения команд, которую плагин решает практически идеально.Но что не позволяет напрямую указывать нужную цель для каждого процесса сборки.
У нас есть свой установщик, несколько тестеров и несколько станков.
Многим людям лень перетаскивать этот файл к себе и что-то с ним делать для установки продукта.
Для этих целей была создана цепочка задач «Удаленное развертывание».
И так, что она может сделать: Подобрать установщик из тега, указанного пользователем Установите его на машину, указанную пользователем.
вот как это выглядит
Эта задача параметризована.
Параметры TAG, HOST, USER, DEPLOY_DIR, OPENSSL_DIR, никакой магии здесь нет, обычные строки.
JOBS_NUMBER — «Селектор сборки для копирования Atrifact», позволяет указать, какую версию сборки брать, последнюю успешную или конкретный номер или что-то еще.
ПАРОЛЬ — параметр типа «Параметр пароля» — закрывает пароль звездочками.
Так из требуемой задачи выбирается нужная сборка
Просмотр настроек
Представления в Jenkins — это средство настройки отображения проектов.Мы удалили один столбец и добавили «Описание сборки» для представлений Trunk и Tag_X. Мы хотели, чтобы версия Jenkins по умолчанию была такой же.
Но Дженкинс не допускает подобных манипуляций со своим основным видом.
Вместо этого вы можете создать свое собственное представление (по умолчанию), добавить в него все проекты с помощью маски .
* и сделать это представление представлением по умолчанию.
Стреляем холостыми
У нас есть специальный скрипт для создания версии и всех возможных ее вариаций.Поначалу он появлялся в каждом из проектов, нуждавшихся в подобном функционале.
Через некоторое время ставим его в одно место и куда надо тянем как внешнюю зависимость.
А потом случился фейл Epic, когда его случайно поправили в одном из проектов, где было пристрастие.
В Дженкинсе на реконструкцию выстроились 15 проектов, простаивающих на реконструкции.
Первое, что пришло в голову — заблокировать файл для изменений.
Мы добавили в файл свойство Needs-lock и заблокировали его в специальной сборке пользователя (svn lock).
Но есть лучшее решение.
Намного лучше.
Jenkins позволяет вам ввести фильтрацию перед запуском сборки, инициированной изменением репозитория.
Он находится в разделе «Управление исходным кодом -> Дополнительно».
Нас интересует параметр «Исключенные регионы», в котором можно указать изменения, в каких файлах и каталогах следует игнорировать.
К месту задержания
На этом моя история заканчивается.На данный момент я уже покинул место работы, где был получен этот опыт и написана данная статья, поэтому вряд ли смогу ответить на какие-либо вопросы, которые могут возникнуть по поводу деталей и настроек.
Спасибо за внимание.
Благодарности
ФримИнк , запп за корректуру статьи Теги: #непрерывная интеграция #автоматизация #опыт #разработка сайтов-
Полное Руководство По Selenium Webdriver
19 Oct, 24 -
Embarcadero Rad Студия Xe6
19 Oct, 24 -
Восстановление Данных С Hdd
19 Oct, 24