Привет. Меня зовут Роман Аймалетдинов, я разрабатываю под Android в inDriver. Сегодня я решил поделиться своим небольшим знанием о том, как выложить в open source свой проект. Приятного чтения!

Содержание

Подготовка проекта

Первое, что нужно сделать до того, как выкладывать что-либо в open source — убедиться, что проект не содержит коммерческой информации, на которую распространяется ваш NDA:

1. Поговорите с руководителем и получите устный аппрув.

2. Создайте приватный репозиторий. Причешем и сделаем публичным, когда все будет красиво и получены аппрувы.

Note: лучшим способом является копипаст интересующего куска проекта или модуля так, чтобы была затерта история Git. Согласитесь, будет не здорово, если любопытные энтузиасты по истории смогут вытянуть коммерческую информацию из вашего проекта.

3. Ответьте на следующие вопросы:

  • Код содержит чувствительные данные (пароли, токены)?

  • Затерта ли история Git?

  • Не нарушаете ли вы чужие авторские права?

  • Использует ли решение сторонние, платные библиотеки?

  • Есть ли в коде бизнес-логика вашего проекта?

  • Все ли файлы необходимы (возможно, что-то следовало добавить в gitignore)?

  • Есть ли в сетевом слое эндпоинты, обращения к бэкенду?

  • Покрыт ли код комментариями на английском?

4. Возможно, в вашем случае целесообразно сделать sample-проект, где будет использовано ваше решение.

Note: по моему личному мнению, sample должен быть действительно простым, без использования сторонних библиотек. Еще раз — он должен быть ОЧЕНЬ простым.

Если вы добавите View Binding и еще пару библиотек, к которым вы привыкли — вы усложните проект для понимания для людей, которые пишут по-другому. Должен быть акцент только на вашем решении.

Если вы хотите продемонстрировать разные сценарии использования вашей библиотеки, имеет смысл сделать несколько sample-проектов. Например, один максимально простой, а второй с накрученной логикой для тех, кто уже разобрался с основами.

5. Допустим, вы убедились, что все лишнее удалено, рабочих эндпоинтов вы не засветили, все красиво. Замечательно! Идем к безопасникам, получаем официальные аппрувы от них и от самого высокого руководителя, насколько этого требует ваша структура.

Лицензия

Следующим шагом идем к юристам и вместе с ними определяем, какая лицензия вам подходит.

  • Советую внимательно ознакомиться с лицензиями, так как некоторые не позволяют сменить тип лицензии в будущем, и вам может быть грустно.

  • Понять, хотите ли вы зарабатывать на этом решении в будущем.

Лицензии — тема отдельная, в рамках этой статьи я лишь хочу предупредить о важных, на мой взгляд, моментах. Но точно советую почитать перед публикацией, а не просто вставлять лицензию. И если вдруг проект взлетит, поменять. Мне понравилась эта статья, в особенности список ссылок, которые автор привел в конце.

Ответственность

Учтите, если бизнес доверился вашему решению, то он полагается на вас. Он будет использовать решение и ожидать, что вы периодически будете обновлять репозиторий. А еще он может зависеть от вашего репозитория.

Но, допустим, вы что-то придумали, но не уверены, что решение взлетит. Или что проект будет поддерживаться долго и ответственно. Вы хотите оградить себя от лишнего гнева разработчиков и прямых претензий компаний за то, что ваше решение делает что-то неочевидное и не соответствующее документации. И, как следствие, они теряют много денег из-за ошибок в вашем репозитории.

Чтобы минимизировать риски, я бы посоветовал написать дисклеймер в readme.md:

(En) 
All information and source code are provided AS-IS, without express 
or implied warranties. Use of the source code or parts of it is at
your sole discretion and risk. YOUR_COMPANY LLC takes reasonable measures
to ensure the relevance of the information posted in this repository,
but it does not assume responsibility for maintaining or updating
this repository or its parts outside the framework established by the 
company independently and without notifying third parties.

(Ru)
Вся информация и исходный код предоставляются в исходном виде, без
явно выраженных или подразумеваемых гарантий. Использование исходного
кода или его части осуществляются исключительно по вашему усмотрению
и на ваш риск. Компания ООО “YOUR_COMPANY” принимает разумные меры для
обеспечения актуальности информации, размещенной в данном репозитории,
но она не принимает на себя ответственности за поддержку или актуализацию
данного репозитория или его частей вне рамок, устанавливаемых компанией
самостоятельно и без уведомления третьих лиц.

Все зависит от вас, вашего проекта и степени вовлеченности в ваш open source. И такой дисклеймер важен не потому, что вы хотите снять с себя ответственность. А потому, что если вы не уверены, что будете ответственно поддерживать проект — дайте знать это сообществу! Пусть они будут готовы, и самостоятельно оценят риски использования вашего решения. Мы культурное сообщество, предупредить коллег — это правильно.

Документация

У вас уже наверняка создан файл readme.md. Я бы порекомендовал отразить следующие пункты в этом файле:

  • Название

  • Вступление (очень коротко, только суть)

  • Установка (тут же gradle version)

  • Зачем использовать (человеческим языком, почему эта библиотека существует)

  • Проблемы, которые решает ваша библиотека (пункты 1, 2, 3..)

  • Решение (как библиотека решила проблемы)

  • Пример

  • Как протестировать

  • Пример тестов

  • Лицензия

  • Дисклеймер

