Розробка opensource - та приватність Composer-пакетів: як це робити і навіщо

У цій статті продемонструємо розробка PHP-пакету, розберемося, для чого це робити та як автоматизувати рутинні дії для його підтримки. Стаття буде цікава програмістам будь-якого рівня, які планують створити свій opensource-пакет, або тим, хто, розробляючи приватний пакет, хоче знайті шлях інкапсулювання складної логіки поза межами основного репозиторію.

Composer

Майже кожен PHP-розробник знає про Composer . Це менеджер пакетів, який революціонував PHP і давши дуже потужний поштовх для розвитку цієї мови.

Тепер для того, щоб використати у своєму проєкті напрацювання інших девів, розробникам не треба завантажувати PHP-файли, копіювати код і робити інші, дивні для сучасної розробки, налаштування. Достатня просто знайте потрібний пакет на packagist.org і виконати команду composer require author/package-name або composer install, якщо потрібно встановити пакети з попередньо сконфігурованого файлу composer.json.

Самі пакети створила велика спільнота розробників, кожен з яких робить свій внесок у opensource-спільноту і розвиток мови.

Для чого розробляти пакети

Давайте розберемося, для чого розробникі створюють composer-пакети — яка у них мотивація?

Вісь декілька головних чинників для opensource-пакетів:

Пакети можуть бути розроблені тільки для внутрішнього використання. Таким чином розробникі відмежовують логіку в пакеті від логіки основного проєкту.

Кожен пакет починається з composer init. Щоб створити пакет, потрібно виконати команду composer init у директорії пакету.

Composer запропонує вам декілька стандартних запитань. Поки що можемо просто пропустити їх.

Composer також запропонує вам інтерактивно зверни залежності — вибираємо no, бо пакет, який створюємо, не матиме залежностей на цьому етапі.

У результаті, створиться файл composer.json — файл з конфігурацією.

composer.json
{
 "name": "igorrebega/uawords",
 "authors": [
{
 "name": "Igor Rebega",
 "email": "[email protected]"
}
],
 "require": {}
}

Autoloading

Щоб Composer міг працювати з namespace й правильно підключати файли, нам потрібне автозавантаження за форматом PSR-4. Будемо складати наш код у папку /src.

Відредагуємо composer.json таким чином, додавши секцію autoload:

{
 "name": "igorrebega/uawords",
 "authors": [
{
 "name": "Igor Rebega",
 "email": "[email protected]"
}
],
 "require": {},
 "autoload": {
 "psr-4": {
 "IRebega\\UaWords\\": "src/"
}
}
}

Виконаємо команду composer dump, яка створить файл для автозавантаження.

На цьому етапі ми готові робити наш перший клас:

src/WordFactory.php

<?php

namespace IRebega\UaWords;

class WordFactory
{
 public function hello()
{
 return 'Привіт!';
}
}

Для тестування створимо файл index.php:

index.php

<?php

include 'vendor/autoload.php';

echo (new \IRebega\UaWords\WordFactory())->hello() . PHP_EOL;

І запустимо скрипт за допомогою команди php index.php.

Як бачите, автозавантаження працює.

Тестування

Якщо ви хочете, щоб вашим пакетом користувалися інші розробникі, вам потрібні тести.

Для цього використаємо фреймворк PHPUnit. З урахуванням того, що він нам потрібен тільки для розробки, додамо його як dev-залежність, виконавши команду composer require --dev phpunit/phpunit (це змінить composer.json-файл).

Тепер давайте створимо папку для тестів і назвемо її tests. Також додамо автозавантаження для неї (секція autoload-dev):

composer.json

Перший тест

Код тесту:

tests/WordFactoryTest.php

<?php

namespace IRebega\UaWords\Tests;

use IRebega\UaWords\WordFactory;
use PHPUnit\Framework\TestCase;

class WordFactoryTest extends TestCase
{
 public function test_it_is_not_null()
{
 $this->assertNotNull((new WordFactory())->hello());
}
}

Щоб його запустити, нам потрібен файл з налаштуваннями phpunit — phpunit.xml:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
 <testsuite name="bvblogic test suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
 <directory suffix=".php">src/</directory>
</whitelist>
</filter>
</phpunit>

Можете використовувати цей код як шаблон своїх пакетів. У більшості випадків вам потрібно буде змінити тільки testsuite name параметр.

Детальніше можна прочитати тут .

Тепер давайте запустимо наш тест командою ./vendor/bin/phpunit:

Вітаю! Наш перший тест пройшов успішно.

Використовуємо пакет локально

Тепер давайте навчимося використовувати наш пакет локально, щоб мати змогу тестувати його в реальних проєктах.

Для демонстрації створюємо новий проєкт й ініціалізуємо його за допомогою composer init.

Далі спробуємо виконати команду composer require igorrebega/uawords.

Пакет не буде знайдено, тому що composer за замовчуванням використовує сервіс Packagist для пошуку пакетів.

Альо ми можемо вказати йому свій локальний репозиторій. Для цього додаємо в composer.json тестового проєкту такий код:

"minimum-stability": "dev",
"repositories": [
{
 "type": "path",
 "url": "../uawords"
}
]

Де url — це відносний або абсолютний шлях до папки з пакетом. А minimum-stability вказаний для того, щоб мати змогу використовувати dev-версії пакетів.

Знову виконаємо composer require igorrebega/uawords:

Далі створимо файл index.php:

index.php 

<?php

require 'vendor/autoload.php';

echo (new \IRebega\UaWords\WordFactory)->hello() . PHP_EOL;

