Работа с несколькими филиалами в непрерывной интеграции

85

Я имел дело с проблемой масштабирования CI в своей компании и в то же время пытался выяснить, какой подход использовать, когда речь идет о CI и нескольких филиалах. Аналогичный вопрос есть в stackoverflow, Multiple features branch и непрерывной интеграции . Я начал новый, потому что хотел бы получить больше обсуждения и дать некоторый анализ вопроса.

На данный момент я обнаружил, что есть 2 основных подхода, которые я могу использовать (или, может быть, некоторые другие ???).

  • Множественный набор заданий (здесь речь идет о Jenkins / Hudson) на ветку
  • Множественный набор заданий на 2 ветки (dev и стабильная)
    • Управляйте двумя наборами вручную (если вы измените конфигурацию задания, обязательно измените в другой ветке)
      • PITA, но по крайней мере так мало, чтобы управлять
    • Другие дополнительные ветки не получат полный набор тестов, пока они не будут отправлены разработчикам
    • Недовольные разработчики. Почему разработчику должны волновать проблемы масштабирования CI. У него есть простая просьба: когда я перейду, я хочу протестировать свой код. Просто.

Похоже, что если я хочу предоставить разработчикам CI для их собственных пользовательских веток, мне понадобятся специальные инструменты для Jenkins (API или сценарии оболочки или что-то в этом роде?) И обработать масштабирование. Или я могу посоветовать им чаще сливаться с DEV и жить без CI в пользовательских ветках. Какой из них вы бы выбрали, или есть другие варианты?

Toomasr
источник

Ответы:

69

Когда вы говорите о масштабировании CI, вы на самом деле говорите о масштабировании использования вашего CI-сервера для обработки всех ваших функциональных веток вместе с вашей основной линией. Поначалу это кажется хорошим подходом, поскольку разработчики в филиале получают все преимущества автоматического тестирования, которые включают в себя задания CI. Однако вы сталкиваетесь с проблемами при управлении заданиями сервера CI (как вы уже обнаружили) и, что более важно, вы на самом деле не выполняете CI. Да, вы используете CI-сервер, но вы не интегрируете постоянно код от всех своих разработчиков.

Выполнение реального CI означает, что все ваши разработчики регулярно переходят на основную линию. Легко сказать, но самое сложное - сделать это, не нарушив работу приложения. Я настоятельно рекомендую вам взглянуть на Непрерывную доставку , особенно на раздел « Сохранение возможности повторного запуска вашего приложения » в главе 13: «Управление компонентами и зависимостями» . Основные моменты:

  • Скрывайте новые функции, пока они не будут завершены (AKA Feature Toggles ).
  • Вносите все изменения постепенно, как серию небольших изменений, каждое из которых является выпускаемым.
  • Используйте переход за абстракцией, чтобы вносить крупномасштабные изменения в кодовую базу.
  • Используйте компоненты для разделения частей вашего приложения, которые изменяются с разной скоростью.

Они довольно понятны, за исключением перехода по абстракции. Это просто причудливый термин для:

  1. Создайте абстракцию над той частью системы, которую вам нужно изменить.
  2. Выполните рефакторинг остальной системы, чтобы использовать уровень абстракции.
  3. Создайте новую реализацию, которая не является частью рабочего кода кода до завершения.
  4. Обновите уровень абстракции, чтобы делегировать свою новую реализацию.
  5. Удалите старую реализацию.
  6. Удалите слой абстракции, если он больше не подходит.

Следующий абзац из раздела « Ветви, потоки и непрерывная интеграция » в главе 14 «Расширенный контроль версий» суммирует воздействия.

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

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

Том Ховард
источник
4
Том, это работает хорошо, только если 1) и выпуск, и обновление сравнительно просты 2) большинство ваших изменений хорошо изолированы. Это верно для веб-разработчиков, но если вы выпускаете выпуски продуктов в штучной упаковке, стабильные версии должны оставаться стабильными любой ценой, потому что исправления действительно дороги или даже невозможны в большой корпоративной среде.
Евгений Кабанов
13
настоящий CI - это не только интеграция, но и обратная связь,
Антон Архипов
3
Я выбрал это в качестве ответа (по крайней мере, назначил награду, пожалуйста, дайте мне знать, если мне все еще нужно отметить это правильно), но я думаю, что это не решение моей проблемы. Я написал продолжение на zeroturnaround.com/blog/…
toomasr
1
@Jevgeni Kabanov и @toomasr Вы оба, похоже, полагаете, что выполнение настоящего CI означает отказ от качества, и это работает только для веб-разработчиков, потому что так легко выпускать исправления. Я предполагаю, что вас беспокоит хитрая фиксация непосредственно перед выпуском. Да, это может привести к плохому выпуску, исправление которого может оказаться дорогостоящим. Однако хитроумная фиксация в функциональной ветке непосредственно перед ее выпуском также плоха. Если вы чувствуете разницу, поделитесь своими рассуждениями. Один из способов борьбы с этим (если фиксация была сделана в основной ветке или в функциональной ветви) - использовать подход непрерывной доставки.
Том Ховард
1
Да, и кстати, последние 4 года мой основной опыт разработки был связан с финансовыми учреждениями. Необходимость иметь стабильные выпуски и цена ошибки (не говоря уже о процессе управления изменениями, который необходимо пройти, чтобы выпустить исправление) не намного больше, чем это. Коробочный продукт был бы для меня расслабляющим изменением.
Том Ховард
4