Получается, что ваша библиотека должна содержать много информации. Например, подробно опишите, как ее установить. Напишите это так, чтобы даже джун справился. Не надо оставлять пропусков, которые кажутся вам очевидными. Все мы имеем разный опыт и разные способности к усвоению новой информации. Помогите использовать ваше решение.

Возможно, информации будет очень много. Тогда вам придется сделать несколько .md-файлов, которые будут ссылаться друг на друга.

Публикация на JitPack

Для кого-то это может показаться самой вкусной частью статьи: как же сделать так, чтобы наш код подключался в .gradle одной строчкой? То есть вот так:

dependencies {
    implementation 'com.github.Evleaps:repository:$version'
}

Есть несколько вариантов, как сделать такое. Некогда был очень популярен jFrog. Еще можно использовать сервис Mymavenrepo, который предоставляет возможность загружать и подключать плагин. Есть и другие способы доставки нашего кода. Но я расскажу про jitpack.io.

Это очень простой способ. Уверен, что используя эту статью, процесс займет не более получаса (но это неточно).

Допустим, код уже подготовили, документацию написали, на GitHub выложили, аппрувы от руководства получили. Теперь выполним несколько действий:

1. Делаем GitHub-репозиторий публичным (видимым всем).

2. Регистрируемся на jitpack.io через GitHub-аккаунт.

3. Теперь нужно подготовить код и сконфигурировать build.gradle, чтобы JitPack смог собрать артефакт. Сервис любезно подготовил sample-проект, по которому можно разобраться в том, что нужно добавить в проект. Но на это я обращу внимание дополнительно.

Итак, сначала нужно в добавить в build.gradle:

apply plugin: 'java'
apply plugin: 'maven-publish'

Убедитесь, что у вас есть:

repositories {
    mavenCentral()
}

И конфигурируем:

java {
	  withSourcesJar()
	  withJavadocJar()
}

Последнее, что нужно добавить:

publishing {
    publications {
        maven(MavenPublication) {
		        from components.java
        }
    }
}

wrapper {
    gradleVersion = "7.3.3"
    distributionType = Wrapper.DistributionType.ALL
}

Весь код выше был взят из примера, предоставленным сервисом. Однако, дополнительно покажу вам build.gradle моего проекта, чтобы вы увидели, как это может выглядеть еще:

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.6.0'
    id 'java'
    id 'maven-publish'
}

apply from: "$rootDir/dependencies.gradle"
apply plugin: 'maven-publish'

group 'com.citymobil.safecoroutines'
version '1.0.3-RC'

repositories {
    mavenCentral()
}

java {
    withSourcesJar()
    withJavadocJar()
}

publishing {
    publications {
        maven(MavenPublication) {
            from components.java
        }
    }
}

wrapper {
    gradleVersion = "7.3.3"
    distributionType = Wrapper.DistributionType.ALL
}

dependencies {
    implementation deps.ktx.stdlib
    implementation deps.ktx.coroutines_core
    implementation deps.static_analysis.detekt_api

    testImplementation deps.test.junit
    testImplementation deps.test.jupiter
    testImplementation deps.test.coroutines
    testImplementation deps.test.mokito
}

test {
    useJUnitPlatform()
}

Ну и, собственно, мой личный проект, можете на него взглянуть и даже поставить звездочку. О нем я расскажу отдельно в будущем.

У меня JitPack завелся не сразу. Моей ошибкой оказалась отсутствие инструкции publishing и плагина maven-publish. В логах, которые предоставляет сервис, было написано, что не удалось собрать артефакт.

1. Обновляем версию в поле version и пушим. Но это не все. Чтобы триггернуть JitPack, необходимо пушнуть git tag. То есть выполняем в терминале несколько команд:

git tag v1.0.0-RC
git push origin --tags
git tag

Мы запушим наш первый релиз, JitPack триггернется и самостоятельно создаст артефакт сборки, а затем сгенерирует путь, по которому можно будет установить нашу библиотеку.

2. После регистрации, слева вы увидите список ваших открытых репозиториев. Выбираем интересующий:

Откроется страница с логами и сгенерированным путем зависимости. Если для вашего релиза не получится собрать артефакт, вы сможете скачать репорт и посмотреть, в чем проблема. Обратите внимание на sample-проект. Возможно, вы что-то пропустили. Если все хорошо, репорт будет выделен зеленым цветом.

3. Ну и последнее, что нужно сделать — вставить в свой readme.md инструкцию по установке вашего open source-проекта. Обратите внимание, что вы можете вставить ссылку на динамически обновляемую версию в ваш readme, и сообщество увидит красивую вьюшку с зеленой или красной заливкой, в зависимости от успешности создания артефакта.

На этом все. Осталось только протестировать, но, я надеюсь, вы и сами знаете, как это сделать лучше всего. Давайте подрезюмируем шаги краткими пунктами:

  • Делаем репозиторий публичным.

  • Регистрируемся на jitpack.io.

  • Конфигурируем build.gradle как в примерах.

  • Пушим изменения.

  • Пушим новый git tag.

  • На jitpack.io смотрим, собрался ли артефакт.

  • Тестируем :)

Ссылки