Как стать автором
Обновить

Процесс разработки и выкатка релизов в Badoo. Автоматическое тестирование. Девелоперское окружение

Время на прочтение26 мин
Количество просмотров43K
Всего голосов 121: ↑92 и ↓29+63
Комментарии41

Комментарии 41

Зашел чтобы прочитать этот коммент.
>Владислав Чернов: Мы используем git rebase, мы именно его используем, потому что git revert нас не устраивает, так как мы разрабатываем каждую задачу в отдельной ветке. Если мы откатываем с помощью revert после сливания ветки релиза и ветки мастера, то разработчику придётся делать revert на revert, поэтому мы используем git rebase. Мы моментально откатываемся, соответственно, собираем новую сборку и выкладываемся на стейджинг.

Признайте честно, что просто не осилили git revert и cherry-pick. В результате, например, разработчикам под страхом страшной смерти нельзя мержится от ветки, к которой ещё могут запустить git rebase.
А зачем разработчику мержить себе в ветку релиз, если он через 4 часа всё равно будет в мастере? Если есть какая-то зависимость между задачами, то можно замержить отдельную задачу, это намного безопаснее.
Например, разработчик может сам разрешать конфликты, поскольку лучше понимает функционал, чем релиз-инженер. Вообще же, замена функционала итп часто обратно несовместима, и на дев-платформах это легко разрешать банальным мержем с мастером/релизом.

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

Кстати, привет 2 хейтерам из Баду.
Все конфликты решают разработчики, релиз-инженер этим не занимается. Вот, как сейчас. Вы задаёте конфликтные вопросы, а отвечают на них разработчики =)
Эгегей — Хейтеры из Баду, friendly fire, свои! не надо минусить мои комменты! Или тут не только из Баду хейтеры таки? =))
Про мастер-продакшен вы правы, если мы это делаем то откатываем через revert.
Но это бывает крайне редко.
Здесь говорилось только про ветку релиза.
По поводу конфликтов у нас сделано просто благодаря той самой автоматизации. если автомерж не смог залить какую-то ветку в билд, то задаче выставляется специальный флаг в Jira чтобы предотвратить дальнейшие попытки автомержа и с AIDA переводится обратно на разработчика с комментарием что в такой-то билд её не удалось замержить.
Логично. Проблема в том, что после этого разработчик мог бы просто смержить в свою ветку мастер/релиз и таким образом легко разрешить конфликт. А так, придётся угадывать ветку, с которой произошёл конфликт, мержиться с ней, и всё равно иметь проблемы в случае отката ребейзом любой из этих веток.
А можете более развернуто описать Ваш workflow? И как откатываете изменения.
Да, будет отдельная статья про то как мы откатываем изменения из ветки релиза и небольшое описание нашего flow.
Про флоу мы уже писали в статьях тут и тут. Но отдельной статьи, посвященной именно флоу, у нас еще не было. Обязательно напишем. Так же, как Влад уже написал, готовится отдельная статья про автоматизированные откаты задач из ветки релиза.
НЛО прилетело и опубликовало эту надпись здесь
Спасибо. Но меня интересовал именно git workflow (возможно, мне стоило уточнить это). У нас прижился такой подход:

1. ветка от мастера
2. работа
3. подливаем мастер в ветку
4. мерджим ветку в мастер

ИМХО, он наиболее демократичен и гибок.

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

Хотелось узнать хотя бы на пальцах про откат ребейзом и общие принципы ветвления, принятые у Вас.
НЛО прилетело и опубликовало эту надпись здесь
1) Ветка от мастера для задачи — работа — Code review — тестирование
2) Ветка релиза от мастера
3) Автомерж веток готовых и протестированных задач в ветку релиза — интеграционное тестирование и staging
4) Нашли багу, откатываем смерженный коммит задачи из релиза c помощью rebase — сборка — повторная проверка на staging
5) Едем на продакшен — проверяем опционально
6) Если все хорошо — сливаем релиз в мастер
7) Все плохо(исключительный случай:)) перекидываем линк на предыдущий релиз.

Два релиза в день, по времени, автомерж тасок останавливается за 2 часа до выкладки на продакшен очередного релиза.

Если кратко:)
Если не сложно, ответьте на несколько простых вопросов:

1. Если представить, что у вас есть две группы разработки, серверная и клиентская, плюс группа системных администраторов, то как вы выкатываетесь?

2. Прошу пояснить что в вашем понимании 100 тасков в день.

3. Как тестировщики успевают протестировать весь проект всего за одинь день?

4. Какие критерии вы используете оценки что релиз «удался»

5. Кто может ставить таски на разработчиков?

6. Есть ли у вас ручное тестирование интерфейсов. Если есть, то какое у них воркфоу?

Подключусь к вопросам

7. Если Stage работает с продакшен базой, как происходит тестирование при изменении схемы(мажор фича, к примеру)? Используются ли инструменты для миграций?

