Комментарии 100
Я только не совсем понял из текста:
Разработка ведется по модели Trunk based development. Большинство пользователей работает с HEAD или наиболее свежей копией репозитория, полученной из основной ветви, называемой trunk, в которой идет разработка. Фиксация изменений в репозитории осуществляются последовательно. Сразу после коммита новый код виден и может использоваться всеми разработчиками. Разработка в отдельных ветках не приветствуется, хотя ветки могут использоваться для релизов.
Что значит разработка в отдельных ветках не приветствуется? Имеются в виду ветки, в которых может осуществляться долгая параллельная разработка (до недель)? Потому что по ссылке trunkbaseddevelopment.com явно написано, что каждое изменение выделяется в одну ветку (feature branch), которая существует некоторое время (короткое — дни), а потом вливается в репозиторий при помощи мержа. Это не совсем то же самое, что и «каждый отдельный коммит». Или вы заставляете обязательно делать людей squash для всех коммитов в их feature branch, а потом rebase того, что получилось, от trunk (master)? Хотелось бы конкретики :)
А еще я проглядел (или в статье этого нет): какую систему контроля версий вы используете?
Что значит разработка в отдельных ветках не приветствуется? Имеются в виду ветки, в которых может осуществляться долгая параллельная разработка (до недель)? Потому что по ссылке trunkbaseddevelopment.com явно написано, что каждое изменение выделяется в одну ветку (feature branch), которая существует некоторое время (короткое — дни), а потом вливается в репозиторий при помощи мержа. Это не совсем то же самое, что и «каждый отдельный коммит». Или вы заставляете обязательно делать людей squash для всех коммитов в их feature branch, а потом rebase того, что получилось, от trunk (master)? Хотелось бы конкретики :)
Строгих правил нет, только рекомендации, никто никого не заставляет. Некоторые команды используют подход с feature-braches. У нас есть много примеров, когда команды сами приходят к пониманию того что разработка в trunk намного удобнее. Многие проекты вели разработку в отдельных ветках, которые могли жить по несколько месяцев. Мержить изменения в trunk и обратно, отщеплять новые ветки – все это было достаточно трудоемкими задачами. Далее время жизни веток постепенно сокращалась, пока разработка полностью не переезжала в trunk. Твой вариант (про squash) почти корректный, но есть набор некоторых допущений.
А еще я проглядел (или в статье этого нет): какую систему контроля версий вы используете?
В статье этого нет, для монорепозитория у нас используется несколько систем контроля версий, которые работают над одним набором данных. На текущий момент это svn, hg и некоторые внутренние разработки.
Если развернуть, то получится еще одна статья, – когда-нибудь обязательно напишем, если вам интересно.
На текущий момент это svn, hg и некоторые внутренние разработки.
Теперь понятно, почему часто фигурирует слово trunk. Не проще всё перевести на git? С svn не работал, а вот с серьёзными проблемами вытягивания большого объёма данных при пропадающем соединении у hg уже успел столкнуться за единственный раз работы с ним. Догадываюсь, что у git есть преимущества по сравнению с обоими системами контроля версий.
Есть некоторые вопросы:
1. Каким образом разработчик взаимодействует с репозиторием? Он же не клонирует себе все 25 Гб? Отсюда же вопрос про push/pull. На следующий день придется скачивать более 2к коммитов? Полагаю, что нет и есть возможность скачать часть репозитория.
2. > любой проект из репозитория получает готовую инфраструктуру
А GitLab разве не дает все то же самое? Тот же community-edition. Если возможностей код-ревью GitLab мало, конечно, можно запилить своё, но просмотр и навигация по коду там сделаны вполне себе неплохо.
3. > система сборки и распределенная сборка. Это отдельная большая тема, и мы обязательно ее раскроем в следующих статьях.
Что имеется в виду под системой сборки? Система сборки проектов на C++? А что вообще у вас используется для сборки проектов на C++? CMake/waf/SCons? Или же имеется в виду аналог Jenkins?
4. > система непрерывной интеграции.
А чем не подошел Jenkins?
5. > совместное использование кода, активное взаимодействие команд.
В чем проблема совместно использовать код и активно взаимодействовать в подходе с множеством репозиториев?
6. > С общим кодом у вас появляется возможность сделать часть работы самим и «помочь случиться» нужным вам изменениям.
Опять непонятно каким образом то же самое не дает делать подход с N репозиториями: склонировал себе, сделал ветку, запушил, сделал pull request.
7. > появляется возможность проводить глобальный рефакторинг. Вам не надо поддерживать старые версии вашего API или библиотеки, вы можете изменить их и поменять те места, где они используются в других проектах.
Опять как-то странно. Когда N репозиториев: склонировал их себе, поправил, запушил. Сделали деплой новой версии на рабочие сервера и перестали поддерживать старую версию.
Из плюсов для себя вижу только решение проблемы dependency hell и упрощение сборки, т.к. не надо поддерживать список зависимостей с ревизиями/ветками, на которые надо обновляться. Но даже если и его надо было бы поддерживать, то это не такая и большая проблема, т.к. многое можно автоматизировать.
1. Каким образом разработчик взаимодействует с репозиторием? Он же не клонирует себе все 25 Гб? Отсюда же вопрос про push/pull. На следующий день придется скачивать более 2к коммитов? Полагаю, что нет и есть возможность скачать часть репозитория.
Есть селективный checkout.
Что имеется в виду под системой сборки? Система сборки проектов на C++? А что вообще у вас используется для сборки проектов на C++? CMake/waf/SCons? Или же имеется в виду аналог Jenkins?
Имеется в виду система автоматизации сборки.
А чем не подошел Jenkins?
— Jenkins не умеет делать то что умеет делать наш CI. Стоимость доработки и адаптации под наши процессы, интеграция с другими нашими системами может легко превышать стоимость разработки своей системы с нуля.
— Тесная интеграция CI системы с нашими процессами и другими системами.
— Наша система скрывает за собой комплекс из нескольких систем. CI система, распределённая система выполнения задач общего назначения с кластером большого размера, система распределенной сборки. Обо всем этом мы будем постепенно рассказывать.
— касательно Jenkins. Мне он не очень нравится. Мне больше нравится Gitlab-ci, еще крутой concourse. Что-нибудь такое готовое используете? Потому что платформа сборки — это чуточку шире, чем какой-то отдельный продукт. И я могу представить себе систему, которая объединяет под капотом concourse/gitlab-ci/ набор сервисных докер-образов и все это работает поверх какого-нибудь менеджера ресурсов (k8s?)
Вот я статья которую я написал на этот счет
ссылку не увидел. Или ее не было?
Некоторые команды используют подход с feature-braches
Не совсем понял из статьи. Подскажите пожалуйста — для feature branch так же как и для trunk автоматически будут запускаться сборки, тесты и т.п.?
Для хранения единой кодовой базы Яндекс использует SVN
Про git видимо не слышали
Ну на самом деле в этом есть смысл, особенно для проектов на С++, у которого отсутствует пакетный менеджер. Все равно с С++ приходишь к мысли, что надо все перекомпилировать одним компилятором, т.е. смысла держать код в разных репах нет, ибо все равно все сливается в одну.
Ну и монолитная репа помогает сразу отлавливать проблемы API, ибо при смене API в одной зависимости надо сразу же починить все зависимые куски, иначе у тебя не пройдет CI.
Другое дело, что создавать свой YMake, который типа не CMake, держать код в svn, потому что "тижило портировать" — ну это детский сад.
Пакетные менеджеры С++ довольно сильно развиваются, но с озвученные проблемы тоже пришлось решать.
К примеру — conan, crosspm
что «тижило портировать» — ну это детский сад.
Свой проект — еще куда не шло.
А все используемые либы, и либы от которых зависят используемые либы и те либы от которых они зависят либы используемые либами, которые мы используем и…
Microsoft gvfs на текущий момент полностью эту задачу не решает.
Каких-либо доступных снаружи решений нет.
Т.к. с git мы знакомы достаточно тесно, внутренние разработки в районе VCS базируются как раз на git.
25GB — ни о чём объёмы для гита. Это я вам как бывший обладатель Git-репозитория на полтора терабайта и нынешний обладатель Git-репозитория на 70GB говорю.
- Добавляется унификация проектов, в том числе и в CI. Иерархически подключенные подмодули — сложно (в плане CI/CD), но реализуемо.
- Возможность множественных вложенных (в плане повторений в рамках проекта) подмодулей тоже реализуема, но через систему сборки и скрипты над git.
- Всё однотипное, тестируется по одинаковым принципам.
На мой взгляд, монорепозиторий — это крайне неудобно. К тому же из подмодулей можно вполне и тот же монорепозиторий сделать, если очень захочется.
А Гуглю помогает… habr.com/post/429018/#comment_19334662
Знание всяких заумных алгоритмов и хайповых технологий — далеко не показатель ума и качества работы потенциального сотрудника, гораздо важнее уметь писать поддерживаемый код и разрабатывать стройную архитектуру, а не «мермишель», но зато ппц какую крутую, имхо
50 000 проектов и библиотек / 2000+ разработчиков = 25 проектов на разработчика…
Есть ощущение, что что-то идет не так.
Судя по такой статистике каждый вновь прибывший разработчик пишет свой велосипед, каждый ушедший разработчик оставляет за собой гору велосипедов, которые никто не хочет использовать и поддерживать или не знает как использовать.
Там где я работаю можно не хило по шапке получить за новую библиотеку или зависимость или за то что народ не разбирается в твоем велосипеде. А в больших компаниях наоборот… вот недавно только пост был habr.com/post/429018
А если по теме статьи, то такое ощущение что создается монолит со скоростью 10 коммитов в секунду и этот адский огромный монолит нужно прогонять по тестам в короткие промежутки времени… но тестов очень много и за секнду не прогоняется и падает всегда. Да и вообще даже внутри тестов энтропия такая, что неизвестно тест вообще рабочий или нет.
Был на гугловой конфе, там одна из команд рассказывала про международный проект, где была всего лишь одной из сотен команд по всему миру (то есть суммарно тоже тысячи разрабов). Так вот они отвечают только за свои микросервисы (а может и не микро). Каждый имеет свою документацию поддерживаему и технически не сильно зависит от остальных. Свои сервера, свои технологии. Главное что бы документация была подробной, понятной, актуальной и доступной для всех пользователей (внутренних) этого сервиса. В общем полная децентрализация и минимум зависимостей и своих велосипедов и всё у них хорошо.
Во-первых, люди хорошо знают проект и могут очень быстро починить проблему.
Во-вторых, если писать код с оглядкой на специфику компании, а не под общий случай, с которыми обязаны работать продукты общего назначения, можно улучшить технические показатели (память, нагрузка на CPU) на порядок. Например, если известно, что в БД только целые числа, а индексы и запросы только определённого вида, код можно написать на порядок эффективнее, чем для БД общего назначения.
Во-первых, люди хорошо знают проект и могут очень быстро починить проблему.
да ладно… этож не стартаперы. Люди приходят и уходят. Среднее время работы разработчика около 3х лет. Сомневаюсь что в Яндексе по 10 лет работают в среднем.
+ Ротация между проектами наверняка имеет место быть, а то с ума сойти можно.
Так что если доки актуальной нет на велосипед (а обычно никто не поощряет документирование велосипедов) — то скорее всего проще написать еще один велосипед, получить премию и почёт. Ну или закостылять, ведь подругому то никак в старом велосипеде не разобраться.
_____
А то что необходимы — это да… но не 25 проектов на человека ведь.
Согласен и не согласен одновременно. Меня тоже очень удивляло желание Яндекса писать все самостоятельно, да ещё и на с++. С другой стороны, у них велосипеды получаются реально крутые (например, Кликхаус, Я.Облако)
Ошибок в вашем коде быть не должно, лучше написать неэлегантный код, но без ошибок, чем наоборотвот так и пишутся разного рода неподдерживаемые «лисапеды» с говнокодом, зато ЧСВ у написавшего зашкаливает. И что значит не должно быть ошибок? Как вы в таком случае нанимаете сотрудников, да еще и CI/CD настраиваете, когда сами себе и противоречите?
Очень обстоятельная статья. Спасибо. Дочитал до середины, остальное — на закуску
Сразу два вопроса.
- Безопасность. Все ли разработчики видят код всех остальных? По всем проектам? А что с секретами — реквизиты подключения к БД, сертификаты ssl и пр.?
- trunk. Это косвенно говорит об использовании svn. Я угадал? Если нет, то какая система управления версиями используется ?
Получается нет исходного кода, который является тайной? Я как-то читал, что то ли алгоритм ранжирования, то ли еще что-то в Яндексе хранится за семью замками. Это не правда?
Ну, и инфраструктура тоже в отдельном репо, видимо?
Сколько по времени обычно длится бинарный поиск коммита, который ломает тесты?
Один общий репозиторий на 25 гигабайт? Это звучит так отстойно, что… ну неужели это обязательно было делать то?
Монорепы очень любит и Google.
И самый большой в мире репозитарий — у Microsoft.
Почему так не скажу, но большие репы в организациях, серьезно занимающихся ИТ — не редкость.
Вы все внешние зависимости прямо исходниками в репу тащите? О_о
OpenSSL нужен — фигак и забрали, webkit нужен — фигак и тоже…
Да ни в какую, если соблюдать semver. Другое дело, что на семвер обычно кладут. И в любом случае боль не больше, чем если обновится внешняя библиотека, которая лежит не в монорепе, а где-то в репозитории debian.
А за тем, какие дебпакеты приедут на сервера, где крутится мой сервис — я сам прослежу.
Как это выглядит в монорепе? Кто выделяет ресурс для таких общих и масштабных задач? Или какая-то одна проектная команда тратит свои драгоценные человеко-дни, чтобы всем сделать хорошо?
Если не монорепа, то обновление зависимости будет быстрым для проекта.
Не путайте обновление зависимости и обновление зависимых. Если обновится внешняя зависимость, никому не станет от этого легче, ибо эту зависимость еще надо втянуть.
С другой стороны я бы послушал аргументы amkruglov по этому поводу.
Как это выглядит в монорепе? Кто выделяет ресурс для таких общих и масштабных задач? Или какоя-то одна проектная команда тратит свои драгоценные человеко-дни, чтобы всем сделать хорошо?
Иногда требуемую open-source зависимость может положить в репозиторий какая-либо проектная команда. Но заметную часть работы выполняет соседняя с нами команда. И всем действительно хорошо :)
Я знаю кучу брошенных репо на гитхабе.
Например, github.com/moira-alert/worker (слава Богу — это не зависимость).
В большой системе вероятность поломки в любой произвольно взятый промежуток времени стремится к единице. Расскажите, что происходит во время поломанного HEAD? Каковы реакции со стороны системы и разработчиков? Сколько времени уходит в среднем на восстановление работоспособности?
Не увеличивает ли это сильно время коммита и не потребляет ли этого много ресурсов на ноутбуках разрабов?
Прекоммитные проверки – это процесс проверки твоих локальных изменений в CI системе. Прекоммитные проверки позволяют понять что будет если закоммитить изменения прямо сейчас. Твои изменения в виде патча/diff'а отправляются в CI систему, далее CI система определяет затронутые цели и осуществляет сборку, запуск тестов и т.д. Патч накладывается на HEAD.
А большое количество предкоммитных проверок не затягивают время коммита? Я так понимаю, что на время предкоммитной проверки репозиторий блокируется?
Продолжу мысль. Есть вероятность поломки тестов в репозитории после коммита, потому что проверка осуществляется поверх одного коммита из trunk, а коммит – спустя некоторое время. Но при осуществлении коммита после успешной прекоммитной проверки вероятность поломки стремится к нулю.
Не совсем понятно, как это работает, когда два разработчика отдают на ревью два изменения затрагивающие один файл. По результатам ревью может быть принято одно изменениеи не принято второе. Причем до ревью не ясно какое.
Правильно ли я понял, что измения первого успевшего будут приняты обязательно, а второй вобще не сможет закоммитить и должен будет исправлять конфликты с изменениями, которые вообще могут оказаться неверными?
Конфликты случаются не так часто как может показаться. Проблем при изменении одного файла обычно нет. Проблемы бывают при изменении одних и тех же строк одного файла. Но конфликты случаются так редко что я даже не могу вспомнить когда я из видел последний раз. Но если все же случаются, то поведение такое как ты описал. Кто-то успел закоммитить первым. Второй разработчик должен разрешить конфликт. Стандартное поведение для систем контроля исходного кода.
Если мерж конфликт при слиянии с транком не остановит, то никак там не разрешаются. После мержа в транк запускается новая проверка (по уже линейной истории), если она станет красная — приходит уведомление владельцу таргета и чинят ASAP. Фактически целиком весь репозиторий зелёным никогда и не бывает — просто стремится к этому состоянию в пределе.
Интересно было бы узнать, как QA занимающиеся ручным тестированием вписываются в данный процесс.
С описанными выше процессами наша система управления ручным тестированием сейчас не интегрирована. Но все впереди.
Еще не очень понятно как организуются зависимости между проектами. Допускается ли между ними прямая связь на уровне исходного кода?
Зависимости между проектами по исходному коду.
Как часто можно делать релизы при такой схеме?
Зависит от сложности проекта, времени выполнения тестов, наличия ручного тестирования. Несколько раз в неделю для самых сложных проектов — вполне достижимо. Про один из наших проектов рассказывали на мероприятии Яндекс изнутри: умные технологии в рекламе. Для более простых проектов — так часто как хочется, хоть покоммитно.
Спасает ли ревью и тесты от попадания багов в релиз?
100% гарантию никто не даст.
Ещё интересно, как делать завивмость на определенную версию библиотеки?
Как релизить проекты независимо?
Вот есть у Вас какой-нибудь условный Слак или Gmail. И у него, как коробочного продукта, нет различных версий. Только «последняя». Ну, может с какими-то встроенными feature toggle и функциональностью A/B тестов, чтобы проверять гипотезы.
Ну вот допустим пишу я слак и либу для него. У тебя новая версия ещё не закончена, но уже влита. А вот слак пора срочно хотфиксить. Что делать? Релизить сразу с новой либой, даже если ещё не доделана?
Если декомпозиция именно такая, как я понял, то не должно быть ситуации, когда либа не доделана и вмержена. Т.е. сначала новый протестированный функционал в либе, и потом уже изменения следом в 'слак'. Либо если текущий слак сломался и нужен хот-фикс, то делаешь хот-фикс в транке…
У общих библиотек только одна версия. Релизам это никак не мешает. Если коммит в trunk про обновление или изменение библиотеки прошел, то каждый проект рано или поздно выкатится в production согласно своему релизному циклу.
Скажите а занимаются ли SDET поддержкой тестовых стендов?
Имею ввиду:
— организацию доставки нового кода на тестовый стенд;
— решением интеграционных проблем на тестовых стендах;
— обновление тестовых данных на cерверах;
— собственно написание ansible скриптов для разворачивания этих серверов.
Или же автоматизаторы занимаются только написанием автотестов?
Разработчики автотестов у нас есть. Но у нас все стремится к тому чтобы разработчики сами писали тесты. И мы делаем все возможное чтобы упростить им жизнь. Но тут тоже все зависит от конкретной команды. Я пишу про общий тренд.
Про деплой.
- Первый этап – пакетирование. Для этого у нас есть стандартное решение. Особый файл json описывает какие артефакты (цели в терминах системы сборки, файлы из репозитория, артефакты из хранилища ресурсов) и как нужно скомпоновать в один пакет (tarball, debian).
- Собрать пакет можно локально, но скорее в тестовых целях. Обычно собирают в распределённой системе выполнения задач общего назначения – так надежнее, т.к. там правильное и безопасное окружение.
- Далее сам деплой. Сейчас есть выбор из нескольких способов деплоя (различные системы деплоя, куда деплоить).
Тема деплоя сейчас очень активно развивается, прямо очень-очень быстро. Выработка единого и подходящего для всех решения с хорошей архитектурой, унификация. Мы верим что очень скоро все сойдется. Деплой становится простым. И мы также постараемся об этом рассказать.
Понял что разработчики пишут автотесты сами, хорошо. Разработчики занимаются devops делами или этим заняты соответственно отдельные люди (организацией тестовой среды, настройками интеграции и тд)?
Основная идея, что в мастер мержит только робот и только после а) успешного прохода CI (можно больше одной штуки) б) +2 на code review.
В этой ситуации любой факап деплоя превращается из дисциплинарного разговора (любого вида — сам понял, выговор — не важно) в баг, который можно исправить.
По коммиту в какой-то один проект делается сборка и запускаются тесты для всего единого репозитария, или это делается только для данного проекта и зависящих от него других проектов.
Если второе, то как отслеживаются эти зависимости.
И как при этом запускаются сборки/тесты — синхронно, то есть если уже одна сборка всего пошла, то все остальные коммиты копятся и ждут? Или асинхронно, то есть на каждый коммит своя сборка запускается.
По коммиту в какой-то один проект делается сборка и запускаются тесты для всего единого репозитария, или это делается только для данного проекта и зависящих от него других проектов.
Если второе, то как отслеживаются эти зависимости.
Запускаются только затронутые изменениями сборки и тесты. В нашей системе сборки, как и в других системах автоматизации сборки, для проекта можно задавать зависимости от других проектов.
И как при этом запускаются сборки/тесты — синхронно, то есть если уже одна сборка всего пошла, то все остальные коммиты копятся и ждут? Или асинхронно, то есть на каждый коммит своя сборка запускается.
Здесь я отвечал про прекоммитные проверки. Для посткоммитных проверок это тоже актуально.
Там рассказываем про устройство системы непрерывной интеграции в Яндексе.
Continuous integration в Яндексе