От новичка до контрибьютора: ваш первый PR в Kotlin проект

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему стоит начать контрибьютить в Kotlin-проекты прямо сейчас?

Вы пишете на Kotlin уже несколько месяцев. Знаете про корутины, разобрались с extension-функциями и даже используете sealed-классы. Но чувствуете, что стоите на месте? Знакомо. Open source — это не про "бесплатный труд". Это про ускорение вашего роста в 10 раз. Когда вы контрибьютите в реальные проекты, вы:

  • Получаете code review от разработчиков уровня JetBrains и Google;
  • Учитесь читать и понимать чужой код (а это 80% рабочего времени сеньора);
  • Пополняете портфолио реальными кейсами, а не учебными тасками;
  • Заводите полезные связи в комьюнити.

В этой статье я покажу, как сделать первый шаг. Без страха, без сложных теорий — только практика. Мы разберем, где искать задачи, как написать первый осмысленный PR и не облажаться.

С чего начать: выбираем проект под свой уровень

Главная ошибка новичков — пытаться сразу контрибьютить в Kotlin Compiler или Ktor. Стоп. Это путь к выгоранию. Вам нужны проекты, где:

  • Есть метка good first issue или help wanted;
  • Поддерживается актуальная версия Kotlin (1.9+);
  • Есть понятный CONTRIBUTING.md;
  • Комьюнити отвечает на вопросы в течение 1-3 дней.

Топ-5 проектов для старта в Kotlin open source

Вот проверенные репозитории, куда я рекомендую заглянуть:

  • detekt — статический анализатор кода. Много задач по документации и простым правилам;
  • Kotlinx.serialization — библиотека от JetBrains. Есть good first issue для новичков;
  • Ktor — фреймворк для серверов и клиентов. Там часто нужна помощь с документацией и тестами;
  • Exposed — ORM для Kotlin. Идеально, если вы работали с базами данных;
  • Anko — хотя проект заморожен, но там ещё много открытых issue по документации.

Важно: не надо хвататься за всё сразу. Выберите один проект, который вам реально интересен. Если вы любите писать тесты — идите в Ktor. Если вам нравится делать код чище — detekt ваш вариант.

Как найти свою первую задачу: разбираем GitHub Issues

Допустим, вы выбрали проект. Заходите в раздел Issues. Ваша цель — найти задачу, которая:

  • Помечена good first issue или beginner friendly;
  • Не закреплена за другим разработчиком (нет assignee);
  • Активна (последний комментарий не старше 2 недель).

Пример из жизни. Я зашел в репозиторий detekt и нашел issue: "Add documentation for new rule: MagicNumber". Задача: написать документацию на русском или английском для нового правила. Это идеальный первый PR — не требует глубоких знаний кода, но вы уже вносите реальную пользу.

Форкаем, клонируем, настраиваем окружение

Когда задача выбрана, действуем по схеме:

  1. Форкаем репозиторий (кнопка Fork в правом верхнем углу);
  2. Клонируем форк локально: git clone git@github.com:YOUR_USERNAME/detekt.git;
  3. Добавляем upstream: git remote add upstream https://github.com/detekt/detekt.git;
  4. Создаем ветку: git checkout -b docs/add-magic-number-rule.

Название ветки должно быть осмысленным. Используйте префиксы: docs/ для документации, fix/ для багфиксов, feat/ для новых фич.

Пишем код: реальный пример на Kotlin

Допустим, мы нашли баг в библиотеке Kotlinx.serialization. В issue написано: "Serializer for LocalDate throws exception when year is negative". Давайте разберем, как это можно пофиксить.

Сначала находим проблемный код:

// Исходный код с багом
internal object LocalDateSerializer : KSerializer<LocalDate> {
    override fun deserialize(decoder: Decoder): LocalDate {
        val value = decoder.decodeString()
        // Проблема: не обрабатывает отрицательные года
        return LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE)
    }
}

Мы видим, что LocalDate.parse() ожидает стандартный ISO формат, но если год отрицательный (например, "-2023-05-10"), парсер может упасть. Исправляем:

// Исправленный код
internal object LocalDateSerializer : KSerializer<LocalDate> {
    override fun deserialize(decoder: Decoder): LocalDate {
        val value = decoder.decodeString()
        // Добавляем обработку отрицательных годов
        return try {
            LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE)
        } catch (e: DateTimeParseException) {
            // Пробуем альтернативный формат
            LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
        }
    }

    override fun serialize(encoder: Encoder, value: LocalDate) {
        encoder.encodeString(value.toString())
    }
}

Теперь пишем тест, чтобы доказать, что фича работает:

@Test
fun testNegativeYearSerialization() {
    val date = LocalDate.of(-2023, 5, 10)
    val json = Json.encodeToString(LocalDateSerializer, date)
    val deserialized = Json.decodeFromString(LocalDateSerializer, json)
    
    assertEquals(date, deserialized)
}

Запускаем тесты локально: ./gradlew test. Если всё зелёное — можно коммитить и пушить.

Коммитим и создаём Pull Request

Правила хорошего тона в open source:

  • Один коммит — одно изменение. Не надо мешать фикс бага и рефакторинг в одном коммите;
  • Сообщение коммита пишем по шаблону: fix: handle negative year in LocalDate serializer (#1234);
  • В описании PR обязательно ссылаемся на issue: Closes #1234.

Пример хорошего описания PR:

## Description
This PR fixes serialization of LocalDate with negative years.

## Changes
- Added fallback DateTimeFormatter for negative years
- Added unit test for negative year serialization

Closes #1234

После создания PR не сидите сложа руки. Можете написать в комментарий: "Hi, I'm new to open source. Could someone review my PR when you have time?". Это покажет вашу мотивацию и ускорит ревью.

Что делать

Блоги

Рекомендаций по книгам