Я бы создал отдельные рабочие места для каждого филиала. Я делал это раньше, и это не сложно, если вы правильно настроили Hudson / Jenkins. Быстрый способ создать несколько заданий - скопировать из существующего задания, которое имеет аналогичные требования, и изменить их по мере необходимости. Я не уверен, хотите ли вы разрешить каждому разработчику настраивать свои рабочие места для своих веток, но для одного человека (например, менеджера сборки) это не так уж сложно. После того, как пользовательские ветви будут объединены в стабильные ветви, соответствующие задания могут быть удалены, когда они больше не нужны.

Если вас беспокоит нагрузка на сервер CI, вы можете настроить отдельные экземпляры CI или даже отдельные ведомые устройства, чтобы помочь сбалансировать нагрузку на нескольких серверах. Убедитесь, что сервер, на котором вы запускаете Hudson / Jenkins, подходит. Я использовал Apache Tomcat и просто должен был убедиться, что у него достаточно памяти и вычислительной мощности для обработки очереди сборки.

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

Бернар
источник
Я думаю, что отсутствие инструментов означает, что в этом отделе есть место для некоторых плагинов / продуктов. Не хотел бы писать свою.
toomasr
1
Для Jenkins существует утилита, которая автоматически создает конфигурацию сборки для каждой ветки: entagen.github.com/jenkins-build-per-branch
kolen
3

Я бы выбрал dev + стабильные ветки. И если вам все еще нужны настраиваемые ветки и вы боитесь нагрузки, то почему бы не переместить эти настраиваемые ветки в облако и позволить разработчикам управлять ими самостоятельно, например http://cloudbees.com/dev.cb Это компания, в которой сейчас находится Kohsuke . Также существует Eclipse Tooling, поэтому, если вы используете Eclipse, он будет тесно интегрирован прямо в dev env.

Антон Сафонов
источник
Обменяю ли я отсутствие инструментов для управления несколькими филиалами с той же проблемой, но в облаке? Я имею в виду, что теперь я смогу управлять нагрузкой, но все еще не могу управлять ветками?
toomasr
Я имел в виду забыть об инструментах и ​​распределить управление между разработчиками - «если вам нужна индивидуальная персональная сборка, вот ваша учетная запись CB». Не влияя на производительность сборки основного сервера. Хотя их API довольно прост, поэтому создание утилит управления, вероятно, займет одну-две недели, а затем вы будете делать там все, что хотите. Как это обычно бывает в жизни, если хочешь чего-то особенного, лучше сделать это самому. В то же время они быстро растут и прислушиваются к сообществу, поэтому заполните запрос функции, и, возможно, он скоро появится.
Антон Сафонов
Ой, понял. Скажите владельцу ветки, что вишня выберет интересующие его вакансии и настроит их для своей собственной ветки по своему усмотрению. Мне нравится эта идея.
toomasr
1

На самом деле, что действительно проблематично, так это изоляция сборки с помощью функциональных веток. В нашей компании есть набор отдельных проектов maven, которые являются частью более крупного дистрибутива. Эти проекты обслуживаются разными командами, но для каждого дистрибутива необходимо выпустить все проекты. Функциональная ветвь теперь может перекрываться от одного проекта к другому, и тогда изоляция сборки становится болезненной. Мы попробовали несколько решений:

  • создавать отдельные репозитории снимков в нексусе для каждой функциональной ветки
  • совместно использовать локальные репозитории на выделенных ведомых устройствах
  • используйте плагин репозитория-сервера с вышестоящими репозиториями
  • построить все в рамках одной работы с одним частным репозиторием

Собственно говоря, последнее решение является наиболее перспективным. Все остальные решения так или иначе отсутствуют. Вместе с плагином job-dsl легко настроить новую функциональную ветку. просто скопируйте и вставьте отличный скрипт, адаптируйте ветки и позвольте начальному заданию создавать новые задания. Убедитесь, что задание семян удаляет неуправляемые задания. Затем вы можете легко масштабироваться с помощью ветвей функций по различным проектам maven.

Но, как хорошо сказал Том выше, было бы лучше преодолеть необходимость в ветвях функций и научить разработчиков чистой интеграции, но это более длительный процесс, и результат неясен со многими устаревшими частями системы, которые вы больше не будете трогать.

мои 2 цента

моряк
источник