Когда речь заходит об open source, многим часто кажется, что это некий закрытый элитарный клуб. Как будто где-то в далёких кабинетах сидят гениальные инженеры и пишут безупречный код, который, благодаря своему природному альтруизму, потом выкладывают бесплатно для общего пользования. Но на самом деле эта история не про «них». Это история про «нас». Про нас всех. Потому что прямо сейчас, используя и создавая open source, мы с вами участвуем в самой крупной задокументированной коллаборации в истории человечества.
Привет. Меня зовут Даниил Липаткин, я тимлид в Яндекс Доставке — мы делаем приложение Яндекс Про для курьеров и водителей. А ещё я контрибьютор и член core-команды Flutter и вы тоже можете им стать.
В этой статье я расскажу, как выстроен процесс контрибьюта на примере репозитория Flutter. Мы пройдём весь цикл — от локальной настройки окружения до готового влитого пулл-реквеста. Я покажу эту внутреннюю кухню от первого лица на реальных примерах своего инженерного опыта. Разберём конкретные кейсы: от того, как статус контрибьютора выручил меня в самый неожиданный момент, до истории о том, за что я чуть не оказался забанен во Flutter навсегда.
С чего начать
Самое сложное всегда — это сделать первый шаг. Когда смотришь на репозиторий с миллионами строк кода, кажется, что подступиться к нему невозможно. Страшно случайно сломать функциональность тысячам пользователей или написать откровенно плохой пулл-реквест. Но на практике всё обычно наоборот: интегрироваться в такой большой проект чаще проще, чем в маленький.

В масштабных экосистемах выстроены строгие и понятные процессы. Там работает настроенная автоматизация, которая отловит баги на этапе CI. Есть регулярное код-ревью — ваш пулл-реквест или заведённая задача точно не останутся осиротевшими, мейнтейнеры обязательно придут и дадут обратную связь.
Кстати, чтобы вам было ещё проще, я собрал все самые нужные и важные ссылки из этого материала в одном месте, чтобы вам не пришлось долго их искать. Там на самом деле много всего полезного, обязательно загляните.
А начинается всё с поиска правильной задачи
Проще всего начинать контрибьютить с того, чем пользуешься сам. Наверняка у вас есть давняя боль, нерешённая проблема или идея для улучшения, до которой никак не доходили руки. Именно личная боль сильно упрощает вход — у вас появляется чёткая цель, а изучение архитектуры чужого проекта становится лишь средством её достижения.
Если конкретной проблемы для исправления нет, выручают лейблы. Например, мейнтейнеры Флаттера специально помечают простые тикеты тегами good first issue или help wanted. На момент подготовки этого текста в баг-трекере висело около 50 таких открытых задач. Выбираете любую, пишете в комментариях о желании взять её в работу — чтобы параллельно за неё не взялся другой разработчик — и приступаете.

Здесь же стоит развеять ещё одно популярное заблуждение. Часто кажется, что контрибьют — это исключительно хардкорная разработка новой логики. Но на деле поддержание крупного проекта требует огромного количества смежных активностей. Вы можете принести пользу, вообще не касаясь исходного кода.
Любое ваше участие — это уже вклад. Можно поправить неточность в документации или дополнить её понятными примерами. Можно прийти в комментарии к чужому пулл-реквесту и провести код-ревью. Опенсорс-проектам всегда не хватает людей, готовых просто руками протестировать чужие изменения в релиз-кандидате.
Даже грамотно заведённая задача в баг-трекере с подробными шагами воспроизведения и логами — это уже половина решения. А если у вас есть технический блог, вы можете помочь проекту, просто рассказывая о нём и развивая сообщество. Начать путь в open source с таких форматов гораздо проще.
Но если вы всё-таки решили писать код, придётся разобраться с инфраструктурой. Подготовка окружения — этап душный, но необходимый, и он напрямую зависит от зоны вашей ответственности. И здесь главным навигатором выступает файл CONTRIBUTING.md, который я очень советую изучить. Именно в нём мейнтейнеры пошагово описывают, как настроить окружение, написать код и пройти ревью. У Флаттера есть две развилки контрибьюта.