8. Я так понял ветвитесь только в один уровень, а если нужно работать группой разработчиков над одной фичей и каждый будет ветвится от этой фича-ветки?

9. Были ли случаи, когда на продакшен ушла очередная фича, но через несколько релизов оказалось, что её нужно откатить. Как происходит этот процес?
7. С базой у нас все просто если нужно что то добавить мы просто заранее делаем нужный альтер, и старый код работает как работал, потом выезжает новый код начинает работать с тем что мы добавили, проверяем все ли хорошо (при этом это уже проверялось на devel окружении), дальше при надобности удаляем ненужное. Миграция — боюсь ошибиться, но нет.
8. Нет каждый будет создавать свою из мастера (декомпозиция задач смотрите выше). Можно вести разработку в одной ветке, либо при надобности смержить их. Смерженные таски отслеживаются на уровне Git и Jira и задача если зависит от другой по коду не уедет в релиз автоматически.
9. Если вы про откат фичи с багом, то нет так как слишком много этапов тестирования и много тестов, так что все баги ловятся на этапе релиза. Бывает реверт из мастера раз в полгода, но это отлавливалось в тот же день. Если вы про выпиливании работающий фичи, то она выключается как и включалась, после этого аккуратно выпиливается код.
с базой чуть-чуть сложнее
* если код не может работать прозрачно с новой схемой — сначала идет фикс-релиз кода (так стараемся не писать, но всяко бывает)
* альтер по-живому (если по кластеру — то шард за шардом)
* релиз, использующий новую схему
* (опционально) clean-up процедуры над базами
а вообще хотя задача и сложная чисто теоретически (100% плавного алгоритма на все случаи жизни нет), на практике организационно все разруливается довольно легко
Спасибо за вопросы
1. Не надо даже представлять, так и есть. Только вы забыли еще группу релиз инженеров. Если говорить об обновлении, то системные администраторы обновляют сервисы и происходит это в момент наименьшего трафика на сайт. Сервер обновляется два раза в день, при этом серверное API (имеется ввиду сервер-клиент) пишется так чтобы не ломались старые версии приложений(если что разработчики меня поправят) и параллельно разрабатывается клиент. Тестируем чтобы новая фича ничего не сломала, что она работает на сервере, что работает с клиентом и выкатывается на сервер. Когда выходит новая версия клиента она использует новую функциональность на сервере.
2. У нас большие фичи декомпозируются на множество мелких задач, разрабатываются и тестируются (например на тестовых пользователях) именно в такой архитектуре, притом последней уезжает таска которая включает данную большую фичу для всех пользователей. Так что это может быть совершенно разные задачи, начиная от багфиксов и заканчивая включением новой большой функциональности на продакшен.
3. Мы используем большое количество автотестов на всех этапах тестирования, и стараемся особо покрывать критичные моменты. Плюс постфактум за проектом следит отдел мониторинга у которого огромное количество различных графиков и триггеров. Ну и конечно ручное тестирование задач которые в релизе. Опционально также проверяем продакшен вручную.
4. Работают новые фичи + ничего не сломалось при выкатке= релиз удался
Если что то случилось, мы не говорим что релиз плохой, а в максимально короткие сроки либо откатываемся, либо фиксим проблемы если они не так критичны и фикс займет очень короткое количество времени.
5. Если баг то QA, сами разработчи, если фича то продукт совместно с лидами, если рефакторинг сами разработчики. Жесткой бюрократии у нас нет.
6. Я не очень понял вопрос, думаю что тестирование ответит вам гораздо лучше:) Илья?
Расскажите как вы поддерживаете консистентность данных. Если я правильно понял, то из за шардинга вы не можете использовать выстроенные в ДБ механизмы типа внешних/уникальных ключей.
Тут путаница. Уникальные ключи, конечно, есть. В шардированной схеме мы внешние ключи не используем по историческим причинам, но это можно сделать. Консистентность будет в пределах шарда, но это как раз нормально — именно это и требуется. Тем не менее, жить без нее не сильно сложнее, как показала практика. Отказ от внешних ключей для датабазника может показаться очень странным (я сам до этого сидел 3 года на оракле), но консистентность по внешним ключам действительно оказалась почти не нужной. Каскадные удаления — фактически единственное реальное удобство, которого нет. Но мы не удаляем данные, а олдскульно помечаем статусами. Удаляется все потом единообразная системой пуржинга. Вообще один-два раза в года я рассказываю об этом подробнее на семинаре в рамках девконфа, например.
Спасибо за ответ. А статья по теме «БД в Баду» не планируется?
6. Ручное тестирование есть и флоу у него ничем не отличается от описанного выше. Задачи (новые фичи, багфиксы и т.п.) приходят в QA сразу после выполнения. На этот момент задача уже прошла code-review и прогнаны автоматом юнит-тесты (в тикете в джире есть репорт об этом). Тестировщики тестят это в девелоперском окружении, если все хорошо — следующий этап это тестирование задачи в шоте. Шот — это пре-продакшен для отдельной ветки кода. Если, опять же, все хорошо, то следующий этап — тестирование билда из смерженных фич на стейджинге. Ну и все что протестировано на стейджинге, уезжает в продакшен. Все эти этапы тестирования включают как ручное, так и автоматизированное тестирование. Интеграционные тесты QA-инженеры пишут на phpUnit, с использованием Selenium WD. Ручное тестирование включает в себя как регрессионные проверки фич, для которых по тем или иным причинам еще нет селениум-тестов, так и exploratory-тестирование фич. Ну и проверка фронтенда (верстка, js и т.д.) в разных браузерах, в зависимости от популярности по статистике посещения.
А можете чуть подробнее рассказать о шотах?
Если они не изолированы друг от друга, т.е используют одинаковые подключения к базам, то, получается, они могут влиять друг на друга(общий кеш, поменялась структура данных уходящих в очередь и тд)?
В функциональных тестах какая база используется? Та же, что и в девелоперском окружении? Если да, то при постоянном запуске(100 задач * 18000 тестов) она будет забиваться различными данными. Или все же используются для этого отдельные снапшоты/фикстуры БД?
Шот это просто папка с гитом, где счекаучена ветка задачи + настройки nginx, чтобы можно было зайдя по определенным точкам входа увидеть веб-морду, апи для клиентов и т.д. Эта папка выгружается на одну из машин в боевом окружении, где и тестируется.
По другим ресурсам — базам, мемкешам, демонам — они не изолированы, вы правы. И риски о которых вы говорите тоже имеются, никуда от этого не деться. Но мы минимизируем эти риски, когда тестируем задачу до шотов — в девел окружении. Где все вышеперечисленные ресурсы отделены от продакшена.
Интеграционные селениум-тесты гоняются в двух окружениях — девелоперском и стейджинговом. Для них используется отдельный пулл объектов, не затрагивающий основных пользователей ресурса.
Для девел-окружения, где (и только где) гоняются еще и юнит-тесты и функциональные тесты, отдельных снапшотов с данными не используем. Данные после сетов тестов либо роллбечим в транзакциях (где это возможно), либо используем моки таблиц. У нас есть свои классы/механизмы для этого, мы подменяем на лету таблицы и запросы к ним в коде. Таблицы делаются темповыми (за небольшими исключениями) и сами удаляются после тестов движком БД. Для тех мест, где нельзя использовать темповые таблицы, есть оффлайновый скрипт, который пробегается и чистит такие таблицы.
Безусловно, бывают ситуации, когда тесты все же оставляют данные в девелоперских базах, но это не критично, ибо 1) используем подход «каждый тест должен сам для себя готовить данные, независимо от того, что в БД или других общих ресурсах было до него» и 2) ничто не мешает в любой момент перезалить девелоперскую БД.
Ведете ли вы общий тест-план проекта, что в него попадает и смогли ли вы автоматизировать его пополнение?
От части таким тест-планом выступает набор автотестов. Отдельно от этого ничего не ведем. Ну если не считать описание фич в confluence, которое ведется продактами и корректируется по ходу реализации.
Расскажите, пожалуйста, о базах: что используете, почему используете и какие действия предпринимаются когда нужно сделать миграцию или откатить ее.
Используем mysql, по историческим причинам (ну и вообще — отличная база, просто не нужно стрелять себе в ногу и всё). У нас кстати одна из крупнейших ферм MySQL — под 500 уже наверное нод в двух ДЦ. Миграция — это выполнение в паралелль по нескольким сотням нод какой-то операции, есть фреймворк под это дело, откатить — ну так же как и на одной базе. Вы умеете на одной базе откатить альтер, например? Я — нет. Надо снова альтерить — опять в параллель пускаем операции на нодах. Всё олдскульненько.
MyISAM?
боже упаси. InnoDB конечно
Спасибо большое за интервью. Сам проработал много лет релиз-инженером, отлично понимаю, насколько важную работу и насколько хорошо ребята выполяют в команде.

Удач и успехов, в общем, пишите ещё.
НЛО прилетело и опубликовало эту надпись здесь
Кстати, Сергей Авдюшкин не в этой же команде часом?
ребята, решите что-то с ресайзом фотографий.
а то глаз режет (

image
Да, согласны, мы сейчас решаем как раз этот вопрос.
Расскажите, как файлы, которые разработчик пишет на своей локальной машине, оказываются на его dev-сервере? Монтирование, синхронизация?
В данный момент наши разработчики используют каждый, кто во что горазд :).
Варианты, как минимум:

— sshfs
— SMB
— rsync «руками»
— загрузка изменений, встроенная в PHPStorm
— realsync
— моя утилита, вместо realsync, которая умеет синхронизироваться на несколько серверов (сильно альфа :))
Зарегистрируйтесь на Хабре, чтобы оставить комментарий