Меня нередко спрашивают “а как сделать свой первый PR”, ответ простой — просто сделай. Но я хочу написать серию заметок о культуре open source и о том, как сделать жизнь удобной для всех. Сегодня разберём кейс, с которым я столкнулся вчера, а именно — множественные изменения в одну полузаброшенную репу.
TL;DR
Когда готовите большой рефакторинг в open source проекте:
- Дробите на маленькие логические PR — снижает когнитивную нагрузку на ревьювера
- Предлагайте integration branch для координации — позволяет review’ить инкрементально и делать пакетные изменения
- Если есть сомнения, то не стесняйтесь связаться с командой заранее — открытость и коммуникация важны
- Будьте готовы к итерациям — open source это про людей
Это снижает нагрузку на ревьюверов и повышает шансы на успешный merge.
Ситуация
Хотел попробовать Jellyfin для домашнего медиа-сервера. Зашёл в jellyfin/jellyfin-helm, посмотрел на чарт и понял — в текущем виде не пригоден для использования. Плюс моя личная война с Ingress — надо добавить хотя бы Gateway API поддержку.
Команда Jellyfin добавила Helm chart по просьбе сообщества, но у них просто нет ресурсов и экспертизы в Helm для активного обслуживания. Это нормальная ситуация — нельзя быть экспертом во всём.
Открыл issue #94 с предложением комплексного обслуживания и перечислением того, что хочу улучшить.
Пять вариантов действий
1. Пройти мимо
Не вариант. Я хочу это использовать, а чарт в текущем виде не работает для моих нужд.
2. Форкнуть и поддерживать у себя
Easy win — делаешь что хочешь, публикуешь свой чарт. Но хоть я и публикую свои чарты, люди в первую очередь смотрят на официальные, а уже потом на “народные”. Значит, проблемы останутся для сообщества.
3. Один большой PR
15 файлов изменено, 500+ строк кода, breaking changes смешаны с фичами.
Когда это уместно: Только когда изменения настолько большие, что нет смысла пытаться протащить это по чуть-чуть. Плюс если команда сильная технически и готова review’ить большие изменения. Если есть автотесты, покрывающие критичные части. Если изменения концептуально связаны и разделить их сложно.
Для этого репо не подходит: У них не хватает ресурсов даже майский PR проверить (кстати, это антипаттерн, расскажем дальше). Команда просто не осилит гигантский diff. Ревьювер смотрит на 500 строк и думает: “Что вообще происходит? Зачем эта строка? Это связано с той фичей или с этой?”
Результат: Либо “LGTM” не глядя, либо полгода висит без внимания, либо долгие споры в комментариях.
4. Попроситься в мейнтейнеры
Можно сразу попроситься в команду и править напрямую. Но это требует доверия, которого пока нет. Плюс всё равно нужен review процесс — нельзя просто коммитить в master.
Вердикт: Уже предложил в issue, но повторю после того как покажу себя в деле.
Кстати, это полезно и работает на репутацию. А поддержка чарта не отнимает слишком много сил, если выстроить CI, linting и т.д. — реагируй на нотификации в GitHub и готово. Для подобных чартов это раз в полгода обычно. Я уже поддерживаю несколько community чартов помимо своих.
5. Много маленьких PR
Это я и выбрал.
Почему 10 отдельных PR
Главная причина: снижение когнитивной нагрузки на ревьювера.
Один большой PR:
# deployment.yaml
+ {{- if .Values.gateway.enabled }}
+ kind: HTTPRoute
...
+ {{- if .Values.persistence.cache.enabled }}
+ - name: cache
...
+ {{- if .Values.extraInitContainers }}
- {{- if .Values.initContainers }}
...
+ startupProbe:
+ httpGet:
...
Ревьювер смотрит и думает: “Что это за блок? Gateway API? Persistence? Init containers? Startup probe? Как они связаны? Можно ли убрать вот это без поломки того?”
Множество отдельных PR:
- PR #86: Gateway API support — весь код про HTTPRoute, ничего больше
- PR #87: IPv6 configuration — только IPv6, всё очевидно
- PR #88: Cache volume — только про cache, понятная граница
- PR #92: Startup probe — один блок кода, одна фича
- PR #93: Fix initContainers — ясная проблема, ясное решение
Каждый PR содержит одну законченную фичу или один багфикс.
Ревьювер открывает PR #86, видит только Gateway API код. Всё понятно: “Ок, это добавляет HTTPRoute. Логика правильная, approve.”
Не надо догадываться, какой кусок кода за что отвечает.
Важно: не дробить слишком мелко
Не надо делать PR на 2-3 мелких изменения типа:
- PR #1: “Добавил одну переменную”
- PR #2: “Добавил вторую переменную”
- PR #3: “Использовал эти переменные”
Это уже перебор. Один PR должен быть одной законченной фичей или одним багфиксом.
Можно делать один огромный PR в духе “я весь мир переписал, вот что случилось: 1, 2, 3, 4, 5… 128, 129”, но тогда пиши в описании детальный список изменений и будь готов к долгому review.
Integration Branch: как это работает
Но не релизить же нам 10 версий чарта просто потому что я решил его причесать? И тут на помощь приходит подход из GitFlow — интеграционная ветка.
Предложил команде Jellyfin такой workflow:
- Maintainer создаёт ветку
v3.0-integrationот master - Я rebase’ю все 10 PR’ов на эту ветку
- Команда review’ит каждый PR отдельно
- Все PR’ы мержатся в
v3.0-integration, не в master - После мерджа всех PR делаем общие пакетные изменения в интеграционной ветке:
- Пишем тесты (helm-unittest)
- Подготавливаем values.schema.json валидацию
- Переписываем README с учётом всех новых фич
- Формируем единый changelog для v3.0.0
- Добавляем примеры конфигураций
- Когда всё готово и протестировано,
v3.0-integrationмержится в master как v3.0.0
Зачем это нужно?
Изоляция: Не ломаем master во время разработки. Пользователи на стабильной версии, мы эксперементируем в интеграционной ветке.
Инкрементальный review: Каждый PR маленький и понятный. Ревьювер может review’ить по одному в день, не перегружаясь.
Тестирование целого: После мерджа всех PR можно протестировать v3.0-integration как единое целое. Если что-то не работает вместе — легко найти и исправить.
Откат: Если конкретный PR вызывает проблемы, легко его исключить или переработать.
Прозрачность: Вся команда и сообщество видят прогресс. Можно комментировать каждую фичу отдельно.
Общие изменения: Можно делать пакетные действия, которые было бы неудобно делать в отдельных PR. Переписать документацию, подготовить changelog, написать тесты — всё это логично делать когда видишь картину целиком, после мерджа всех фич.
Это стандарт в крупных проектах
Linux kernel, Kubernetes, и другие большие проекты используют этот подход:
linux-nextв kernelstagingbranches в Kubernetesintegrationилиdevelopbranches в GitFlow
Но почему-то в Helm-чартах это редкость. А зря — подход работает отлично.
Коммуникация с командой: обсуждайте заранее
Когда я понял, что открыл уже 6 PR и не планирую останавливаться, я связался с командой через Discord (именно этот способ связи указан на сайте проекта) и создал issue #94 для трекинга изменений:
- Что именно хочу изменить
- Почему это нужно
- Как предлагаю это сделать (integration branch)
- Какие breaking changes будут
Почему это важно:
Показываете уважение: Команда понимает, что вы не просто “накидали кода”, а продумали подход.
Получаете обратную связь: Может быть, команда скажет “не надо вот это” или “давайте лучше вот так”. Лучше узнать ДО написания кода.
Избегаете сюрпризов: Maintainer’ы не любят, когда внезапно прилетает 10 PR без предупреждения.
Как найти команду
Стандартная точка входа — Issue в репозитории, если репо живое и команда активна на GitHub.
Но если ситуация как у меня (репо полузаброшен, PR висят месяцами без review), можно попробовать:
1. Зайти через основной репозиторий проекта:
- Jellyfin Helm chart — это отдельная репа
- Основной проект — jellyfin/jellyfin
- Там может быть больше активности и ссылки на каналы связи
2. Искать способы связи за пределами GitHub:
Где искать:
- Официальный сайт проекта (обычно есть раздел Community/Contact)
- README основного репозитория
- Файл
CONTRIBUTING.md - Organization profile на GitHub
- Предыдущие issues/PRs (посмотрите, где обсуждают важные вопросы)
Популярные каналы:
- Discord — большинство современных open source проектов
- Matrix — FOSS-friendly альтернатива Discord
- Slack — корпоративные и enterprise проекты
- IRC — старые проекты (Linux kernel, многие GNU утилиты)
- Mailing lists — академические и крупные проекты (LKML, Apache)
В моём случае:
- На сайте Jellyfin указан Discord
- Я написал туда, объяснил ситуацию
- Получил быстрый ответ от maintainer Cody и одобрение подхода
Важно: Даже если команда не очень активна в чате, сам факт что вы попытались связаться показывает хорошие намерения. Команда оценит проактивность.
Lessons Learned
1. Маленькие PR снижают когнитивную нагрузку
Ревьювер не должен держать в голове весь контекст изменений. Один PR = одна фича = ясная граница.
2. Integration branch даёт безопасность
Можно экспериментировать, не боясь сломать production. Пользователи остаются на стабильной версии.
3. Открытость и коммуникация важны
Я не просто накидал PR’ов — я открыл issue, объяснил план, предложил workflow. Команда оценила и поддержала.
4. Open source — это про людей
Команда Jellyfin честно сказала: “У нас нет ресурсов на Helm chart, но мы рады помощи.” Это нормально. Проекты живут благодаря сообществу.
P.S. Если вы готовите большой рефакторинг в open source проекте:
- Дробите на маленькие логические PR
- Предлагайте integration branch для координации
- Объясняйте план команде заранее
- Будьте готовы к итерациям
Это снижает нагрузку на ревьюверов и повышает шансы на успешный merge.