Правки во Flutter Framework Это базовый путь. Вы делаете классический форк репозитория, клонируете его и настраиваете ремоуты для пуша коммитов. Из специфичных шагов — нужно прописать пути в переменных окружения. Это необходимо, чтобы тестовая сборка вашего приложения начала подтягивать именно склонированную локальную версию фреймворка, а не глобальную. Дальше прогоняете получение зависимостей во всех подпакетах и просто открываете код Flutter в привычной IDE.
Правки во Flutter Engine
Маршрут для хардкорщиков, которые хотят писать нативный код движка. К базовым шагам здесь добавляется работа со специфическими тулчейнами. Сначала нужно настроить утилиту gclient для выкачивания нативных C++ зависимостей. Затем развернуть Engine Tool для сборки движка прямо на вашей машине и прописать конфигурацию в редакторе для подсветки нативного синтаксиса.
В финале всё это связывается через утилиту flutter_tool — чтобы локально собранный Flutter Engine интегрировался в сборки ваших тестовых приложений. Оба пайплайна подробно задокументированы мейнтейнерами, поэтому процесс сводится к аккуратному выполнению инструкций.
И как только окружение готово, начинается этап работы над задачей. Глобально он состоит из тех же шагов, к которым мы все привыкли: вы исследуете баг или консультируетесь с экспертами, пишете код и покрываете его тестами. Процесс разработки ничем не отличается от ваших повседневных рабочих тасок. Всё самое интересное начинается на этапе слияния.
Как не надо делать
Даже если вы написали безупречный код, он может никогда не попасть в релиз. В крупных репозиториях действуют строгие регламенты, которые важнее красоты архитектуры. У Флаттера все правила собраны в отдельном документе Tree Hygiene — он описывает жизненный цикл задачи от написания тестов до ответственности контрибьютора за налитый пулл-реквест.

Если игнорировать эти стандарты, ваш код превратится в мёртвый груз. Вот три реальных сценария из моего опыта, которые запросто могут легко похоронить полезный коммит.
1. Игнорирование кастомных политик breaking change
В небольших проектах всё прозрачно — вы внесли ломающее изменение, подняли мажорную версию по правилам SemVer и задекларировали этот факт. Во Флаттере семантическое версионирование не используется вообще, несмотря на привычный формат релизных версий с тремя числами. Для ломающих изменений действует отдельная сложная политика.
Если ваши правки масштабные, придётся заранее написать дизайн-документ. У Flutter для этого есть специальный шаблон и свой процесс согласования. В таком документе вы описываете архитектуру будущего решения, что сильно упрощает жизнь ревьюерам и бережёт ваши собственные нервы на этапе приёмки кода.
Однажды я внёс правки в core-логику компонента Scroll. Код успешно прошёл ревью и налился в master. Я уже успел получить свою дозу дофамина от закрытой задачи, но радость была недолгой. После налития мастер покраснел — моё изменение разломало посткомитные проверки.
Мейнтейнерам пришлось откатить пулл-реквест. Чтобы залить его заново, мне нужно было переделать работу с учётом всех политик для ломающих изменений. Мотивации возвращаться к уже по сути выполненной задаче у меня тогда не нашлось, и этот пулл-реквест так и остался закрытым.
2. Ловушка автоформаттера
Каждый проект имеет свой уникальный стиль кодирования. У Флаттера стайл-гайд занимает несколько тысяч строк. Полностью осознать его за пару вечеров у вас, конечно же, не получится, но короткую выжимку знать всё-таки необходимо.
Долгое время в этом гайде чёрным по белому было написано: «код редактируется руками». Использование автоформаттеров строго запрещалось. Многие внешние разработчики пропускали этот пункт. Они писали полезную логику, по привычке прогоняли файл через автоформаттер и пушили результат. В итоге пулл-реквест засорялся сотнями изменённых отступов. Ревьюерам приходилось заворачивать коммиты и просить авторов вручную откатывать форматирование.
К счастью, сегодня это правило отменили. Репозиторий всё же переехал на автоформаттер с дополнительными кастомными настройками поверх дефолтных. Но сам кейс отлично показывает, почему перед отправкой кода полезно хотя бы бегло просмотреть локальный стайл-гайд.
3. Отказ от декомпозиции
При работе над локальным багом всегда возникает соблазн попутно исправить соседнюю проблему или отрефакторить старый кусок логики. На этапе написания кода это кажется очень даже благим делом.
Но когда вы открываете пулл-реквест, мейнтейнер справедливо просит разбить большой комок кода на независимые части. У меня было несколько таких коммитов, где ревьюер писал: «Это не просто классно, а эпически! Но давай ты декомпозируешь». А мне снова возвращаться к коду и тратить время на отделение зёрен от плевел как-то не хотелось. В итоге все эти эпические пулл-реквесты точно так же остались лежать невлитыми. Так что мой вам совет: делите задачу прямо по ходу работы — это сильно повышает шансы на успешный мёрж.
Софт-скиллы тут тоже нужны
В open source, как, наверное, и во многих других сферах нашей жизни, техническая правота вовсе не даёт никому права игнорировать элементарные правила общения. Для регулирования этих правил во Flutter существует универсальный для всего open source коммьюнити стандарт — Code of conduct, в котором описано, как следует решать любые спорные ситуации.
Приведу пример из собственного опыта. Когда я только начал контрибьютить во Флаттер, то сфокусировался исключительно на коде. О правилах ведения дискуссий я вообще не думал, просто общался с людьми, как мне тогда казалось, вполне нормально. Однако спустя какое-то время мне на почту приходит письмо от техлида проекта, в котором он буквально по частям разбирает мои комментарии в тредах пулл-реквестов:
- первая ссылка — здесь ты ответил токсично;
- вторая ссылка — тут ты не воспринял конструктивную критику;
- у ревьюеров сложилось неприятное впечатление от работы с тобой.
А в конце письма заботливо предупреждает, что если подобный тон сохранится, то меня раз и навсегда забанят в репозитории. У меня совершенно не было цели задеть чьи-то чувства. Всё, чего я хотел на тот момент, — побыстрее продвинуть свой код до продакшена. И тем не менее, этот эпизод в очередной раз напоминает нам важное правило — по ту сторону монитора ревью проводят точно такие же живые люди. Естественно, я прислушался к предупреждению и стал гораздо внимательнее следить за формулировками.
Не знать чего-то – абсолютно нормально
Инженерная культура бигтеха поощряет и даже в какой-то мере защищает процесс обмена знаниями. В том же Code of conduct Flutter есть показательная иллюстрация того, как нужно выстраивать коммуникацию — комикс про ментос и колу.

