Меня нередко спрашивают “а как сделать свой первый PR”, ответ простой — просто сделай. Но я хочу написать серию заметок о культуре open source и о том, как сделать жизнь удобной для всех. Сегодня разберём кейс, с которым я столкнулся вчера, а именно — множественные изменения в одну полузаброшенную репу.

TL;DR

Когда готовите большой рефакторинг в open source проекте:

  1. Дробите на маленькие логические PR — снижает когнитивную нагрузку на ревьювера
  2. Предлагайте integration branch для координации — позволяет review’ить инкрементально и делать пакетные изменения
  3. Если есть сомнения, то не стесняйтесь связаться с командой заранее — открытость и коммуникация важны
  4. Будьте готовы к итерациям — 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:

  1. Maintainer создаёт ветку v3.0-integration от master
  2. Я rebase’ю все 10 PR’ов на эту ветку
  3. Команда review’ит каждый PR отдельно
  4. Все PR’ы мержатся в v3.0-integration, не в master
  5. После мерджа всех PR делаем общие пакетные изменения в интеграционной ветке:
    • Пишем тесты (helm-unittest)
    • Подготавливаем values.schema.json валидацию
    • Переписываем README с учётом всех новых фич
    • Формируем единый changelog для v3.0.0
    • Добавляем примеры конфигураций
  6. Когда всё готово и протестировано, v3.0-integration мержится в master как v3.0.0

Зачем это нужно?

Изоляция: Не ломаем master во время разработки. Пользователи на стабильной версии, мы эксперементируем в интеграционной ветке.

Инкрементальный review: Каждый PR маленький и понятный. Ревьювер может review’ить по одному в день, не перегружаясь.

Тестирование целого: После мерджа всех PR можно протестировать v3.0-integration как единое целое. Если что-то не работает вместе — легко найти и исправить.

Откат: Если конкретный PR вызывает проблемы, легко его исключить или переработать.

Прозрачность: Вся команда и сообщество видят прогресс. Можно комментировать каждую фичу отдельно.

Общие изменения: Можно делать пакетные действия, которые было бы неудобно делать в отдельных PR. Переписать документацию, подготовить changelog, написать тесты — всё это логично делать когда видишь картину целиком, после мерджа всех фич.

Это стандарт в крупных проектах

Linux kernel, Kubernetes, и другие большие проекты используют этот подход:

  • linux-next в kernel
  • staging branches в Kubernetes
  • integration или develop branches в 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 проекте:

  1. Дробите на маленькие логические PR
  2. Предлагайте integration branch для координации
  3. Объясняйте план команде заранее
  4. Будьте готовы к итерациям

Это снижает нагрузку на ревьюверов и повышает шансы на успешный merge.