При разработке перл-модулей приходится делать много работы, которая практически не связана с задачами и кодом модуля — начиная от создания десятка типовых файлов/каталогов и заканчивая выполнением десятка одинаковых операций необходимых для выпуска новой версии.
Помимо того, что это скучно, лениво, и часто приводит к ошибкам (из-за необходимости обновлять мета-информацию — вроде номера версии — в нескольких файлах или нечаянного пропуска части команд при релизе) всё дополнительно осложняется перловским TIMTOWTDI — существует несколько разных систем сборки, у всех есть свои достоинства и недостатки (но нет простой таблички с их перечислением), и ни одна из них не является рекомендуемой ни официально ни сообществом.
Кроме того, многие из нас пишут на перле очень много лет, и последний раз читали perlnewmod когда изучали перл. В результате, когда создаются новые модули это нередко делается в стиле 15-ти летней давности, причём система сборки выбирается практически случайным образом — либо древний, но знакомый и точно умеющий что угодно EUMM, либо одна из других (не потому, что нужна именно она, а просто в надежде что она окажется проще и удобнее EUMM, не создав при этом новых проблем… которые она всё-таки со временем создаёт).
Далее кратко описаны имеющиеся на начало 2015 года средства, которые могут облегчить процесс разработки перл-модулей, сделать ваши модули более современными, и упростить другим разработчикам доработку ваших модулей. Я постарался перечислить их основные плюсы и минусы, но т.к. сам пользовался не всеми то буду дополнять/исправлять этот список в соответствии с вашими комментариями.
- Задачи
- $VERSION
- Скелет модуля / Boilerplate
- Сборка / Build
- Управление зависимостями / Dependencies
- Управление версиями / VCS
- Непрерывная интеграция / CI
- Выпуск / Release
- Поддержка / Support
- Авторинг / Authoring
- Резюме
- Разные полезности для авторов модулей
Задачи
Итак, давайте составим список задач, которые обычно входят в процесс авторинга Perl модулей.
Задачи при создании нового модуля:
- задать имя/email автора
- определить лицензию
- выбрать систему сборки
- выбрать дополнительные особенности:
- поддержка XS
- базовый набор тестов (проверка документации, правописания, качества кода, зависимостей, файлов системы сборки, etc.)
- автоматическая генерация README из документации модуля
- использование VCS
- интеграция с GitHub, Travis CI
- создать скелет модуля — каталог с кучкой файлов необходимых для его разработки и релиза:
- скелет самого модуля и документации
- базовый набор тестов
- Changes
- README
- LICENSE
- файлы системы сборки
- список зависимостей (иногда входит в файлы системы сборки)
- при использовании VCS: репозиторий и его настройки
Задачи при релизе новой версии:
- обновить список зависимостей
- собрать модуль
- запустить тесты
- выбрать новый номер версии и изменить её в нескольких файлах (в некоторых файлах — в нескольких местах)
- описать изменения в Changes
- добавить в Changes текущую дату и версию релиза
- обновить README
- при использовании VCS:
- commit изменений версии, Changes, и всех остальных изменённых файлов
- добавить tag для новой версии
- при использовании центрального репо (GitHub) — отправить в него изменения
- создать архив с модулем
- залить его на CPAN
В идеале, все решения необходимые при создании нового модуля (кроме необходимости в XS) нужно принять один раз, и в дальнейшем создавать новые модули одной командой. А при релизе, в идеале, одна команда должна выполнить все шаги кроме выбора нового номера версии и описания изменений в Changes.
$VERSION
In a perfect world, I would never blog about version numbers in Perl.
«Version numbers should be boring» — David Golden
Перед тем как перейти к сути вопроса, необходимо описать одну проблему: выбор формата для версии модуля. Хотя это и не связано напрямую с темой статьи, этот выбор необходимо делать в процессе авторинга, и он не так прост, как может показаться.
Есть очень много способов неправильно объявить версию своего модуля, поэтому я перечислю только правильные — их намного меньше.
Старая десятичная / Old-style decimal
Стабильные релизы (две/три цифры, кому как нравится):
our $VERSION = '0.08';
our $VERSION = '0.008';
package MyModule 0.08; # need perl-5.12
package MyModule 0.008; # need perl-5.12
Альфа-версии для тестирования CPAN Testers перед выпуском 0.09
/ 0.009
:
our $VERSION = '0.08_01';
our $VERSION = '0.008_001';
Либо, учитывая что альфа-версии пользователи всё-равно не увидят, вы можете использовать две независимые последовательности для стабильных и нестабильных релизов: пример.
Точечно-числовая / Dotted-decimal
Стабильные релизы (можно использовать 3 и более чисел в версии):
use version; our $VERSION = 'v0.8.0'; # need perl-5.8.1
our $VERSION = 'v0.8.0'; # need perl-5.10
package MyModule v0.8.0; # need perl-5.12
Альфа-версии для тестирования CPAN Testers перед выпуском v0.8.1
:
use version; our $VERSION = 'v0.8.0_1'; # need perl-5.8.1
our $VERSION = 'v0.8.0_1'; # need perl-5.10
Хотя "v0.8_1"
тоже можно использовать как альфа-версию между стабильными "v0.8.0"
и "v0.8.1"
но такая версия может быть только одна — если понадобится выпустить несколько альфа-версий то выпустить стабильную с номером "v0.8.1"
уже не получится.
Семантическая / Semantic
На данный момент нет возможности полностью соответствовать спецификации семантического версионирования - pre-release версии определённые как "1.2.3-alpha1"
применить к перл-модулям нельзя. Самым близким вариантом будет вышеописанная 3-х элементная точечно-числовая версия — вы можете следовать правилам определения следующей стабильной версии по спецификации, а вместо текстовых pre-release версий выпускать числовые альфа-версии.
TRIAL
Вы уже заметили, что альфа версии это, как говорят наши зарубежные коллеги, «боль в заднице». Фактически ведь речь идёт не о настоящих «альфа» — настоящие альфа, бета и прочие pre-release версии описаны в спецификации семантического версионирования и не поддерживаются перлом. Речь идёт о том, чтобы дать CPAN команду «не индексировать» данную версию. Таким образом мы смешиваем в одной переменной два типа данных (номер версии и флаг для CPAN), что является плохим стилем, уродливо выглядит, запутывает (что выбрать перед выпуском "v0.8.1"
— "v0.8_1"
или "v0.8.0_1"
?) и создаёт другие проблемы: альфа версии нельзя задать в package, в некоторых старых (до 5.8.1) версиях perl они работают не корректно.
Не так давно на CPAN добавили новый способ дать команду «не индексировать» данную версию — если в имени архива с модулем есть слово "TRIAL"
. Таким образом, вы можете больше не использовать «альфа» версии. Некоторые утилиты (Dist::Zilla, shipit, …) поддерживают параметр для добавления в имя архива с модулем "-TRIAL"
перед заливанием на CPAN. Учтите, что "v1.2.3-TRIAL"
(в отличие от "v1.2_3"
) это обычная версия "v1.2.3"
, так что следующая после неё должна быть "v1.2.4"
или "v1.2.4-TRIAL"
.
Скелет модуля / Boilerplate
Эти утилиты создают каталог с новым модулем, наполняя его базовым набором необходимых файлов по какому-то шаблону. Это самый старый, и, до сих пор, основной способ создать новый модуль. Проблема этого подхода в том, что значительную часть этих файлов мало просто однократно создать, их нужно постоянно обновлять при выпуске новых версий модуля. Поэтому многие постепенно начинают использовать вместо этих утилит более комплексные решения (обычно на базе Dist::Zilla).
h2xs, Module::Starter
Использование этих модулей описано в perlnewmod, но суть в том, что они очень устарели, практически не поддерживаются, слишком сложные и при этом недостаточно гибкие.
На CPAN можно найти ещё некоторое количество аналогичных модулей, но все, которые видел я, были заточены под потребности их авторов и не очень гибко настраивались — по сути, задача генерации каталога с новым модулем по шаблону настолько проста, что почти каждый пишет свой велосипед (мой — это скрипт на 20 строк в ~/bin/
, тоже абсолютно не настраиваемый).
Сборка / Build
С 95% модулей содержащих несколько pm-файлов, тесты и стандартно собирающийся небольшой кусок XS — справится любая система сборки.
Начиная с 5.10.1 появилась поддержка configure_requires — т.е. теперь можно в META.{json,yml}
указать какие модули должны быть установлены до запуска perl Makefile.PL
или perl Build.PL
. Иными словами теперь не важно, установлен ли у пользователя, например, Module::Build::Tiny — вы можете использовать его для сборки своего модуля. А можете написать свою систему сборки для своих модулей.
ExtUtils::MakeMaker (a.k.a. EUMM)
Особенности:
- требует наличия
make
- есть поддержка графа зависимостей (благодаря использованию
make
)
Недостатки:
- для изменения процесса сборки обычно приходится менять
Makefile
(либо дописывая к нему кусок, либо как-то его преобразуя; более того, это необходимо делать портабельно как в плане форматаMakefile
так и в плане используемых в нём шелл-команд) — что очень сильно всё усложняет- при внесении изменений нужно писать портабельный код
- слишком большой и сложный, никто не хочет его поддерживать и развивать
- к нему сложно писать плагины и сложно подключать одновременно несколько плагинов
Достоинства:
- самый гибкий из всех альтернатив, поэтому в сложных случаях приходится использовать исключительно EUMM
Module::Build (a.k.a. MB)
Особенности:
- для работы достаточно perl, не нужен ни
make
ни знание как писать портабельныйMakefile
- нет поддержки графа зависимостей (что от чего зависит при сборке)
- убирают из core (модулей распространяемых вместе с perl) — что ни на что не повлияет (спасибо configure_requires), но вызвало волну FUD; на самом деле никаких новых причин его избегать не появилось, и если старые причины вас не останавливали — то продолжайте спокойно им пользоваться и дальше
Недостатки:
- слишком большой и сложный, никто не хочет его поддерживать и развивать
- из-за архитектуры схожей с EUMM (для расширения нужно писать код, который будет использоваться для генерации другого кода, который уже будет выполняться) у него та же проблема — сложно писать плагины и сложно подключать одновременно несколько плагинов (недавно появился Module::Build::Pluggable, который пытается решить вторую половину этой проблемы)
Достоинства:
- использовать и, в небольших объёмах, расширять значительно проще, чем EUMM
Module::Install (a.k.a. MI)
Особенности:
- обёртка над EUMM
Недостатки:
- пытался решить проблему отсутствия в то время configure_requires копируя себя и все необходимые ему для сборки текущего модуля плагины в
inc/
- что, в свою очередь, создало новые проблемы (а сейчас и вовсе потеряло смысл) — от необходимости перевыпускать свой модуль для исправления бага в идущей в комплекте с ним версии MI до неудобств при использовании VCS из-за того, что в репозитории постоянно обновляется код относящийся к MI
Достоинства:
- простой и наглядный интерфейс
Несмотря на единодушную нелюбовь сообщества к EUMM и Module::Build, у меня сложилось впечатление что Module::Install в последнее время вообще перестали воспринимать всерьёз — создаваемые им время от времени проблемы перевесили его достоинства.
Module::Build::Tiny (a.k.a. MBT)
Особенности:
- эксперимент, показавший что можно сделать систему сборки на перле достаточную для большинства модулей всего в 120 строчках кода
Ваш Build.PL
выглядит так:
use 5.008001; # only if you need it
use Module::Build::Tiny;
Build_PL();
Как ни странно, но этим даже можно пользоваться — используя файл cpanfile для управления зависимостями и вспомогательную утилиту mbtiny для авторинга (генерации Build.PL
, MANIFEST
и META.{json,yml}
, подготовки архива с модулем — того, что делал Module::Build и что не относится к процессу сборки модуля). Либо использовать Dist::Zilla вместо mbtiny
(кстати, Dist::Milla и Minilla используют MBT — для таких навороченных систем как раз очень удобно, когда система сборки делает только своё дело и не берёт на себя «лишние» задачи).
Управление зависимостями / Dependencies
cpanfile
Это подход, при котором зависимости указываются отдельно от системы сборки, в файле cpanfile
. Есть несколько причин это делать:
- Если вы используете разные системы сборки в разных модулях, то использование cpanfile позволит забыть об отличиях синтаксиса (и ограничениях — EUMM и Module::Install пока не полностью поддерживают CPAN::Meta::Spec 2.0) разных систем сборки и использовать один формат для всех (кстати, совместимый с форматом Module::Install).
- Этим же способом можно задавать зависимости не только для перл-модулей, но и для обычных приложений (у которых обычно нет
Makefile.PL
илиBuild.PL
и зависимости указывать просто негде) — собственно, именно ради этой возможности cpanfile и был разработан. Причём можно задать для отдельной зависимости альтернативный источник, откуда её брать — из приватного CPAN mirror, из git, etc. - Можно устанавливать все зависимости через
cpanm --installdeps .
или carton безMETA.{json,yml}
файлов. - При использовании Module::Install можно не держать в репозитории
inc/
иMETA.{json,yml}
и корректно указывать зависимость от Module::Install как «develop» (author_requires) а не «configure» (configure_requires). При этом другие разработчики, у которых не установлен Module::Install, смогут его установить черезcpanm --with-develop --installdeps .
илиcarton
.
Управление версиями / VCS
В случае перл-модулей нужно иметь в виду, что в репозитории нужно, с одной стороны, хранить все необходимые для сборки модуля файлы (чтобы его можно было устанавливать прямо из репозитория через cpanm
и чтобы после форка другие разработчики получили рабочую версию проекта), а с другой избежать замусоривания его лишними авто-генерируемыми файлами (например, файлами Module::Install в inc/
) — вам ведь их commit-ить постоянно, плюс они будут замусоривать diff, etc. Особенно это касается пользователей Dist::Zilla — если вы хотите получать pull-request-ы то не стоит требовать чтобы желающие пофиксить вам какую-то мелочь были вынуждены устанавливать 150-200 дополнительных модулей для запуска сборки проекта.
GitHub
При использовании GitHub вам скорее всего придётся либо писать дополнительное описание модуля в README.md
, либо настроить автоматическую генерацию этого файла из POD-документации модуля. И во втором случае может потребоваться добавлять дополнительные элементы - например, статус сборки проекта в Travis CI.
Непрерывная интеграция / CI
CPAN Testers
До апреля 2013 CPAN Testers не поддерживал отдельное указание test_requires (зависимостей необходимых только для запуска тестов). При этом системы сборки уже давно давали возможность их указывать… но это не работало. В результате некоторые разработчики модулей сильно огорчались, выпускали новую версию без всяких умных test_requires и забывали про эту фичу. Так вот, уже можно! Подробности поддержки test_requires разными версиями систем сборки.
В принципе, сервис CPAN Testers покрывает основные потребности, но у него есть один недостаток: тестирование происходит уже после релиза. Чтобы прогнать модуль через CPAN Testers до релиза нужно выпускать специальные alpha-версии — и всё-равно это релиз, да и работает CPAN Testers не так уж быстро.
GitHub + Travis CI
Подключив к репозиторию с модулем на GitHub Travis CI можно автоматизировать тестирование текущей версии модуля до релиза на нескольких версиях perl (хоть это и не так круто в плане разных платформ как CPAN Testers, но всё-таки лучше, чем запускать тесты только у себя на машине).
Выпуск / Release
App::scan_prereqs_cpanfile
Предоставляет команду scan-prereqs-cpanfile для анализа зависимостей модуля и генерирования cpanfile
или вывода отличий от текущего cpanfile
(если он модифицировался вручную и просто сгенерировать его заново это не лучшая идея).
Perl::Version
Предоставляет команду perl-reversion для изменения номера версии в (почти) всех файлах модуля.
Поддерживает README
, но не README.md
.
CPAN::Uploader
Предоставляет команду cpan-upload для заливания модулей на CPAN из командной строки. Конфиг-файл ~/.pause
с логином/паролем для PAUSE может быть зашифрован GnuPG.
GitHub
К сожалению, GitHub пока не умеет автоматически заливать перл-модули на CPAN (хотя, наверное, технически правильнее будет сказать, что это CPAN не умеет выкачивать модули с GitHub) при добавлении тега для новой версии (как это происходит, например, с плагинами для jQuery). Но я всё-равно оставлю этот пункт здесь, вдруг его увидят нужные люди и добавят фичу. ☺
Поддержка / Support
CPAN RT
Баг-трекер CPAN много лет был единственным доступным вариантом. Учитывая его неудобный интерфейс это было очень печально. С другой стороны, им можно пользоваться даже если вы не используете VCS при разработке модуля.
К счастью, сейчас есть возможность указать в META.{json,yml}
(не ручками, конечно, а через используемую систему сборки) альтернативный баг-трекер (например на GitHub). К сожалению, хотя при этом изменятся ссылки на баг-трекер на сайтах CPAN и MetaCPAN, это не отключит возможность добавлять тикеты для вашего модуля на CPAN RT (но там показывается уведомление, что предпочитаемый баг-трекер в другом месте). Разумеется, после изменения баг-трекера текущие баги остаются в RT.
GitHub
Не буду описывать преимущества и удобство поддержки проектов на GitHub (особенно бросающиеся в глаза по сравнению с CPAN RT). Тем более, что даже если не нравится Git, то можно без проблем локально работать с Mercurial и всё-равно держать проект на GitHub (через плагин hg-git).
Если вы захотите переместить текущие тикеты из CPAN RT в GitHub Issues - можете попробовать воспользоваться rt-to-github.pl или этой модификацией его старой версии.
Авторинг / Authoring
В этом разделе будут описаны утилиты полностью берущие на себя процесс авторинга модулей, зачастую используя при этом вышеописанные утилиты решающие отдельные подзадачи авторинга.
У меня есть два сервера, один только что установлен, там всего 27 CPAN-модулей, на втором много лет разрабатывается много перл-проектов, там установлено 248 CPAN-модулей. Я подсчитал, сколько приходится установить дополнительных CPAN-модулей на каждом из серверов для описанных в этом разделе утилит:
- Dist::Zilla (без дополнительных плагинов) требует 162 модуля на первом и 83 на втором сервере.
- Dist::Milla (фактически, подборка плагинов для Dist::Zilla) требует 257 и 166 модулей.
- Minilla (которая декларирует минимум зависимостей как одно из основных преимуществ) — 126 и 41 модуль.
- ShipIt — 1 и 1.
- App::ModuleBuildTiny — 8 и 6.
Dist::Zilla
Это настоящий монстр. Он делает всё! На CPAN сейчас порядка 900 модулей входящих в 480 дистрибутивов расширяющих возможности Dist::Zilla. Из этих 480 дистрибутивов 315 это плагины (Dist::Zilla::Plugin::*), и ещё 100 - разные подборки этих плагинов (Dist::Zilla::PluginBundle::*).
Есть только две проблемы: сколько дней нужно потратить, чтобы он начал делать то, что нужно лично вам, и количество модулей, которые требуется установить чтобы им воспользоваться.
По первой проблеме — ничего не могу сказать. Я не рискнул связываться и пытаться его настроить под себя. Кто это сделал — поделитесь впечатлениями в комментариях.
Вторая проблема тоже достаточно важна — если вы хотите получать патчи и pull-request-ы к своему модулю, необходимо, чтобы желающие внести в него изменения могли сделать это достаточно просто. Если им для исправления пары строк нужно будет установить половину CPAN (автор утверждает что не половину, а всего 0.6%) и разбираться с нестандартным процессом сборки - патч вы не дождётесь.
Dist::Milla
Особенности:
- просто подборка плагинов для Dist::Zilla и утилита-обёртка
- используется лицензия Perl, для изменения замените её другой в POD
- нет автоматического определения и обновления зависимостей, их нужно описывать вручную в
cpanfile
- можно воспользоваться
scan-prereqs-cpanfile --diff=cpanfile
чтобы быстро найти все новые подключенные модули, которые ещё не добавлены вcpanfile
- можно воспользоваться
- можно выбрать какая система сборки будет использоваться: Module::Build::Tiny (по умолчанию), Module::Build или EUMM, но я не уверен, что можно воспользоваться всеми возможностями выбранной системы сборки —
Build.PL
редактировать смысла нет, он при каждой сборке генерируется заново
Недостатки (по сравнению с Dist::Zilla):
- ещё большее количество зависимостей, которые нужно установить… но это, в значительной мере, компенсируется тем, что можно сэкономить несколько дней на составление своей подборки плагинов, которая ещё не факт что оказалась бы меньше
- впрочем, как только захочется добавить новую фичу, например вывод badge с отчётом Travis CI в README.md — всё-равно нужно будет искать и подключать дополнительный плагин Dist::Zilla
- вроде бы XS-модули не поддерживаются (вероятно, нужно будет подключать дополнительный плагин)
Достоинства:
- многие популярные плагины Dist::Zilla модифицируют код и/или документацию модуля (или зависят от плагинов, которые это делают), заставляя вас изменять свой рабочий процесс — таких плагинов в Dist::Milla принципиально нет: ваш код и документацию изменяете только вы сами (исключая обновление
$VERSION
при релизе)- вместо того, чтобы изменять код/документацию на основании заданных мета-данных, Dist::Milla работает в обратном направлении, вычисляя мета-данные на основании кода, документации и репозитория — как это всегда делали системы сборки вроде Module::Install или Module::Build
- в отличие от большинства модулей использующих Dist::Zilla, в разработке модулей использующих Dist::Milla могут легко участвовать сторонние разработчики — им не нужно устанавливать себе Dist::Zilla или разбираться с нестандартным процессом сборки, ваш модуль выглядит, собирается, тестируется и устанавливается как все обычные модули
- в частности, ваш модуль можно устанавливать прямо из GitHub
- нет необходимости тратить несколько дней на подбор и настройку своего набора плагинов для Dist::Zilla, можно начать сразу использовать достаточно неплохой стартовый набор, и в дальнейшем его модифицировать по мере необходимости
- поддержка миграции существующего модуля использующего другую систему сборки или авторинга на Dist::Milla
Minilla
Особенности:
- работает практически идентично Dist::Milla с настройками по умолчанию
Недостатки:
- практически не настраивается
Достоинства:
- совместим со стандартным процессом сборки/установки модуля
- не использует Dist::Zilla
- значительно меньше зависимостей, чем у Dist::Milla
- поддерживает XS
- поддержка миграции существующего модуля использующего другую систему сборки или авторинга на Minilla
Если вы делаете авторинг практически так же, как Tokuhiro Matsuno (автор Minilla), либо если вам всё-равно как именно делается авторинг, главное чтобы всё работало само из коробки достаточно современным образом (т.е. с использованием git и GitHub) и не требовало установки дикого количества модулей — Minilla вам идеально подойдёт. Если же потребуется что-то делать иначе — придётся искать ему замену (вероятнее всего ей окажется Dist::Milla).
ShipIt
Позволяет одной командой shipit
выполнить большинство операций, требуемых при выпуске новой версии.
В каталоге модуля создаётся файл .shipit
, примерно такой:
steps = FindVersion, ChangeVersion, CheckChangeLog, DistTest, Commit, Tag, MakeDist, UploadCPAN
и теперь при запуске shipit
будут выполнены указанные в .shipit
операции:
- у вас спросят номер новой версии
- новая версия пропишется в коде модуля
- проверит наличие записи в
Changes
и предложит её добавить - запустит тесты (поддерживает
Makefile.PL
иBuild.PL
) - сделает commit (поддерживает Git/Mercurial/SVN)
- добавит tag для новой версии
- подготовит архив с модулем
- зальёт архив на CPAN
Все доступные операции оформлены в виде плагинов, так что на CPAN полно дополнительных модулей (генерация README
из POD, обновление версии в POD, прописывание новой версии в коде каждого модуля, анонсы в соц.сети, …).
Не понятно, будет ли ShipIt поддерживаться — он уже пару лет не обновлялся, а его автор сейчас активно работает над Dist::Milla и описывает миграцию с ShipIt на Dist::Milla. На мой взгляд ShipIt делает практически всё необходимое, и при этом он очень маленький, простой, расширяемый и без зависимостей. Не знаю, что в нём не устроило автора, и почему он решил делать обёртку для Dist::Zilla вместо дописывания недостающей функциональности плагинами для ShipIt. По мнению автора Dist::Zilla (который активно использовал ShipIt до того как разработать Dist::Zilla) основная проблема ShipIt — сложность и недостаточная гибкость расширения его плагинами. Надо признать, эту проблему Dist::Zilla действительно решил более чем основательно.
App::ModuleBuildTiny
Долго думал, стоит ли вообще включать его в статью. Функциональность у него рудиментарная, текущая версия 0.005, год его никто не обновлял… но буквально на днях автор им активно занялся, и кроме того он необходим для использования Module::Build::Tiny напрямую, не через Dist::Zilla или Minilla.
Это не похоже на утилиту для авторинга, по крайней мере если сравнить его возможности с вышеописанными утилитами. Но автор его назвал «A standalone authoring tool», значит будем рассматривать её в этом разделе. С учётом его крайне ограниченных возможностей попробуем использовать вместе с ним другие мелкие утилиты (описанные в следующих разделах) в попытке получить полную функциональность авторинга без Dist::Zilla.
Для начала — самый минималистичный способ создать модуль для CPAN:
mkdir -p Example-MBtiny/lib/Example/
cd Example-MBtiny
vi lib/Example/MBtiny.pm
mbtiny dist
В результате получаем Example-MBtiny-$VERSION.tar.gz
который можно заливать на CPAN. Никаких других файлов в каталоге с модулем больше нет - только созданный нами lib/Example/MBtiny.pm
и этот архив.
Теперь создадим (или сгенерируем какой-нибудь утилитой) все стандартные файлы, которые обычно присутствуют в каждом современном модуле выложенном на GitHub: README.md
, LICENSE
, Changes
, t/*
, .gitignore
, .travis.yml
а так же создадим репозиторий, добавим туда все эти файлы и зальём на GitHub.
Следующий вопрос — в каком стиле использовать mbtiny
:
- Если вызывать только
mbtiny test
иmbtiny dist
, то необходимые для сборки, тестирования и установки файлыBuild.PL
,MANIFEST
иMETA.{json,yml}
будут генерироваться на лету и удаляться по завершению операции. Безусловно, они будут присутствовать в созданном архиве для заливания на CPAN, но их не будет в репозитории — что сделает невозможным установку модуля черезcpanm
прямо из репозитория и может озадачить сторонних разработчиков которые хотели бы что-то изменить и прислать pull-request. - Альтернативный вариант — вызвать
mbtiny regenerate
для созданияBuild.PL
,MANIFEST
иMETA.{json,yml}
и добавить их в репозиторий. При изменении версии модуля, добавлении новых файлов, или изменении зависимостей — будет необходимо снова вызывать эту команду.
При использовании GitHub нужно добавить в проект metamerge.json
, его содержимое будет учитываться при генерации META.{json,yml}
:
{
"resources" : {
"bugtracker" : {
"web" : "https://github.com/powerman/Example-MBtiny/issues"
},
"homepage" : "https://github.com/powerman/Example-MBtiny",
"repository" : {
"type" : "git",
"url" : "git://github.com/powerman/Example-MBtiny.git",
"web" : "https://github.com/powerman/Example-MBtiny"
}
}
}
При релизе новой версии пригодятся дополнительные утилиты:
# update dependencies
scan-prereqs-cpanfile >cpanfile
# ... update META.* from cpanfile if you added META.* into the repo
mbtiny regenerate
# build & test
mbtiny test
# update version everywhere
ver=1.2.3
perl-reversion -set $ver
# don't forget to update version & date
vi Changes
# regenerate README.md with badges
cp BADGES.md README.md
pod2markdown lib/Example/MBtiny.pm >> README.md
# release
git commit -a -m "release $ver"
git tag $ver
git push
mbtiny dist
cpan-upload Example-MBtiny-$ver.tar.gz
Как видите, выполнять всё это каждый раз вручную — не лучшая идея, что-то забудешь, где-то ошибёшься. Но оформить это скриптом не сложно. Двух таких простых скриптов (этого, и создающего скелет нового модуля по шаблону) вполне достаточно для авторинга современных модулей без Dist::Zilla.
Резюме
- если нет острой необходимости поддерживать старые версии перла, на мой взгляд, в модулях стоит по умолчанию использовать
use 5.010001;
- версию задавать используя формат
our $VERSION="v1.2.3";
- соответствовать спецификации семантического версионирования настолько, насколько возможно в перле
- для альфа-версий добавлять после версии в имени архива с модулем
"-TRIAL"
вместо использования подчёркиваний в номере версии
- в качестве системы сборки использовать Module::Build::Tiny или Module::Build (только если не хватает возможностей MBT)
- для управления зависимостями использовать
cpanfile
- держать модуль на GitHub, указать ссылки на GitHub в
META.json
- использовать Travis CI
Что же касается выбора утилиты для авторинга — здесь сложно дать однозначную рекомендацию. Если выбирать среди не заброшенных:
- Minilla, если работа по умолчанию устраивает и нет потребности как-то его настраивать
- Dist::Milla, если нравится Minilla но хочется что-то настроить, либо хочется начать использовать Dist::Zilla с достаточно адекватной и документированной подборки плагинов
- App::ModuleBuildTiny, если хочется быстро сделать свой велосипед, простой и достаточно гибко настраиваемый
Разные полезности для авторов модулей
- What are the files in a CPAN distribution?
- The Annotated Lancaster Consensus
- CPAN Authors FAQ
- Kwalitee indicators
- How to convince Meta CPAN to show a link to the version control system of a distribution?
- Minilla — система подготовки дистрибутивов для CPAN @ Pragmatic Perl #14
______________________
Текст конвертирован используя habrahabr backend для AsciiDoc.
Автор: powerman