Суть принципа проста — никогда не высмеивайте коллег за то, что они признаются в незнании. Любые базовые концепции, которые вам самим кажутся очевидными, вы тоже когда-то узнали впервые. Никто не рождается с этим знанием, люди обычно узнают вещи в процессе работы и жизни.
Суть примера из руководства Флаттера в том, что если другой разработчик спрашивает вас, что за известный прикол с ментосом и колой, у вас есть два варианта реакции:
- Первый — поднять его на смех. Итог предсказуем — вы приучите человека скрывать свои пробелы. Он закроется и больше никогда не придёт к вам с вопросами, а вы сами пропустите всё веселье.
- Второй — отреагировать адекватно. Сказать коллеге: «Пойдём-ка в магазин, купим Ментоса и колы и ты увидишь нечто очень интересное».
Такой подход формирует прозрачную и доверительную среду. Люди не боятся подсвечивать какие-то пробелы в своих знаниях, команда быстрее синхронизирует контекст, а обсуждения в пулл-реквестах не скатываются во взаимные обвинения. Это нормальный человеческий подход, который отлично работает не только в open source, но и в рабочих пайплайнах любой продуктовой команды.
Вклад в вечность
Бывает так, что довольно ощутимый вклад в глобальные проекты часто начинается с решения банального локального бага. Так случилось и у меня. В 2020 году я писал собственный музыкальный плеер, в котором был разворачивающийся экран с анимацией. И меня по какой-то причине очень не устраивала скорость этой анимации — она казалась то слишком быстрой, то чересчур медленной. Я полез в настройки фреймворка, чтобы просто поменять параметры, но неожиданно упёрся в системное ограничение.

