Как законтрибьютить в опенсорс, чтобы не сгореть со стыда
Мы все используем опенсорсные продукты, но немногие решаются туда законтрибьютить. Помимо банальной лени, есть и более серьёзные причины: сложность или корявость самих проектов, а также боязнь показать миру свой код.
На осеннем TechTrain Андрей Солнцев (asolntsev) и Артем Ерошенко (eroshenkoam) показали на примере Allure и Selenide, как справиться с техническими и психологическими трудностями. Прямо во время доклада они сделали изменения в опенсорсных проектах.
Под катом — расшифровка их доклада и видео с фестиваля. Далее повествование будет от лица спикеров.
Зачем
Андрей: Начнем с простых вопросов, которые вам интересны. Зачем вам это нужно? Зачем люди занимаются опенсорсом?
Лично я занимаюсь опенсорсом, потому что мне это интересно. Все остальные ответы меркнут и не важны. Но можно найти другие ответы, если вам этого мало.
Занятие опенсорсными проектами — хорошая возможность прокачать скиллы.
Артём: Например, я очень много читаю код опенсорсных проектов вместо того, чтобы читать статьи. Я в основном делаю поиск по GitHub. Раньше я брал код из StackOverflow, вставлял его в свой код, и все работало. Сейчас я использую GitHub как источник примеров.
Например, недавно я искал, как настроить пайплайны в YAML Bamboo. Мне нужен был определенный пример конфигурации. Я нашел пример в документации — вам нужен такой-то класс. А примера, как его использовать, не было. Вставляете класс в GitHub, смотрите примеры, и у вас получаются хорошие ответы, которые можно сравнить и выбрать лучший.
Андрей: Я научился многим вещам благодаря тому, что занимаюсь опенсорсом: владению гитом, все эти ветки, мерджи, ребейзы.
Еще опенсорс — это отличная возможность прокачать свой профиль на GitHub. С тех пор, как я начал активно заниматься опенсорсом, меня заваливают вот такими письмами: «Привет, нам понравился твой профиль на GitHub, давай к нам».
Теоретически на GitHub можно заработать. Есть миллион способов, как большие компании зарабатывают на опенсорсе, но сейчас будем говорить о том, как могут зарабатывать отдельные личности. С недавних пор на GitHub появилась программа GitHub Sponsorship: на страничку любого человека или проекта можно зайти, и там будет кнопка спонсорства.
Вот пример чувака, который мне лично нравится. Он делает популярные библиотеки, у него есть страничка на GitHub, где он пишет, мол, вы наверняка в своих проектах используете мой продукт, и если вам не жаль, вы можете перевести мне денежек.
Артём: Скорее всего, у него есть основное место работы, он не заинтересован в большом количестве спонсоров. Но я знаю проекты, которые разрабатываются полностью в опенсорсе. Там люди не работают в других местах, и им нужно получать спонсорскую поддержку.
Андрей: Самый важный пункт для меня — самовыражение. Есть пирамида потребностей айтишника.
Физиология у айтишника покрывается зарплатой и печеньками. Безопасность покрывается комфортным офисом и удобным стулом. Любовь в айти — это преданность компании. Признание очень часто покрывается тем, что тебе говорят: «Дружище, поздравляем — теперь ты тимлид!» Для некоторых это важнее, чем повышение зарплаты.
А вот последний уровень — самоактуализация. Мне кажется, что опенсорс — отличный способ самовыражения. Может, даже единственный, потому что все мы работаем на своих работах, хотим быть максимально крутыми разработчиками и автоматизаторами, сделать фреймворк по нашему вкусу. Но, как правило, нам этого не дают злобные заказчики или таймфреймы, а вот в опенсорсе есть возможность делать все по вашим вкусам и попробовать себя в разных ролях.
Как поддержать опенсорс?
Лайки или деньги
Самый простой способ. Чтобы поддержать лайками, достаточно зайти на страничку любого опенсорс-проекта.
Любой проект с кнопкой Sponsor можно поддержать деньгами. Посмотрите, кто эти люди, чем занимаются, зачем им нужны деньги. Есть разные варианты:
- заплатить самому;
- уговорить свою компанию;
- подписаться на платный саппорт.
Не знаю, как вы, а я встречал много проектов, которые мы все используем, и вдруг они умерли, потому что их больше никто не поддерживает. Таким образом их можно спасти.
Ответы на вопросы
Помочь можно не только деньгами или кодом. Все обычно думают, что нужно коммитить, уметь программировать. Так вот, мейнтейнерам нужен не только код и даже не столько он. Вы можете попробовать отвечать на вопросы других людей в форумах, в чатиках, на StackOverflow и еще на куче подобных сайтов. Это уже большая помощь.
Когда я запустил Selenide, то первые два года сам регистрировался во всех чатиках и отвечал на вопросы людей. Впервые я понял: «О, началось», когда увидел, что на вопрос чувака о Selenide ответил другой чувак. И теперь на некоторые вопросы я не успеваю ответить, потому что прилетает ответ от другого. Для меня это огромная польза.
Артём: Это снимает с разработчика очень много нагрузки, потому что коммьюнити большое и ты физически не сможешь ответить на все вопросы. Без коммьюнити невозможно что-то нормально развернуть.
Пост в блоге
Андрей: Это может показаться мелочью: зачем писать пост, если о Selenide и так много написано?
Во-первых, можно написать о том, как используется Selenide в специфической ситуации со специфичным фреймворком, с которым я, скорее всего, никогда это не пробовал делать. И у меня, например, последнее время часто случается так, что в крупной компании, которая сама Selenide не использует, находится чувак, который где-то увидел Selenide и говорит: «А давай я напишу в нашем корпоративном блоге про Selenide». Пишет пост в корпоративном блоге, всем он нравится, и они начинают использовать Selenide.
Выступление на митапе
Вы можете рассказать на митапе или конференции про Selenide или про любой другой любимый фреймворк. Это и для вас полезно: выступление на митапе очень круто прокачивает ваши скиллы. Маленький лайфхак: если вы обратитесь к мейнтейнерам фреймворка, скорее всего, они вам помогут и пост подредактировать, и посоветуют, как сделать выступление интереснее.
Помощь с кодом
Пойдем ближе к коду: можно оценить feature request. У меня, например, для Selenide поступает много feature requests. Я зачастую даже не умею оценить идею. Огромную ценность для меня представляют комментарии типа: «Ой, не надо этого делать, такое уже есть».
Также вы можете повторить issue, который сложно повторяется. Еще вы можете проревьюить pull request или дополнить документацию.
И, наконец, самое сложное, чего все больше всего боятся, — это запилить багфикс или фичу. Но это далеко не единственное, что вы можете сделать для опенсорс-проектов.
Примеры
Сейчас посмотрим, как все эти пункты выглядят на практике.
Как заценить feature request?
- Идите в свой любимый проект на GitHub, откройте папку issues: там есть не только баги, но и вопросы, пожелания и pull requests.
- Ищите, где нет ясности.
Проекты бывают разные, в некоторых мейнтейнеры заботятся о других людях, в некоторых — не очень. Мы пытаемся заботиться, навешивать какие-то ярлыки, чтобы как-то дать сигнал другим людям, что это: фича или баг, понимаем ли мы ее сами, нужна ли тут их помощь или нет.
Метки четко вам могут показать, что это фича. Брейнсторм намекает, что тут нужно пораскинуть мозгами и понять, надо это или нет. И ваше мнение здесь может быть полезно, поэтому вы можете зайти, почитать, проанализировать, может, даже поэкспериментировать самому и написать комментарий.
Пример плохого комментария, где никто не поймет, почему идея дурацкая и кто ты вообще такой:
Вот пример хорошего комментария:
Дайте как можно больше контекста: у нас тоже есть такая проблема, мы научились обходить ее вот так, но этот способ ненадежный. Если бы это было в Selenide, то было бы круто. Мы сразу вникаем в контекст и понимаем, нужна фича или нет.
Мой любимый комментарий обычно выглядит так:
Это мой любимый комментарий, потому что этот issue можно сразу закрывать и ничего не делать.
Вы можете повторить issue. Очень часто бывает так, что в опенсорс-проекте висит куча каких-то багов, которые сложно или невозможно повторить. И мейнтейнеры рады бы их исправить, но не знают, как.
Вот пример из известного опенсорс HtmlUnit:
У HtmlUnit долго висел такой баг, но никто не знал, как его повторить, и иногда люди писали, что у них такая же проблема. И у меня однажды случилось так, что когда я гонял тесты Selenide, то случайно нащупал, как она у меня стабильно повторяется. Я смог написать такой вариант Selenide-тестов, где этот баг повторялся довольно стабильно. Я сделал отдельную ветку, в ней сделал этот вариант с повторением и заслал чувакам. И буквально через день чувак написал ответ:
Этой историей я хотел подчеркнуть еще раз, что очень часто помощь может быть не в исправлении бага, а в его повторении.
Артём: Я занимаюсь разработкой большого количества инструментов, и зачастую для меня исправление проблемы стоит одну единицу времени, а ее воспроизведение стоит 7 единиц. Между нашим кодом и пользователем Allure находится много слоев, и мне приходится тратить время на воспроизведение проблемы.
Например, мне пишет человек, что у него не работает интеграция с Jira. Я поднимаю стенд прямо в облаке и говорю: «Вот рабочий пример». А у него все равно не работает. Поэтому если бы мне прислали вот такой пример, я был бы счастлив. Это действительно хороший способ помочь авторам опенсорс-фреймворков.
Андрей: Вы можете проревьюить pull request. Зайдем в Files changed. Здесь вы можете создать свой code review на эти изменения. Написать, что именно плохо, чем плох стиль или посоветовать, как переименовать класс.
Зачастую одна из самых больших проблем для мейнтейнеров — это решить, как назвать класс или метод. Отличие разработки энтерпрайзов от опенсорсов в том, что в энтерпрайзе ты можешь сегодня назвать класс не самым удачным образом, а завтра переименовать — и ничего страшного. А в опенсорсе, как только ты его один раз назовешь, он уйдет в льды Арктики.
Нажимаем Review changes и оставляем какой-нибудь ревью.
Это плохой пример. Лучше конструктивно говорить, почему плохо, как лучше исправить. Но можно и так оставить.
Повышаем градус: попытаемся теперь понять, как можно это делать не только с помощью комментариев и обмена мнениями, а как залезть в код и поменять.
Как поменять код
Есть два способа: легкий и продвинутый.
Легкий способ хорош тем, что там не надо вообще уметь пользоваться гитом, что-то компилировать. Многие о нем не знают, но на самом деле, это крутейший способ.
Будучи совершенно посторонним человеком с GitHub-аккаунтом, вы можете нажать Edit. Вам выдается предупреждение.
Исправляем, например, грамматические ошибки. Можно написать дополнительные комментарии о том, что ты сделал: fix typos. Обычно typos знакомо всем мейнтейнерам. Это кодовое слово, с которым, скорее всего, вас быстро смёрджат, потому что это очень простое изменение.
Все эти вещи подходят по умолчанию, GitHub за вас их заполняет правильно.
Далее мы выбираем Bug-fix, потому что это не новая фича и не breaking change. Больше ничего особенно и не надо.
И нажимаем волшебную кнопку Create pull request. Находясь в этом pull request, на всякий случай можем проверить, что все изменения есть, все строчки изменены. Еще важно проверять, что билд зеленый, потом еще вернуться и посмотреть, смёрджил он его или нет.
Отслеживать статус — очень важный пункт, потому что я очень часто вижу, что в Selenide люди оставляют какой-то issue и уходят. А я, допустим, захожу, пишу свой комментарий или дополнительный вопрос, а они не отвечают.
Еще один лайфхак: если у вас есть проект, за которым вы хотите следить, знать о новых фичах и мёрджах, можно нажать на любом проекте кнопку Watch. Это позволяет получать уведомления о важных событиях.
Это пример, где в результате pull request полетел еще автоматический билд. Здесь можно отслеживать, какой у вас статус. Вы могли сломать какие-то тесты своим изменением. И самое важное: не бросайте! Вернитесь потом и посмотрите, что ваши изменения смёрджили или задали дополнительный вопрос.
Лёгкий способ хорош для:
- документации;
- сайта;
- форматирования;
- Javadoc;
- исправления опечаток;
- обновления зависимостей.
Артём: GitHub скоро выкатывает IDE, которая будет прямо в GitHub. И все эти штуки на GitHub будет легче делать. Сейчас у них уже выкатилась подсветка, когда ты можешь кликнуть переменную и посмотреть, где она используется. Естественно, большой рефакторинг так не сделать, но для небольшого pull request достаточно будет IDE, встроенной в GitHub.
Андрей: Продвинутый способ — это когда вам нужно уже зачекаутить проект и менять его на своем компе: компилировать, запускать тесты.
Сначала вы должны сделать fork (клон) проекта в вашем GitHub-аккаунте, зачекаутить его на свою машину и реально поменять код, тест и все, что требует изменений.
Потом запустить локально какой-то минимальный набор тестов, проверить, что там ничего не сломано. И тогда уже коммитить и пушить. Когда вы запушите его, в GitHub появится pull request, и вам остается только следить за его статусом: что его наконец-то уже смёрджили или попросили что-то исправить. Здесь важно не просто его оставить, а довести дело до конца. Иногда приходится заходить и напоминать.
Практическая часть
Пример 1: Андрей → Allure
Открываем проект Allure и находим issue, который можно исправить. Нашел три штуки, которые как-то связаны с Selenide. Похоже на то, что это не баги.
Этот пример связан не с Selenide, но это баг, который не похож на баг. Или, по крайней мере, баг не в Allure. Я залез в код Allure, проверил стектрейсы и пришел к выводу, что в Allure исправлять нечего.
Похоже, это баг не в Allure, а где-то в другом месте. И он повторяется в какой-то старой версии Java, на новой версии он никак не повторился. Поэтому я ему написал: «Чувак, ты точно уверен? Ты пробовал повторить на более новой версии? Возможно, там уже это исправлено».
Обычно я вешаю лейбл на issue, где автор не отвечает, чтобы потом можно было понять, что тут мы ждем ответ. Если он долго не отвечает, мы просто закрываем issue. На самом деле закрыть issue не страшно, потому что когда он очнется, то оставить комментарий можно даже в закрытом issue, и мы сможем потом снова его открыть.
Видите, мне уже удалось помочь проекту Allure, даже не поменяв ни строчки кода.
Пример 2: Андрей → Allure
Здесь чувак жалуется, что у него при запуске Allure сыпется такой-то exception, а если взять предыдущую версию Allure 2.13.5, то exception не сыпется. То есть что-то поменялось между двумя этими версиями. Это пример хорошего описания issue, потому что понятно, где искать. Я зачекаутил обе версии, сделал diff, увидел, что изменилось и понял, в чем проблема. И в итоге я ему ответил, что в Allure багов нет — баги в его демопроекте. Он Allure обновил, а версию JUnit не обновил, и они друг с другом не работают. Я даже ему заслал pull request, написал, что его проблему исправит обновление JUnit в его проекте. Помог и Allure, и проекту.
Пример 3: Андрей → Allure
А вот эта issue связана с Selenide. Также хороший баг-репорт, потому что он четко описывает, что делать, есть код для повторения.
Он говорит, что объявил PageObject, в нем объявил несколько неиспользуемых полей, а они зачем-то отображаются в отчете Allure.
Видно, что на них потрачено ноль секунд, то есть их не использовали, но в отчете эти строчки есть.
Я сначала ломанулся исправлять этот баг, но потом понял, что баг не в Allure, а в Selenide. Selenide присылает Allure такие лишние ивенты. И я ему написал, что баг в Selenide, так что заведи там баг-репорт, там будем исправлять, а в Allure можно закрывать issue.
Для мейнтейнера это большая помощь. Человеческий мозг не может удерживать в памяти сразу много вещей. Если он сегодня исправил одну-две issue или даже не исправил, а просто прошелся, посмотрел, проанализировал — все, мозг отключается. Чем меньше таких отвлечений, тем лучше.
Пример 4: Андрей → Allure
Поскольку я не нашел issue, который я мог бы полноценно исправить, я решил сделать простое исправление в Allure.
Для этого захожу в Allure, нажимаю Fork. Теперь нужно сделать git clone. Ваш URL-репозиторий есть под кнопкой Code:
Теперь идем в командную строку, вызываем git clone. Если проект не очень большой, это должно пройти довольно быстро. Заходим в папку проекта.
Советую первым делом всегда попробовать его скомпилировать. Иногда даже это не компилируется. Вы еще ничего не поменяли, а он уже не компилируется.
Лайфхак: если вы хотите попробовать сделать куда-то pull request, обновите Gradle или версию зависимости. Allure использует Gradle 6.6.1, а уже есть версия 6.7. На сайте Gradle можно подсмотреть команду, как обновить версию.
Проверяем и видим, что теперь в проекте используется Gradle 6.7. Нам нужно снова запустить тесты, чтобы убедиться, что ничего не сломалось.
Тесты запустятся, и можно сразу закоммитить. Или можно открыть этот проект в IDEA и закоммитить оттуда. Это проще и нагляднее.
Мы видим, что поменялось четыре файла, мы их закоммитим. Самый важный файл — это версия Gradle.
И важный момент — мы находимся в мастер-ветке. Это плохая идея — коммитить в мастер-ветку. Поэтому лучше создать новую ветку с говорящим названием: upgrade-gradle-6.7. И делаем Commit and Push.
Теперь возвращаемся в репозиторий и смотрим, что случилось.
Вот важный момент — это fork Allure, и находясь в нем, мне GitHub подсказывает, что появилась новая ветка и она хорошая. Он предлагает сделать из нее pull request.
GitHub сразу подсказывает с какого репозитория, с какого основного бранча ты это сделал. Здесь самая важная работа — правильно написать, что вообще ты тут сделал, есть ли issue, который это описывает.
И здесь начинают прыгать статусы.
У Артёма настроены какие-то правила, которые не позволяют сразу смёрджить.
Артём: Во многих репозиториях настроены правила автоматизации. В Allure сейчас ивент перешел в Jenkins. И Jenkins поднимает Agent в Digital Ocean и запускает тестирование там. Мы потихонечку мигрируем на GitHub Actions. В GitHub Actions ты бы сразу увидел, что у тебя GitHub Action стартанул. Ну и нужен хотя бы один ревьювер, чтобы это можно было смёрджить.
Чтобы заревьюить, я захожу на свою страницу. У меня пошли проверки и мне надо дождаться CI, пока он поднимется и так далее.
Здесь провайдится jenkins-digitalocean. Сейчас Jenkins отпишется сюда о том, что билд пошел.
Заметим, что license/cla уже подписан.
Пример 5: Артём → Selenide
Я нашел вот такой issue: не отображается URL в сообщении об ошибке. Я согласен с автором, тут есть и за, и против. «Против» заключается в том, что сейчас у нас все приложения одностраничные, и URL будет не настолько показательным.
Я с этим не согласен. Мне кажется, что это прекрасная идея, потому что я вижу, что здесь есть некоторый ожидаемый результат и скриншот, но не хватает информации, где я нахожусь.
Соответственно, я делаю fork. У меня два remote, обычно делаю так, что у меня есть origin remote:
То есть у меня есть ссылка на этот репозиторий, я ее всегда оставляю как origin. С большой вероятностью, если я буду долгое время контрибьютить в какой-то инструмент, например в Selenide, то мне потом дадут права, и я смогу сам создавать бранчи.
Здесь у меня origin называется eroshenkoam, и когда я буду делать бранч, я буду делать его там.
После этого я открываю новый проект из IDE. Я могу заметить от себя, что очень круто сформулирована ошибка. Я, например, решил поправить ошибку, и мне надо понять, что искать. Раз эта штука печатается, то по ней можно искать.
Я сразу же нашел места, где это используется.
Дальше смотрю, что у нас провайдится screenshotPath. Соответственно, я делаю следующее:
А теперь мне надо обработать понятие, что такое URL == null, и я здесь ставлю условную логику.
Прикольно делать комментарии, где вы указываете issue. И дальше я делаю push в свой fork. Обычно я описываю так:
И провайжу еще Action list, который будет состоять из следующих задач: provide tests, refactor meta adding. Грубо говоря, я еще провайжу список того, как вижу решение этой задачи. First draft я уже закончил. И нажимаю Draft pull request.
Соответственно, я потом пишу:
Сначала я хочу проверить, правильно я думаю или нет. И после того, как мне ответят, я запровайжу информацию о тестах и refactor meta adding.
Андрей: На Selenide pull request появился, еще пришел имейл. На Travis CI автоматически запускается билд. Он не во всем удобен, зато любой посторонний может посмотреть статус билда, какие тесты пробежали, какие упали и почему.
Сложности
Иногда сложно найти проект с исходниками, чтобы его зафоркать. У многих проектов одинаковое имя, или проект может быть не на GitHub. Например, исходники Java долгое время лежали в каком-то старом месте, их только недавно перевели на GitHub.
Бывает много forks одного и того же проекта. Первоначальный мейнтейнер уже давно ушел, вместо него уже проект поддерживает другой, затем третий. В таких случаях иногда не разобраться, в каком репозитории в итоге нужно исправлять.
Когда ты меняешь код, надо разобраться в том, какая у него структура, какие папки, в какую ветку коммитить. Бывает не только ветка master, а также ветки develop и features. Надо понимать, какую команду надо запустить локально, чтобы проверить, что ты ничего не сломал. Она тоже бывает очень разная, с кучей параметров.
В идеале нужно искать в проекте файлик CONTRIBUTING — там всё это описано. К сожалению, такой файл есть не в каждом проекте. Кстати, это хорошая идея для первого pull request: если в проекте такого файла нет, создайте его сами.
И последний, самый большой вопрос, который наверняка есть у всех. Допустим, вы согласны, хотите и готовы попробовать.
Но что, если я стесняюсь? Мой код увидят, там будут косяки, я буду выглядеть глупо, меня засмеют.
Всем на самом деле все равно, плохо ли закоммитили или хорошо. Я, например, честно скажу, что в Selenide есть места, которые не идеальны, которые мне не нравятся. Даже то место, которое Артем поменял, на самом деле — неудачный код. Там видно, что в одном месте много if, много ответственностей, и он ломается, если там не html. Не самый удачный код, но меня же никто не атакует.
Поэтому коммить, словно никто не видит, и пушь, словно никто не слышит. И контрибьють, словно тебя никто никогда не обижал!
Это доклад с фестиваля TechTrain, рассчитанного на самых разных IT-специалистов. Но если он вас заинтересовал, то вас могут привлечь и наши профильные IT-конференции, где контент сосредоточен на определённой области. Пока в весеннем онлайн-сезоне 2021 анонсировали пять: JPoint (Java), Heisenbug (тестирование), HolyJS (JavaScript), DotNext (.NET), Mobius (мобильная разработка).