Запустимо його командою php index.php і отримаємо «Привіт!» у консолі.

Додаємо пакет у Git

Виконуємо команду git init. Додаємо файл .gitignore з таким вмістом:

.gitignore

vendor
composer.lock

Додаємо всі інші файли в Git і пушимо на GitHub.

Додаємо пакет у Packagist

Переходимо за цією адресою , реєструємося і вказуємо посилання на GitHub. Далі підтверджуємо створення пакету.

Як ви тепер можете бачіті, у нас тільки одна версія — dev-master. Тобто все, що ви пушите у гілку master, автоматично позначається як найновіша версія.

Додаємо версії

Для версій ми будемо використовувати Semantic Versioning. Докладніше можна прочитати тут semver.org .

Найголовніше, розуміти те, що версія складатиметься з трьох чисел, розділених крапкою.

  1. MAJOR — ті зміни, які можуть зламати код користувача, якщо він використає вищу версію пакету, ніж у нього був.
  2. MINOR — удосконалення, які додають функціонал, альо не ламають код, який використовує старий функціонал.
  3. PATCH — зазвичай для багфіксів.

Отже, заходимо в GitHub, потім releases:

Натискаємо create a new release, вводимо інформацію про реліз і тиснемо Publish release.

Тепер переходимо на сторінку свого пакету в Packagist, тиснемо оновити і маємо побачити, що версія змінилася на 1.0.0. Саме вона буде використана за замовчуванням:

Рекомендуємо декілька змін заливати в одну версію, щоб ваш пакет був стабільний і ві малі досить годині протестувати новий код.

Travis CI

Тепер зробімо так, щоб тести запускалися автоматично. Для цього використаємо сервіс Travis CI .

Реєструємося, синхронізуємося з GitHub і вибираємо наш репозиторій:

Додаємо до проєкту файл з налаштуваннями travis:

.travis.yml

language: php

php:
 - 7.2
 - 7.3
 - 7.4

env:
matrix:
 - COMPOSER_FLAGS="--prefer-lowest"

before_script:
 - travis_retry composer update ${COMPOSER_FLAGS}

script:
 - vendor/bin/phpunit

Таким чином ми вказуємо сервісу, що потрібно запускати програму на декількох версіях PHP і використовувати найнижчі версії розширень. У такий спосіб ми можемо впевнитися, що тести працюють навіть зі старими версіями залежностей.

Після того як ви запушите, Travis автоматично виконає тести й сповістить вас про результат.

StyleCI

Тепер давайте подбаємо про єдиний формат написання коду. У цьому нам допоможе сервіс StyleCI .

Після реєстрації переходьте на сторінку Repos і включіть StyleCI для свого репозиторію.

Також пропонуємо перейти до Repositories setting та зверни бажаний рівень автоматизації. Для орепѕоигсе-проєктів часто підходить Automatically send and merge fix pull requests:

Він буде автоматично надсилати і мержити пул реквести із змінами code style.

Тепер нам потрібно додати файл конфігурації в проєкт:

.styleci.yml

preset: laravel

Таким чином ми будемо використовувати code style фреймворку Laravel. Після пушу ви маєте побачити, як StyleCi автоматично пофіксить усі проблеми з code style.

Ліцензія

Якщо ви не вкажете ліцензію для вашого проєкту, то легально не дозволяєте нікому його використовувати. Більшість проєктів для opensource мають MIT-ліцензію, яка дозволяє використовувати пакет у будь-яких цілях, але знімає з автора юридичну відповідальність за його роботу.

Тут можна прочитати більше про MIT і скопіювати текст ліцензії.

Пропонуємо так і зробити, створивши файл LICENCE.md , змінивши [year] [fullname] секції та вставивши текст ліцензії туди.

Далі ви маєте побачити на GitHub іконку MIT-ліцензії:

Readme

Якщо ви хочете, щоб про ваш пакет дізналися більше, вам обов'язково треба створити readme-файл.

Пропонуємо скористатися сервісом Makereadme .

Далі додаємо завантажений файл README.md до репозиторію.

Додаткові ресурси

Як бачите, процес створення пакету справді займає чимало часу. Щоб вирішити цю проблему, було створен багато сервісів, які можуть згенерувати вам порожній проєкт, який ви потім можете використовувати. Наприклад, Laravel Package Boilerplate .

Приватні пакети

Нещодавно Packagist запустивши комерційну версію, яка дозволяє створювати приватні пакети — Packagist .

Тому, якщо ваш проєкт не opensource, і ви не маєте змоги створити публічний пакет для нього, цей сервіс може стати вам у пригоді.

Ми в команді часто користуємося приватними пакетами. Наприклад, коли необхідно розробити АПІ-інтеграцію зі специфічним ресурсом, то простіше код інтеграції винести в окремий пакет і просто підключати тієї пакет до нашого основного репозиторію.

Наступні кроки

Сподіваюся, ця стаття надала вам потрібні для створення пакетів інструменти. А якщо треба додаткові приклади, то рекомендуємо вам переглянути найпопулярніші PHP-пакети на GitHub.

Опубліковано: 13/02/20 @ 11:00
Розділ Різне

Рекомендуємо:

Як подружити розробника і менеджера
Маніпулюємо користувачами: інстинкти
Набір на 5 потік мого курсу SEO Шаолінь
$2000 за рекомендацію та робота в оточенні друзів. Як працюють реферальні програми в ІТ
C++ дайджест #24: Code cleanup, VR, з чого почати вивчення С++ та створюємо валентинку