Несколько лет назад Microsoft приняла решение начать долгий процесс по восстановлению системы разработки во всей компании. Мы большая компания, с множеством коллективов — у каждого собственные продукты, приоритеты, процессы и инструменты. Есть некоторые «общие» инструменты, но их много разных — и ОЧЕНЬ БОЛЬШОЕ количество разработанных внутри компании инструментов одноразового использования (под коллективами я имею в виду подразделения — тысячи инженеров).
У этого есть отрицательные стороны:
- Множество избыточных инвестиций в коллективы, которые разрабатывают похожие инструменты.
- Невозможность финансировать какой-либо инструментарий до «критической массы».
- Затруднения для сотрудников в перемещении по компании из-за разных инструментов и процесса.
- Сложность в обмене кодом между организациями.
- Разногласия с новичками в начале работы из-за чрезмерного изобилия инструментов «только для MS».
- И так далее...
Мы выступили с инициативой, которую называем «Одна Инженерная Система» (One Engineering System) или сокращённо 1ES. Как раз вчера у нас был день 1ES, где тысячи инженеров собрались, чтобы отметить достигнутый прогресс, узнать о текущем состоянии дел и обсудить планы. Это было на удивление хорошее мероприятие.
Отступим немного от темы… Вы можете задать вопрос — эй, ты же годами говорил нам, что Microsoft использует Team Foundation Server, ты что нам врал? Нет, я не врал. Более 50 тыс. человек регулярно используют TFS, но они необязательно применяют его для всей своей работы. Некоторые применяют для всего. Некоторые только для отслеживания рабочих тем. Некоторые только для контроля версий. Некоторые для сборок… У нас есть внутренние версии (и во многих случаях больше, чем одна) практически всего, что делает TFS, и кто-то где-то использует их все. Здесь есть немного хаоса, абсолютно честно. Но если объединить и взвесить, то можно с уверенностью сказать, что у TFS больше пользователей, чем у любого другого набора инструментов.
Я также хочу заметить, что говоря «инженерная система», я использую термин ОЧЕНЬ широко. Он включается в себя, но не ограничен следующим:
- Управление исходным кодом
- Рабочий менеджмент
- Сборка
- Релизы
- Тестирование
- Управление пакетами
- Телеметрия
- Управление происшествиями
- Локализация
- Сканирование безопасности
- Доступность
- Управление соблюдением правовых норм
- Подпись кода
- Статический анализ
- и многое, многое другое
Итак, вернёмся к истории. Когда мы встали на этот путь, то было несколько ожесточённых дебатов о том, куда мы идём, что должно быть главным и т. д. Вы же знаете, у разработчиков никогда нет мнения. :) Не было никакого способа решить всё сразу, не потерпев неудачу, поэтому мы согласились начать с трёх проблем:
- Планирование работы
- Контроль исходного кода
- Сборка
Не хочу подробно вдаваться в причины, кроме того, что это фундаментальные основы, а многое другое интегрируется с ними, строится на них, так что имеет смысл выбрать для начала именно три эти проблемы. Замечу также, что у нас были ОГРОМНЫЕ неприятности с временем сборки и надёжностью из-за размера наших продуктов — некоторые программы состоят из сотен миллионов строк кода.
Со временем эти три главные темы разрослись, так что инициатива 1ES в различной степени затронула почти все аспекты нашего процесса разработки.
Мы сделали несколько интересных ставок. Среди них:
За облаком будущее — Большая часть нашей инфраструктуры и инструментов размещаются локально (в том числе TFS). Мы согласились, что будущее за облаком — мобильность, управление, эволюция, эластичность, все причины, которые могут прийти на ум. Несколько лет назад это было очень спорным. Как Microsoft может перенести всю свою интеллектуальную собственность в облако? Что насчёт производительности? Что насчёт безопасности? Надёжности? Соблюдения правовых норм и управления? Что насчёт… Понадобилось время, но в конце концов набралась критическая масса согласных с идеей. Спустя годы это решение становилось более и более понятным, и сейчас все в восторге от переезда в облако.
Первое лицо == третье лицо — Такое выражение (1st party == 3rd party) мы используем внутри компании. Оно означает, что мы в максимальной степени стремимся использовать свои коммерческие продукты — и наоборот, продавать продукты, которые сами используем. Не всегда получается на 100% и это не всегда параллельный процесс, но таково направление движения — предположение по умолчанию, пока не появится хорошая причина поступать иначе.
Visual Studio Team Services лежат в основе — Мы сделали ставку на Team Services как основу. Нам нужна ткань, объединяющая воедино всю нашу систему разработки — центральный хаб, откуда вы всё узнаете и всего достигаете. Хаб должен быть современным, обильным, расширяемым и т. д. Каждая группа должна иметь возможность вносить свой вклад и делиться своими особенными вкладами в систему разработки. Team Services отлично подходят на эту роль. За последний год аудитория этих сервисов в Microsoft выросло с пары тысяч человек до более 50 000 преданных пользователей. Как и с TFS, не каждая группа использует их для всего возможного, но импульс в этом направлении наблюдается сильный.
Планирование работы Team Services — Выбрав Team Services, было довольно естественным выбрать соответствующие возможности по планированию работы. Мы загрузили группы вроде группы Windows, с многими тысячами пользователей и многими миллионами рабочих элементов, в единый аккаунт Team Services. Чтобы всё заработало, по ходу дела пришлось произвести немалую работу по производительности и масштабированию. В данный момент практически каждая группа в Microsoft осуществила этот переход и вся наша разработка управляется через Team Services.
Оркестровка Team Services Build и CloudBuild — Не буду слишком глубоко копать эту тему, потому что она гигантская сама по себе. Скажу только о результате, что мы выбрали сервис Team Services Build в качестве нашей системы оркестровки операций сборки, а управление Team Services Build в качестве нашего пользовательского интерфейса. Мы также разработали новый “make-движок” (который пока не выпустили) для некоторых из самых больших кодовых баз, он поддерживает тонко настроенное кэширование в большом масштабе, параллельное выполнение и инкрементальность, то есть поэтапное выполнение. Мы видели, как многочасовая сборка иногда сокращалась до минут. Подробнее об этом как-нибудь расскажем в будущей статье.
После большой предыстории — к самому главному.
Git для управления исходным кодом
Наверное, самое спорное решение мы приняли по поводу системы управления исходным кодом. У нас была внутренняя система под названием Source Depot, которую абсолютно все использовали в начале 2000-х. Со временем TFS и её решение Team Foundation Version Control получили популярность в компании, но так и не смогли проникнуть в самые крупные группы разработки — такие как Windows и Office. Думаю, здесь много причин. Одна из них в том, что для таких больших коллективов цена перехода оказалась чрезвычайно высокой, а две системы (Source Depot и TFS) не настолько сильно отличались, чтобы оправдать её.
Но системы контроля версий порождают интенсивную лояльность — больше, чем любой другой инструмент разработчика. Так что схватка между сторонниками TFVC, Source Depot, Git, Mercurial и других была жестокой, и если честно, мы сделали выбор, так и не придя к консенсусу — это просто должно было случиться. Мы решили сделать стандартом в компании Git по многим причинам. Со временем это решение получало всё больше и больше сторонников.
Против выбора Git тоже было много аргументов, но самым железобетонным было масштабирование. Существует не так много компаний с кодовой базой нашего размера. В частности, Windows и Office (есть и другие) имеют массивный размер. Тысячи разработчиков, миллионы файлов, тысячи машин для сборки, которые постоянно работают. Честно говоря, это поражает воображение. Чтобы внести ясность, когда я упоминаю здесь Windows, я имею в виду все версии — это Windows для PC, Mobile, Server, HoloLens, Xbox, IOT и так далее. А Git — распределённая система контроля версий (DVCS). Она копирует весь репозиторий и всю его историю на вашу локальную машину. Сделать это с проектом Windows было бы смешно (и мы очень смеялись в первое время). Как TFVC, так и Source Depot тщательно настраивались и оптимизировались для больших кодовых баз и конкретных групп разработчиков. Git никогда не применяли для такой задачи (или даже в пределах одного порядка от неё), и многие утверждали, что система никогда не заработает.
Первый большой спор был — сколько репозиториев заводить, один для всей компании или по одному для каждого маленького компонента? Большой диапазон. Git доказал свою исключительно хорошую работу для очень большого количества скромных репозиториев, так что мы потратили немало времени, думая над разбиением наших объёмных кодовых баз на большое количество репозиториев умеренного размера. Хм-м-м. Когда-нибудь работали с огромной кодовой базой в течение 20 лет? Когда-нибудь пробовали впоследствии вернуться назад и разбить её на маленькие репозитории? Можете догадаться, к какому ответу мы пришли. Этот код очень сложно разобрать на части. Цена будет слишком велика. Риски от такого уровня смешения станут чудовищными. И у нас действительно есть сценарии, когда единственному инженеру требуется произвести радикальные изменения в очень большом объёме кода. Координировать это между сотнями репозиториев будет очень проблематично.
После длительного выкручивания рук мы решили, что наша стратегия должна быть «Правильное количество репозиториев, в зависимости от природы кода». Некоторый код можно выделить (как микросервисы) и он идеально подходит для изолированных рпепозиториев. Некоторый код нельзя разделить на части (как ядро Windows) и его нужно воспринимать как единый репозиторий. И я хочу подчеркнуть, что дело не только в сложности разбиения кода на части. Иногда в больших связанных друг с другом кодовых базах действительно лучше воспринимать эту кодовую базу как единое целое. Может быть когда-нибудь я расскажу историю о попытках группы Bing выделить компоненты ключевой платформы Bing в отдельные пакеты — и о проблемах версионности, с которыми они столкнулись. Сейчас они уходят от этой стратегии.
Таким образом, нам пришлось приступать к масштабированию Git для работы на кодовых базах с миллионами файлов в сотни гигабайт и используемых тысячами разработчиков. Кстати говоря, даже Source Depot никогда не масштабировали на всю кодовую базу Windows. Её разбили более чем на 40 репозиториев, чтобы иметь возможность масштабировать. Но сверху надстроили слой, так что в большинстве случаев кодовую базу можно было воспринимать как единое целое. Такая абстракция не была идеальной и определённо вызвала некоторые разногласия.
Мы неудачно начинали масштабировать Git по крайней мере двумя способами. Вероятно, самой значительной стала попытка использовать подмодули Git, чтобы сшить воедино множество репозиториев в единый «супер-репозиторий». Не буду вдаваться в детали, но после 6 месяцев работы над проектом мы поняли, что он не будет функционировать — слишком много граничных ситуаций, высока сложность, проект слишком хрупкий. Нам нужно было проверенное надёжное решение, которое бы хорошо поддерживалось почти всеми инструментами Git.
Почти год назад мы вернулись к началу и сконцентрировались на вопросе, как в реальности масштабировать Git до единого репозитория, вмещающего целую кодовую базу Windows (в том числе оценки для роста и историю), и как поддерживать всех разработчиков и машины для сборки.
Мы попробовали «виртуализацию» Git. Обычно Git скачивает всё при клонировании. Но что если нет? Что если мы сделаем виртуализацию хранения, чтобы он скачивал только нужные части. Таким образом клонирование объёмного репозитория в 300 ГБ становится очень быстрым. По мере того как я у себя ввожу команды на чтение/запись, система незаметно подгружает контент из облака (а затем хранит его локально, так что в будущем доступ к данным осуществляется локально). Единственная отрицательная сторона здесь в потере поддержки офлайновой работы. Для этого нужно «прикоснуться» ко всему, чтобы оставить манифест для локальной работы, в остальном ничего не меняется — вы по-прежнему получаете на 100% верный опыт работы с Git. И для наших огромных кодовых баз такой вариант с виртуализацией был приемлемым.
Это был перспективный подход, и мы начали разрабатывать прототип. Мы назвали проект Git Virtual File System или GVFS. Мы поставили цель совершить минимум изменений в git.exe. Конечно, мы не хотели форкать Git — это было бы катастрофой. И не хотели изменять его настолько, чтобы сообщество никогда не приняло эти изменения. Так что мы выбрали промежуточный путь, в котором максимальное количество изменений производится «под» Git — в драйвере виртуальной файловой системы.
Драйвер виртуальной файловой системы в основном виртуализирует две вещи:
- Папку .git, где хранятся все пакетные файлы, история и т. д. Это папка для всего по умолчанию. Мы виртуализировали её, чтобы вытягивать только нужные файлы и только когда нужно.
- «Рабочую директорию» — место, куда вы идёте, чтобы реально отредактировать исходный код, собрать его и т. д. GVFS отслеживает рабочую директорию и автоматически «проверяет» каждый файл, к которому вы прикасаетесь, создавая впечатление, что все файлы реально находятся там, но не требуя ресурсов, пока вы на самом деле не запросите доступ к конкретному файлу.
По мере продвижения нашей работы, как вы можете представить, мы многое узнали. Среди прочего, мы узнали, что сервер Git должен быть умным. Он должен паковать файлы Git наиболее оптимальным образом, чтобы не отправлять клиенту больше, чем ему действительно необходимо — представьте это как оптимизацию локальности ссылок. Так что мы сделали много улучшений в Git-сервере Team Services/TFS. Мы также обнаружили, что у Git много сценариев, когда он трогает файлы, которых не должен трогать. Раньше это никогда не имело значения, потому что всё хранилось локально, а Git использовали в репозиториях среднего размера, так что он работал очень быстро — но если трогать всё, то придётся скачивать с сервера или сканировать 6 000 000 файлов, это не шутка. Так что мы потратили много времени на оптимизацию производительности Git. Многие из сделанных нами оптимизаций принесут выгоду «нормальным» репозиториям в какой-то степени, но эти оптимизации являются критическими для мега-репозиториев. Мы отправили многие из этих улучшений в проект Git OSS и получили удовольствие от хорошего сотрудничества с ними.
Итак, быстро перенесёмся в наши дни. Всё работает! Мы вместили весь код с более чем 40 серверов Windows Source Depot в раках единого репозитория Git, размещённого в VS Team Services — и он хорошо себя проявляет. Вы можете зайти (enlist) за пару минут и проделать все свои обычные операции в Git в течение секунд. И во всех смыслах это прозрачный сервис. Просто Git. Ваши разработчики продолжат работать как работали, используя те инструменты, которые использовали. Ваши сборки просто работают, и т. д. Это просто удивительно. Магия!
В качестве сопутствующего эффекта, такой подход хорошо отразился на больших бинарных файлах. Он не расширяет Git с помощью нового механизма, как делает LFS, никаких «выделений» и тому подобного. Вы можете работать с большими бинарными файлами как с любыми другими файлами, но при этом скачиваются только те блобы, которые вы затронули.
Git Merge
На конференции Git Merge в Брюсселе Саид Нурсалехи (Saeed Noursalehi) поделился с миром тем, что мы делаем — в том числе мучительными деталями сделанной работы и того, что мы поняли. Одновременно мы выложили всю нашу работу в open source. Мы также включили несколько дополнительных серверных протоколов, которые нужно было представить. Можете найти проект GVFS и все изменения, сделанные в Git.exe, в репозиториях Microsoft GitHub. GVFS полагается на новый драйвер фильтра Windows (моральный эквивалент драйвера FUSE в Linux), и мы поработали с группой Windows, выпустив этот драйвер пораньше, чтобы вы могли попробовать GVFS. Дополнительную информацию и ссылки на дополнительные ресурсы см. в посте Саида. Можете изучить их. Можете даже установить GVFS и опробовать её.
В то время как я отмечаю работоспособность GVFS, хочу подчеркнуть, что ещё многое предстоит сделать. Мы не всё закончили. Думаем, что доказали концепцию, но всё ещё предстоит большая работа, чтобы воплотить её в жизнь. Мы делаем официальный анонс и публикуем исходный код, чтобы привлечь сообщество к совместной работе. Все вместе мы сможем масштабировать Git для самых больших кодовых баз.
Извините за длинный пост, надеюсь, он был интересным. Я в восторге от проделанной работы — как в рамках инициативы 1ES в Microsoft, так и над масштабированием Git.
Автор: m1rko