Google: Software Engineering at Google
Как Google выстроил инженерную инфраструктуру для монорепозитория с миллиардом файлов и 25 000 разработчиков
Первоисточник
Software Engineering at Google: Lessons Learned from Programming Over TimeTitus Winters, Tom Manshreck, Hyrum Wright, 2020
Монорепозиторий как философия
Google хранит весь свой код в одном репозитории. Не метафорически, не «большую часть», а буквально всё: больше миллиарда файлов, 35 миллионов коммитов, 86 терабайт данных. Ежедневно 25 000 инженеров вносят 16 000 изменений, а ещё 24 000 коммитов делают автоматизированные боты. Единственное исключение из монорепозитория — проекты Android и Chrome, которые живут в отдельных репозиториях по историческим причинам.
Titus Winters и соавторы объясняют логику этого решения так: Google предпочитает проблемы version control проблемам dependency management (подробнее о trade-offs — в главе про monorepo vs polyrepo). Когда весь код лежит в одном месте, инженер видит все зависимости. Если команда А меняет API библиотеки, она может найти всех потребителей этого API через Code Search и обновить их вызовы в том же коммите. В мире polyrepo эта же задача превращается в координацию между пятью командами, тремя версиями библиотеки и бесконечной матрицей совместимости.
Внешние зависимости (open source библиотеки, лицензированный код) тоже живут в монорепозитории, но в отдельной директории third_party, которая маркирует код с потенциальными лицензионными ограничениями.
Инструменты, которые делают масштаб возможным
Миллиард файлов в одном репозитории живёт благодаря стеку кастомных инструментов. Готовых решений под такие объёмы на рынке нет, поэтому всё пришлось писать самим.
Piper — система контроля версий. Google мигрировал на Piper с Perforce, когда тот перестал справляться с нагрузкой. Piper работает поверх Spanner (распределённая база данных Google), реплицируется через 10 дата-центров и обрабатывает десятки тысяч операций в секунду.
Clients in the Cloud (CitC) — облачная рабочая среда. Клонировать репозиторий локально невозможно: 86 терабайт на ноутбук не помещаются. CitC через FUSE-файловую систему показывает весь репозиторий как локальную директорию, а хранит только изменённые файлы. Средний рабочий набор — меньше 10 файлов. Открыть любой файл в репозитории — мгновенно, без git clone и git pull.
Blaze — система сборки, которую Google позже открыл как Bazel. Blaze собирает только изменённое, кэширует артефакты между всеми инженерами и распределяет компиляцию по кластеру. Без инкрементальной распределённой сборки каждый коммит превратился бы в часовое ожидание.
Critique — система code review. Все изменения в Google проходят через review до коммита. Critique показывает diff, запускает линтеры, тесты и статический анализ, хранит обсуждение. По данным из книги, культурное давление «не коммитить плохой код» работает мощнее любого формального гейта.
Code Search — полнотекстовый поиск по всему репозиторию с индексацией. Имя функции — и за секунды видны все её использования среди миллиарда файлов. Code Search интегрируется с CitC: из результатов поиска можно перейти в редактирование, внести правку и отправить на review, не покидая браузер.
Tricorder — платформа статического анализа, встроенная в процесс review. Rosie — инструмент для массовых рефакторингов через весь репозиторий.
Trunk-based development без исключений
Google практикует trunk-based development в чистом виде: никаких feature branches, никаких long-lived веток. Все 25 000 инженеров коммитят в одну ветку (trunk), которая в каждый момент времени должна быть рабочей. Winters и соавторы пишут, что «существует только одна версия, которая имеет значение».
Такое решение ставит жёсткие требования к тестированию. Каждый коммит проходит через набор тестов, и в скорость и надёжность тестовой инфраструктуры вкладываются огромные ресурсы. Flaky-тесты Google рассматривает как баги инфраструктуры: ненадёжный тест подрывает доверие ко всей системе тестирования.
Readability — уникальная практика
Одна из необычных практик Google — процесс «readability». Для каждого языка программирования (C++, Java, Python, Go) существует группа экспертов, которые проводят readability review. Чтобы коммитить код на определённом языке, инженеру нужно одобрение от человека с readability-статусом для этого языка.
Readability обеспечивает консистентность по всему репозиторию. Чужой код читают чаще, чем пишут свой, и предсказуемый стиль снижает когнитивную нагрузку при чтении.
Trade-offs подхода Google
Инструменты Google невозможно скопировать. Piper, CitC, Blaze (в полной внутренней версии), Critique — продукты многолетних инвестиций, которые окупаются при масштабе Google. Компания с 200 инженерами не получит тех же преимуществ от монорепозитория, но заплатит высокую цену за настройку инфраструктуры.
Монорепозиторий создаёт зависимость от внутренних инструментов. Инженер Google привыкает к Piper и Critique, а при переходе в другую компанию обнаруживает, что git и GitHub работают иначе.
Trunk-based development без веток требует зрелой культуры тестирования и feature flags. Без возможности коммитить незавершённый код за флагом trunk превращается в хаос.
Что можно позаимствовать
У Google стоит учиться принципам, а не конкретным инструментам. Три идеи из книги «Software Engineering at Google» работают на любом масштабе.
Инвестируйте в code search. GitHub Code Search, Sourcegraph, OpenGrok экономят часы в неделю даже в репозитории из 500 файлов.
Стандартизируйте стиль кода через автоматизацию. Линтеры и форматтеры (prettier, black, gofmt) делают readability review ненужным для стилевых вопросов. Ревьюерам остаются логика и архитектура.
Относитесь к flaky-тестам как к P1-багам. Если тесты проходят «через раз», инженеры перестают доверять CI. Через полгода CI превращается в декорацию.