Оказалось, что для реализации таких жестов во Флаттере существовало два базовых метода, и оба мне не подходили:
- Метод
fling— отлично отрабатывал свайпы, но не позволял задать кастомные параметры симуляции. - Метод
animateWith— принимал нужные конфигурации, но содержал баг. Он некорректно репортил статус вAnimationController. Из-за этого приложение не могло отличить направление движения — сворачивается экран или разворачивается.
Последний оставшийся вариант — лезть в ядро и дорабатывать fling. Немного покопавшись в исходниках, я понял схему исправления. Требовалось просто пробросить один опциональный параметр SpringDescription, который заменял дефолтную симуляцию внутри метода на пользовательскую.
class AnimationController {
TickerFuture fling({
double velocity = 1.0,
AnimationBehavior? animationBehavior,
+ SpringDescription? springDescription,
});
TickerFuture animateWith(Simulation simulation);
void addStatusListener(AnimationStatusListener listener);
}
enum AnimationStatus {
/// The animation is stopped at the beginning.
dismissed,
/// The animation is running from beginning to end.
forward,
/// The animation is running backwards, from end to beginning.
reverse,
/// The animation is stopped at the end.
completed,
}
Я написал реализацию и открыл пулл-реквест. Весь коммит уложился примерно в 50 строк. При этом полезной нагрузки там оказалось ровно 8 строк. Остальные строки ушли на обновление документации и тесты.
Перед слиянием оставалось чекнуть Pre-launch Checklist от мейнтейнеров и подписать CLA — юридическое соглашение контрибьютора с Google. Это базовая процедура, которая занимает пять минут и делается один раз. Проверки позеленели, ревью было пройдено, код успешно влился в master. Я обновил версию Флаттера, настроил свою анимацию и забыл об этой задаче.
Но код в open source живёт по своим правилам. Спустя почти пять лет, при подготовке доклада для выступления, я решил посмотреть, кто-нибудь вообще использует этот параметр кроме меня. И статистика меня приятно удивила.
Мою доработку затянули к себе авторы других проектов ровно для таких же интерфейсных кейсов:
- Пакет flutter_map — самое популярное решение для показа карт во Флаттере с более чем 3 тысячами звёзд на GitHub.
- Пакет accordion — инструмент для создания разворачивающихся списков.
- Ещё шесть репозиториев поменьше.

Восемь строк кода, которые я написал ради плавной анимации в пет-проекте, прямо сейчас крутятся на сотнях миллионов пользовательских девайсов по всему миру. А ещё работа с open source даёт шанс в прямом смысле оставить след в истории. Например, в 2020 году GitHub сделал глобальный бэкап открытых репозиториев и захоронил его в вечной мерзлоте Шпицбергена по программе Arctic Code Vault. Конкретно мой пулл-реквест в тот архив немного не успел, но само существование таких программ отлично показывает масштаб. Ваш код буквально становится общим наследием человечества. И именно это чувство прочно подсаживает на контрибьют.
Так зачем нам всем open source?
Когда долго работаешь в индустрии, наступает момент, когда формируется некая внутренняя потребность «возвратить долги сообществу», на технологиях которого мы все строим свои продукты.
Такой инженерный альтруизм очень часто окупается и возвращается вам обратно порой совершенно неожиданными путями. И речь тут не только про усиление резюме или статус члена core-команды, хотя и это уже немало. Иногда это может выражаться в официальном признании — например, в виде премий от крупных компаний и некоммерческих организаций. А иногда способно принести и вполне реальную пользу в быту. Как-то, ещё будучи студентом, я умудрился проспать экзамен по мобильной разработке. Пишу преподавателю сообщение с извинениями и обещанием примчаться через полчаса, а в ответ получаю:
Всё в порядке. Контрибьюторам во Флаттер зачёт автоматом»
Преподаватель просто заглянул в репозиторий и оценил реальный практический опыт.
На одном энтузиазме разработчиков экосистему не построить
Зачем крупному бизнесу вообще тратить оплачиваемые часы инженеров на open source? На первый взгляд кажется, что компания просто так отдаёт свои проприетарные наработки.
На деле это чистый прагматизм. Открытый код снижает издержки и ускоряет инновации. Вы выкладываете внутренний инструмент в публичный доступ, сообщество начинает им пользоваться и приносить пулл-реквесты. Внешние разработчики находят баги, закрывают уязвимости и дописывают фичи. В итоге компания абсолютно бесплатно получает прокачанный продукт и экономит часы собственной команды на разработку и развитие. И конечно, это формирует сильный HR-бренд — инженерам нравится работать в местах, где поддерживают культуру прозрачной разработки.
По такому пути идём и мы в Яндексе. Например, когда нам потребовался DI-фреймворк для работы со скоупами во Флаттере — похожий на Dagger в Android — мы написали yx_scope. Позже появился инструмент для управления состояниями yx_state. Мы решили свои архитектурные задачи и сразу выложили библиотеки в открытый доступ, чтобы они появились у всего комьюнити.
Для меня лично работа с open source — это эстетическое удовольствие от решения сложных интеллектуальных задач. Это история про полную автономию: вы сами вольны выбирать, что, как и когда улучшать, сами определяете рамки своей ответственности. Вы приносите пользу себе, своему бизнесу и огромному рынку. Если вы никогда не пробовали контрибьютить — уделите этому пару вечеров. Найдите баг в библиотеке, с которой работаете каждый день, загляните в баг-трекер и откройте свой первый пулл-реквест.
Кто знает, возможно, именно ваш коммит завтра станет стандартом индустрии.




